feat: pending identity sorting, face detail modal, video player fps, processor counts
This commit is contained in:
137
src/store.ts
137
src/store.ts
@@ -15,6 +15,36 @@ export const thumbnailsCache = ref<Record<string, string>>({})
|
||||
export const profilesCache = ref<Record<string, string>>({})
|
||||
export const faceThumbsCache = ref<Record<string, string>>({})
|
||||
|
||||
export interface ProcessorOutputInfo {
|
||||
has_json: boolean
|
||||
frame_count: number | null
|
||||
segment_count: number | null
|
||||
chunk_count: number | null
|
||||
last_modified: string | null
|
||||
}
|
||||
|
||||
export interface ProcessorProgress {
|
||||
processor_type: string
|
||||
status: 'pending' | 'running' | 'complete' | 'failed'
|
||||
progress: number
|
||||
current?: number
|
||||
total?: number
|
||||
eta_seconds?: number
|
||||
}
|
||||
|
||||
export interface FileProgress {
|
||||
file_uuid: string
|
||||
overall_progress: number
|
||||
processors: ProcessorProgress[]
|
||||
cpu_percent?: number
|
||||
gpu_percent?: number
|
||||
memory_percent?: number
|
||||
}
|
||||
|
||||
export const processorCountsCache = ref<Record<string, Record<string, ProcessorOutputInfo>>>({})
|
||||
export const fileProgressCache = ref<Record<string, FileProgress>>({})
|
||||
export const fileStatusCache = ref<Record<string, string>>({})
|
||||
|
||||
const thumbQueue: (() => Promise<void>)[] = []
|
||||
let activeThumbLoads = 0
|
||||
const MAX_CONCURRENT = 16
|
||||
@@ -26,6 +56,8 @@ const MAX_PROFILE_CONCURRENT = 4
|
||||
const loadingThumbs = new Set<string>()
|
||||
const loadingProfiles = new Set<string>()
|
||||
const loadingFaceThumbs = new Set<string>()
|
||||
const loadingProcessorCounts = new Set<string>()
|
||||
const pollingProgress = new Set<string>()
|
||||
|
||||
function drainThumbQueue() {
|
||||
if (activeThumbLoads >= MAX_CONCURRENT || thumbQueue.length === 0) return
|
||||
@@ -203,6 +235,111 @@ export function loadFaceThumb(key: string, uuid: string, frame: number, bbox?: a
|
||||
})
|
||||
}
|
||||
|
||||
export async function loadProcessorCounts(fileUuid: string, force = false) {
|
||||
if (!fileUuid) return
|
||||
if (!force && processorCountsCache.value[fileUuid]) return
|
||||
if (loadingProcessorCounts.has(fileUuid)) return
|
||||
loadingProcessorCounts.add(fileUuid)
|
||||
try {
|
||||
const data: any = await apiCall('get_processor_counts', { uuid: fileUuid })
|
||||
const counts: Record<string, ProcessorOutputInfo> = {}
|
||||
for (const p of data.processors || []) {
|
||||
counts[p.processor] = {
|
||||
has_json: p.has_json ?? false,
|
||||
frame_count: p.frame_count ?? null,
|
||||
segment_count: p.segment_count ?? null,
|
||||
chunk_count: p.chunk_count ?? null,
|
||||
last_modified: p.last_modified ?? null,
|
||||
}
|
||||
}
|
||||
processorCountsCache.value = { ...processorCountsCache.value, [fileUuid]: counts }
|
||||
} catch (e) {
|
||||
console.error('loadProcessorCounts failed:', fileUuid, e)
|
||||
} finally {
|
||||
loadingProcessorCounts.delete(fileUuid)
|
||||
}
|
||||
}
|
||||
|
||||
export function getProcessorCounts(fileUuid: string): Record<string, ProcessorOutputInfo> {
|
||||
return processorCountsCache.value[fileUuid] || {}
|
||||
}
|
||||
|
||||
export async function pollProgress(fileUuid: string) {
|
||||
if (!fileUuid || pollingProgress.has(fileUuid)) return
|
||||
pollingProgress.add(fileUuid)
|
||||
try {
|
||||
while (pollingProgress.has(fileUuid)) {
|
||||
const data: any = await apiCall('get_progress', { fileUuid })
|
||||
fileProgressCache.value[fileUuid] = {
|
||||
file_uuid: data.file_uuid || fileUuid,
|
||||
overall_progress: data.overall_progress || 0,
|
||||
processors: (data.processors || []).map((p: any) => ({
|
||||
processor_type: p.processor_type,
|
||||
status: p.status,
|
||||
progress: p.progress || 0,
|
||||
current: p.current,
|
||||
total: p.total,
|
||||
eta_seconds: p.eta_seconds,
|
||||
})),
|
||||
cpu_percent: data.cpu_percent,
|
||||
gpu_percent: data.gpu_percent,
|
||||
memory_percent: data.memory_percent,
|
||||
}
|
||||
const allComplete = data.processors?.every((p: any) => p.status === 'complete' || p.status === 'failed')
|
||||
if (allComplete || data.overall_progress >= 100) {
|
||||
stopPolling(fileUuid)
|
||||
fileStatusCache.value[fileUuid] = 'completed'
|
||||
await loadProcessorCounts(fileUuid)
|
||||
break
|
||||
}
|
||||
await new Promise(r => setTimeout(r, 2000))
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('pollProgress failed:', fileUuid, e)
|
||||
} finally {
|
||||
pollingProgress.delete(fileUuid)
|
||||
}
|
||||
}
|
||||
|
||||
export function stopPolling(fileUuid: string) {
|
||||
pollingProgress.delete(fileUuid)
|
||||
}
|
||||
|
||||
export function getProgress(fileUuid: string): FileProgress | null {
|
||||
return fileProgressCache.value[fileUuid] || null
|
||||
}
|
||||
|
||||
export function getFileStatus(fileUuid: string): string {
|
||||
return fileStatusCache.value[fileUuid] || ''
|
||||
}
|
||||
|
||||
export async function refreshFileStatus(fileUuid: string) {
|
||||
try {
|
||||
const data: any = await apiCall('get_progress', { fileUuid })
|
||||
if (data.overall_progress >= 100 || data.processors?.every((p: any) => p.status === 'complete')) {
|
||||
fileStatusCache.value[fileUuid] = 'completed'
|
||||
await loadProcessorCounts(fileUuid)
|
||||
} else if (data.processors?.some((p: any) => p.status === 'running')) {
|
||||
fileStatusCache.value[fileUuid] = 'processing'
|
||||
fileProgressCache.value[fileUuid] = {
|
||||
file_uuid: fileUuid,
|
||||
overall_progress: data.overall_progress || 0,
|
||||
processors: data.processors || [],
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('refreshFileStatus failed:', fileUuid, e)
|
||||
}
|
||||
}
|
||||
|
||||
export async function refreshAllFilesStatus() {
|
||||
for (const f of filesCache.value) {
|
||||
if (f.isRegistered && f.file_uuid) {
|
||||
await refreshFileStatus(f.file_uuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function invalidateFiles() {
|
||||
filesLoaded.value = false
|
||||
filesCache.value = []
|
||||
|
||||
Reference in New Issue
Block a user