# scene-actor-extraction A face-recognition pipeline that finds when each actor appears on screen in a film or TV episode — built on [KPN++](https://gitea.tourolle.paris/dtourolle/KPN) (a C++20 Kahn Process Network library) for the detect → track → match → scene pipeline, with a Jellyfin-integrated gallery and an X-Ray-validated optimizer. This is what a good second looks like — one sampled frame from a held-out film, 19 faces named, all 19 correct, the rest honestly declared unknown: ![19 correct identifications in one wedding shot, Downton Abbey: A New Era](assets/images/downton_wedding_19_correct.jpg) And this is why the work isn't done: on this same film the same config misses 6 in 10 of the actor-seconds X-Ray says are present, and on the worst held-out film it reports ghost actors over empty walls — at 100% confidence. Both stories, with the evidence, are in the pages below. ## Start here — four questions this bake-off answers - **[Which model is best?](best-model.md)** — calibration curves first (discriminative power, independent of any threshold), then F1 on the actual benchmark. LVFace-B Glint360K wins both. - **[Whole gallery vs. limited (cast-restricted) gallery](gallery-scope.md)** — restricting the matcher to a film's credited cast is a clean win on every axis (+3.3pp F1, less than a third the misIDs), but isn't a shipped runtime feature yet. - **[Does pose expansion help?](pose-expansion.md)** — a real training-set effect that didn't reproduce on 5 held-out films once two methodology bugs were caught and fixed. An honest null result, not a forced narrative. - **[Deep dive: LVFace-B Glint360K](lvface-deep-dive.md)** — the winning model's held-out generalization gap, its two real failure modes (frozen-bbox "ghost tracks"), and one case where it correctly identified an actor that the X-Ray ground truth itself failed to credit. ## The full technical log - **[Model bake-off + threshold re-tune](model-bakeoff.md)** — the complete experiment log behind the four pages above: the ROCm teardown deadlock root cause and fix, DE concurrency tuning, the full 16-combo results table, and every caveat. This is where the shipped [`src/config.hpp`](https://REPOLINK/src/config.hpp) defaults come from. - **[Optimizer experiments (prior round)](optimizer-experiments.md)** — the earlier scene-union-metric tuning pass, superseded by the per-second metric used in the bake-off but kept for the ground-truth/architecture background. - **[Service conversion (proposal)](service-conversion.md)** — design sketch for an idle-GPU Docker worker, not yet built. ## Reproducing the benchmarks Gallery `.h5` files, embedding dumps, the X-Ray corpus, montage frame images, and DE trajectories are not committed to this repository — they're pushed to the Gitea package registry and pulled on demand: ```bash scripts/artifacts/pull_artifacts.sh galleries scripts/artifacts/pull_artifacts.sh experiment-data scripts/artifacts/pull_artifacts.sh montage-frames ``` See [`scripts/artifacts/push_artifacts.sh`](https://REPOLINK/scripts/artifacts/push_artifacts.sh) for the upload side (requires a `GITEA_TOKEN` with package write scope).