Skip to content

Drop out-of-span chunk speech metadata instead of aborting the run - #301

Merged
0xShug0 merged 1 commit into
0xShug0:mainfrom
bjhengen:fix/chunking-speech-metadata-drop-outside-spans
Aug 24, 2026
Merged

Drop out-of-span chunk speech metadata instead of aborting the run#301
0xShug0 merged 1 commit into
0xShug0:mainfrom
bjhengen:fix/chunking-speech-metadata-drop-outside-spans

Conversation

@bjhengen

Copy link
Copy Markdown
Contributor

Found while investigating #249. src/framework/audio/chunking.cpp has two sibling merge paths that compute the identical out-of-span guard and then disagree about what it means:

path function on out-of-span reached by
word timestamps append_chunk_word_timestamps warn + continue (since #252) qwen3_asr forced aligner
speech metadata append_chunk_speech_metadatamerge_span throw, aborting the whole run vibevoice_asr

#252 chose warn-and-drop for the word path. This PR applies that same decision to the metadata path, which still aborts. It is not proposing a new policy — it is finishing the one already merged.

merge_span covers both speech_segments and speaker_turns, so either can abort a run.

The change

merge_span already returns std::optional<TimeSpan>, and both call sites already continue on std::nullopt. So the throw becomes a warning plus return std::nullopt — the "not applicable" signal the function was already built around. No signature change, no call-site change. The warning carries the same diagnostic fields the word path emits (local_start, local_end, source_samples, the source/keep spans, both sample rates).

Test

Adds test_chunk_speech_metadata_merge_drops_outside_spans, mirroring #252's test_chunk_word_timestamp_merge_drops_outside_words: one kept span and one outside span for both speech_segments and speaker_turns, asserting the outside ones are dropped and the valid ones survive with correct global spans.

Only test_chunk_speech_metadata_merge_rescales_chunk_domain existed before, so the out-of-span behaviour on this path had no coverage at all.

Scope: which routes were checked

Shared framework code, so to be explicit about blast radius:

  • Affected: the vibevoice_asr chunked path (speech_segments and speaker_turns). Behaviour change: a run that previously aborted now completes, with the out-of-span entry dropped and a warning logged.
  • Not affected: the qwen3_asr word-timestamp path — untouched; it has behaved this way since Avoid aborting ASR word merge on out-of-span timestamps #252. append_chunk_speech_metadata calls append_chunk_word_timestamps at the end, so today a vibevoice user gets the lenient behaviour for words and the fatal one for segments within the same call.
  • No output, performance or memory change on any path that does not hit the guard.

Verification

Verified on this PR's base, main @ 288a271, CPU-only:

cmake -S . -B build-cpu -DENGINE_ENABLE_CUDA=OFF -DENGINE_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build-cpu --target audio_chunking_test -j8
./build-cpu/bin/audio_chunking_test
state result
new test, stock chunking.cpp audio_chunking_test failed: Audio chunker speech metadata merge received a speech segment outside the chunk span (exit 1)
new test, with the fix audio_chunking_test passed (exit 0)

So it is a real regression test: it fails without the change and passes with it, on the exact commit this PR targets.

Earlier I ran the same pair at release-0.6.1 in both configurations — CPU-only and CUDA (-DENGINE_ENABLE_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=120, sm_120 / RTX 5090) — with identical results. I did not repeat the CUDA build on main; src/framework/audio/chunking.cpp is byte-identical between release-0.6.1 and 288a271 (unchanged since #252), and this path has no backend-dependent code.

Known limitation, stated plainly

Reachability of the metadata case is unproven. I have not observed an out-of-span segment or turn in the wild — my own trigger (#249) is on the word path. The argument for this change is the inconsistency itself: the same guard on the same arithmetic in the same file should not abort in one place and drop in the other.

The supporting evidence that it is not theoretical:

If you would rather see a reproduction on the metadata path before changing behaviour there, that is a fair ask and I am happy to keep digging instead.

`append_chunk_speech_metadata`'s `merge_span` throws when a speech segment or
speaker turn lands outside the chunk span, which aborts the whole run. The
sibling `append_chunk_word_timestamps` path computes the identical guard and,
since 0xShug0#252, warns and drops the offending entry instead. This applies the same
decision to the metadata path so both merge paths behave consistently.

`merge_span` already returns `std::optional<TimeSpan>`, and both call sites
already `continue` on `std::nullopt`, so the throw becomes a warning plus
`return std::nullopt` with no signature or call-site change. The warning
carries the same diagnostic fields as the word path.

Adds `test_chunk_speech_metadata_merge_drops_outside_spans`, mirroring 0xShug0#252's
`test_chunk_word_timestamp_merge_drops_outside_words`. The out-of-span
behaviour on this path previously had no test coverage.
@0xShug0
0xShug0 merged commit d25ffac into 0xShug0:main Aug 24, 2026
6 checks passed
@0xShug0

0xShug0 commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Thanks @bjhengen! PR merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants