Skip to content

Reference

fxdub-dialogue <scene.json> <words.json> [--only-speaker NAME] [--json OUT] [--debug]
ArgumentMeaning
sceneAuthored scene JSON. See Scene scripts.
wordsWord-level diarized transcript JSON.
--only-speaker NAMENarrow the contract to one character — the mode for per-character stems. Case-sensitive.
--json OUTWrite the full receipt.
--debugRe-raise on error instead of printing the structured shape.

line_present:N:SPEAKER · no_invented_speech · no_overlap · no_internal_straggle · turn_gaps · one_voice_per_character · characters_are_distinct · fits_clip

codeCause
scene_not_foundno file at the scene path
scene_malformedscene is not valid JSON
empty_contractthe scene has no lines
unknown_speaker--only-speaker names a character absent from the scene
words_not_foundno file at the transcript path
words_malformedtranscript is not valid JSON
receipt_unwritable--json path is not writable
fxdub-receipt <run_dir> [--bed-gain-db N] [--json OUT] [--debug]
ArgumentMeaning
run_dirDirectory holding the downloaded artifacts.
--bed-gain-db NMix gain applied to the bed, in dB. Required for a correct ducking figure. Default -9.0.
--json OUTWrite the full receipt.

Matched by filename_prefix stem, whatever counter suffix the platform appends:

mix*.flac stem_bed*.flac stem_vo*.flac
mix_lufs*.txt vo_lufs*.txt bed_lufs*.txt
caption*.txt dubbed*.mp4

The bed_lufs manifest is required — R128 gates a quiet bed out of the mix master, so ducking depth is unmeasurable without a meter on the bed stem.

ConstantValue
Runtime sample rate48 000 Hz
Target loudness−18.0 LUFS, ±2.0
Dialogue over bed8–20 LU
CodeMeaning
0every check passed
1contract failure — a finding, with a receipt to read
2runtime error — the tool could not run

3 (partial success) is unused: a receipt is all-or-nothing, and there is no partial verification.

from fxdub import audition_receipt, dialogue_receipt, media_probe, vo_graphs
FunctionReturns
check_dialogue(scene, words, only_speaker=None){"checks": [...], "measured": {...}}
align(scene_lines, words)(matched, unconsumed) — per-line spans, and every token no line claimed
normalize_words(raw)coerce raw node output into the internal word shape
load_words(path)the same, from disk
normalize(text)comparable word tokens
render(result)the markdown table

check_dialogue accepts raw transcript JSON directly — no conversion step needed.

FunctionReturns
check_run(run_dir, bed_gain_db=-9.0){"checks": [...], "measured": {...}}
render(result)the markdown receipt

Never raises on a bad artifact — a malformed file is a failed check, not a crash.

FunctionReturns
parse_streaminfo(data)FLAC sample rate, channels, bit depth, total samples
probe_mp4(data)track handlers, frame count, duration, header validity
parse_lufs(text)the float out of a loudness manifest

Standard library only — no ffprobe subprocess.

See Graph builders. Every function returns an API-format dict; none of them submit.

Python 3.10+ on any OS. CI runs 3.10 and 3.12 on Linux. There is no compiled extension, no subprocess, and no network call, so platform differences are limited to path handling.

No network egress, no telemetry, no credential access, zero runtime dependencies — and CI fails the build if that dependency list ever becomes non-empty. Full threat model in SECURITY.md.