You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Forced aligner: --words-out + fixed chunking throws "timestamp outside the chunk span" at ~the 10th chunk of a process; the same audio passes in a fresh process #249
--words-out (Qwen3 forced aligner) with fixed-mode chunking throws
audiocpp_cli failed: Audio chunker word merge received a timestamp outside the chunk span
at roughly the 9th–10th chunk of a single process, aborting the whole run so no timestamps are
produced for any chunk.
The important part: the same audio passes in a fresh process. The failure needs both
triggering content and enough accumulated per-process state — neither alone is sufficient. That
points at per-call state in the aligner rather than at any particular audio or timestamp value.
This is long-standing, not a regression — release-0.4 fails identically (see below). Please
don't search a recent commit window for it.
main @ f08e61d — src/framework/audio/chunking.cpp:602 is unchanged
Backend
CUDA, RTX 5090 (sm_120), CUDA 13.3
Models
Qwen3-ASR-1.7B-hf + Qwen3-ForcedAligner-0.6B
Input
16 kHz mono WAV (ffmpeg-normalised)
Reproduce
# FAILS at ~chunk 10
./build/bin/audiocpp_cli --task asr --family qwen3_asr \
--model models/Qwen3-ASR-1.7B-hf --backend cuda \
--audio repro-A-150s-fails.wav \
--text-out /tmp/t.txt --words-out /tmp/w.json \
--session-option qwen3_asr.forced_aligner_model_path=models/Qwen3-ForcedAligner-0.6B \
--audio-chunk-mode fixed --audio-chunk-seconds 15
# PASSES -- same length, same chunk count, different content# ... --audio repro-B-150s-PASSES-negative-control.wav ...# PASSES -- same content as A, fewer chunks# ... --audio control-60s-passes.wav ...
What isolates it to per-process state, not the audio
The same 15 s of audio (135–150 s of repro-A):
Presented as
Result
chunk 1 of 1 (isolated)
pass
chunk 2 of 2 (120–150 s window)
pass
chunk 10 of 10 (full 150 s)
FAIL
The chunk-count threshold is sharp — tested at 75 / 90 / 105 / 120 / 135 / 150 s, 9 chunks pass,
10 fails. repro-B is the negative control: identical duration and chunk count, different
content, passes.
Consistent with that reading, --audio-chunk-seconds 30 on the same 150 s passes — fewer aligner
invocations per process, not better audio. That is our downstream workaround.
Throw site
src/framework/audio/chunking.cpp:602, in the word-merge path:
constint64_t local_start = std::max<int64_t>(word.span.start_sample, 0);
constint64_t local_end = std::min<int64_t>(word.span.end_sample, source_samples);
if (local_start >= local_end) {
throwstd::runtime_error("Audio chunker word merge received a timestamp outside the chunk span");
}
Two observations, offered as leads rather than conclusions:
A single out-of-span word aborts the entire run. Even once the underlying cause is found, it
may be worth clamping or dropping the offending word (with a warning) instead of throwing — a
40-minute transcription currently loses every timestamp because of one bad span. The adjacent
speech-metadata merge at :637 has the same all-or-nothing shape.
This looks related in family to VibeVoice-ASR: chunked (VAD/fixed) timestamps are in the input sample rate, not the 24 kHz single-pass domain — inconsistent #167 (chunked timestamps in the wrong sample-rate domain),
which was fixed for vibevoice_asr in 0.5 by rate-aware chunking. The qwen3_asr + forced
aligner words path still reaches this throw on 16 kHz input. It may be a surviving corner of the
same domain mismatch — though the sharp chunk-count threshold above suggests state accumulation
is at least as important as any rate conversion.
Ruled out
Two candidate commits were eliminated by testing directly at each one's parent — both still fail 3/3:
Commit
Tested at parent
Verdict
622cadd "Align ASR chunk timestamp domains"
788253b
not the cause
7ce769e "Add Qwen3 ASR streaming path"
80627af
not the cause
We originally filed this internally as a 0.5 regression on the strength of a 3-minute gap between
our last green run and the 0.5 deploy. That was coincidence — the earlier runs used recordings that
do not trigger it.
Coverage note
No regression test appears to cover multi-chunk fixed-mode alignment with --words-out in any
released version — a test that runs ≥10 chunks through one process would catch this.
Fixtures
I have the three 16 kHz WAVs used above (repro-A-150s-fails, repro-B-150s-PASSES-negative-control, control-60s-passes) and can attach them or provide the failing --words-out JSON, chunk-boundary
dump, or any instrumented run that would help. Happy to test a patch on sm_120.
Related: #198 (a different all-or-nothing abort in the same aligner path, from punctuation-only
chunks).
Summary
--words-out(Qwen3 forced aligner) with fixed-mode chunking throwsat roughly the 9th–10th chunk of a single process, aborting the whole run so no timestamps are
produced for any chunk.
The important part: the same audio passes in a fresh process. The failure needs both
triggering content and enough accumulated per-process state — neither alone is sufficient. That
points at per-call state in the aligner rather than at any particular audio or timestamp value.
This is long-standing, not a regression —
release-0.4fails identically (see below). Pleasedon't search a recent commit window for it.
Environment
release-0.5(3178daf), built from sourcerelease-0.4(archived binary, clean 0.4 worktree + 0.4model_specs/), 3/3main@f08e61d—src/framework/audio/chunking.cpp:602is unchangedQwen3-ASR-1.7B-hf+Qwen3-ForcedAligner-0.6BReproduce
What isolates it to per-process state, not the audio
The same 15 s of audio (135–150 s of
repro-A):The chunk-count threshold is sharp — tested at 75 / 90 / 105 / 120 / 135 / 150 s, 9 chunks pass,
10 fails.
repro-Bis the negative control: identical duration and chunk count, differentcontent, passes.
Consistent with that reading,
--audio-chunk-seconds 30on the same 150 s passes — fewer alignerinvocations per process, not better audio. That is our downstream workaround.
Throw site
src/framework/audio/chunking.cpp:602, in the word-merge path:Two observations, offered as leads rather than conclusions:
may be worth clamping or dropping the offending word (with a warning) instead of throwing — a
40-minute transcription currently loses every timestamp because of one bad span. The adjacent
speech-metadata merge at
:637has the same all-or-nothing shape.which was fixed for
vibevoice_asrin 0.5 by rate-aware chunking. Theqwen3_asr+ forcedaligner words path still reaches this throw on 16 kHz input. It may be a surviving corner of the
same domain mismatch — though the sharp chunk-count threshold above suggests state accumulation
is at least as important as any rate conversion.
Ruled out
Two candidate commits were eliminated by testing directly at each one's parent — both still fail 3/3:
622cadd"Align ASR chunk timestamp domains"788253b7ce769e"Add Qwen3 ASR streaming path"80627afWe originally filed this internally as a 0.5 regression on the strength of a 3-minute gap between
our last green run and the 0.5 deploy. That was coincidence — the earlier runs used recordings that
do not trigger it.
Coverage note
No regression test appears to cover multi-chunk fixed-mode alignment with
--words-outin anyreleased version — a test that runs ≥10 chunks through one process would catch this.
Fixtures
I have the three 16 kHz WAVs used above (
repro-A-150s-fails,repro-B-150s-PASSES-negative-control,control-60s-passes) and can attach them or provide the failing--words-outJSON, chunk-boundarydump, or any instrumented run that would help. Happy to test a patch on sm_120.
Related: #198 (a different all-or-nothing abort in the same aligner path, from punctuation-only
chunks).