Timing Compare (Phase 0): dubtitle-vs-subtitle timing + VAD analysis tool #3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/timing-compare"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Phase-0 analysis tool (
tools/timing_compare.py) that compares Whisper dubtitle card timingagainst the embedded human-timed dialogue subtitle cues — to measure timing alignment and quantify how
many silence/music hallucinations leak into the output, and (the key part) to distinguish those from
real dub-only lines the subs omit via an independent audio VAD. Read-only, GPU-free, non-invasive —
it changes nothing about how dubtitles are generated. Design brainstormed + panel-reviewed
(
specs/timing-compare/).What's in it
dialogue_intervalsfromrepair.py→common.pyasdialogue_intervals(video, stream_indices=None); adddialogue_event_count,dialogue_density_score,is_dialogue_event.repair.pyre-imports — pinned identical by tests.tools/timing_compare.py: CLI; conf.json load + hardening; dialogue-track auto-selection;RANSAC offset+drift linear fit (handles PAL/framerate drift, not just a constant offset);
slack-aware on-cue/in-gap classification.
tools/vad.py: independent CPU VAD (webrtcvad + ffmpeg-silencedetect fallback, both guarded);probes the dub audio at each in-gap card's un-aligned Whisper timebase → splits
in_gap_silent(confident hallucination) vs
in_gap_speech(real dub-only line a naive gate would drop).applicability_ratio,false_in_gap_rate(the Phase-1 gate-safety headline), band buckets matching
hallucination.py, null-safe aggregates.webrtcvadadded as an optionalanalysisextra +Dockerfile.builder(won't affect core install).Notable decisions (from the multi-model panel consult)
PAL 25↔23.976 sources.
VAD is what makes the eventual Phase-1 gate safe.
kept_in_gapframed as a "leaked-past-B1" floor (survivorship); Phase-1 trigger recalibrated tofalse_in_gap_rate, not %-on-cue.Test plan
pytest -q→ 334 passed (193 → 334; +141 across 4 units, all pure-function/hermetic). Run viartk proxy python -m pytest tests/.ruff check .→ 0 whole-tree.tools/timing_compare.py --helpimports clean, GPU-free (no
faster_whisper).webrtcvad(no py3.14wheel here), and the ffmpeg audio/sub extraction seams. That run sets the Phase-1
false_in_gap_ratethreshold and is where the tool proves out on real data.🤖 Generated with Claude Code
main() built the --lang set with `if s.strip()`, dropping the blank token that common.SUB_LANGS's default ("eng,en,und,") includes. common.eng_sub_streams treats an untagged subtitle stream's language as "", so this tool was stricter than the rest of the pipeline and wrongly marked untagged-only episodes as no-reference, inflating U4's applicability_ratio no-reference count. Mirror common.SUB_LANGS's construction (no strip-filter) so the default and any explicit --lang keep "" the same way, and add regression tests covering both.