feat: add face_cluster processor support to LibraryView

Core Changes (P0):
- Add 'face_cluster' to processors array (2 locations)
- Add data.clusters branch to getJsonCount()
- Add FACE_CLUSTER to QC Pipeline Stage 2 filter

Additional Changes (P1):
- Add Face Cluster UI to context menu
- Add procFaceCluster ref and selectedProcessors()

Backend: Always-Produce rule ensures face_cluster.json always exists
Ref: /Users/accusys/momentry_core/docs_v1.0/GUIDES/QC_FaceCluster_Support.md
This commit is contained in:
2026-07-24 20:52:27 +08:00
parent 5951aca086
commit 2af8ffaf93

View File

@@ -190,6 +190,12 @@
<span class="ms-proc-count" @click.stop="viewProcessorJson('asrx')">{{ procCountLabel('asrx', 'segment') }}</span>
<button class="ms-proc-redo" @click.stop="redoProcessor('asrx')" title="Re-run ASRX">🔄</button>
</div>
<div class="ms-proc-line" :class="procStatusClass('face_cluster')">
<label class="ms-fm-check-label"><input type="checkbox" v-model="procFaceCluster"> Face Cluster</label>
<span class="ms-proc-status">{{ procStatusIcon('face_cluster') }}</span>
<span class="ms-proc-count" @click.stop="viewProcessorJson('face_cluster')">{{ procCountLabel('face_cluster', 'frame') }}</span>
<button class="ms-proc-redo" @click.stop="redoProcessor('face_cluster')" title="Re-run Face Cluster">🔄</button>
</div>
<div class="ms-proc-line" :class="procStatusClass('face')">
<label class="ms-fm-check-label"><input type="checkbox" v-model="procFace"> Face</label>
<span class="ms-proc-status">{{ procStatusIcon('face') }}</span>
@@ -457,7 +463,7 @@
<div class="ms-qc-arrow"></div>
<div class="ms-qc-stage-row">
<div v-for="r in qcResults.filter(p => ['ASRX','APPEARANCE'].includes(p.processor))" :key="r.processor" class="ms-qc-node" :class="r.exists ? 'ms-qc-ok' : 'ms-qc-missing'">
<div v-for="r in qcResults.filter(p => ['ASRX','FACE_CLUSTER','APPEARANCE'].includes(p.processor))" :key="r.processor" class="ms-qc-node" :class="r.exists ? 'ms-qc-ok' : 'ms-qc-missing'">
<span class="ms-qc-icon">{{ r.exists ? '✓' : '✗' }}</span>
<span class="ms-qc-proc">{{ r.processor }}</span>
<span class="ms-qc-count">{{ r.size || 0 }}</span>
@@ -847,6 +853,7 @@ const reprocessing = ref(false)
const actionMsg = ref('')
const procAsr = ref(true)
const procAsrx = ref(true)
const procFaceCluster = ref(true)
const procFace = ref(true)
const procOcr = ref(true)
const procPose = ref(true)
@@ -931,6 +938,7 @@ function selectedProcessors(): string[] {
const procs: string[] = []
if (procAsr.value) procs.push('asr')
if (procAsrx.value) procs.push('asrx')
if (procFaceCluster.value) procs.push('face_cluster')
if (procFace.value) procs.push('face')
if (procOcr.value) procs.push('ocr')
if (procPose.value) procs.push('pose')
@@ -1001,13 +1009,13 @@ const jobsList = ref<{id: number, uuid: string, status: string, current_processo
function getJsonCount(data: any, proc: string): number {
if (!data) return 0
// Count items based on processor type
if (data.segments) return data.segments.length
if (data.faces) return data.faces.length
if (data.frames) return data.frame_count || data.frames.length
if (data.chunks) return data.chunks.length
if (data.traces) return data.traces.length
if (data.cuts) return data.cuts.length
if (data.clusters) return data.clusters.length
return 0
}
@@ -1033,7 +1041,7 @@ async function refreshSystemStatus() {
// Load output files for this job
job.outputs = []
const processors = ['cut', 'asr', 'asrx', 'face', 'ocr', 'pose', 'appearance']
const processors = ['cut', 'asr', 'asrx', 'face', 'ocr', 'pose', 'appearance', 'face_cluster']
for (const proc of processors) {
try {
const data: any = await apiCall('get_processor_json', { fileHash: job.uuid, processor: proc })
@@ -1093,7 +1101,7 @@ async function runProcessorQC(f: any) {
qcAudioInfo.value.hasAudio = false
}
const processors = ['cut', 'asr', 'asrx', 'face', 'ocr', 'pose', 'appearance']
const processors = ['cut', 'asr', 'asrx', 'face', 'ocr', 'pose', 'appearance', 'face_cluster']
for (const proc of processors) {
const counts = getProcessorCounts(f.file_uuid)