diff --git a/src/framework/audio/chunking.cpp b/src/framework/audio/chunking.cpp index c2f16e44..dcfa30d5 100644 --- a/src/framework/audio/chunking.cpp +++ b/src/framework/audio/chunking.cpp @@ -1,5 +1,6 @@ #include "engine/framework/audio/chunking.h" +#include "engine/framework/debug/trace.h" #include "engine/framework/runtime/options.h" #include @@ -7,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -599,7 +601,20 @@ void append_chunk_word_timestamps( const int64_t local_start = std::max(word.span.start_sample, 0); const int64_t local_end = std::min(word.span.end_sample, source_samples); if (local_start >= local_end) { - throw std::runtime_error("Audio chunker word merge received a timestamp outside the chunk span"); + std::ostringstream warning; + warning << "dropping word timestamp outside chunk span" + << " word=\"" << word.word << "\"" + << " local_start=" << word.span.start_sample + << " local_end=" << word.span.end_sample + << " source_samples=" << source_samples + << " source_start=" << source_span.start_sample + << " source_end=" << source_span.end_sample + << " keep_start=" << keep_span.start_sample + << " keep_end=" << keep_span.end_sample + << " source_sample_rate=" << source_sample_rate + << " timestamp_sample_rate=" << timestamp_sample_rate; + debug::log_message(debug::LogLevel::Warning, "audio.chunking", warning.str()); + continue; } const int64_t global_start = timestamp_source_span.start_sample + local_start; if (global_start < timestamp_keep_span.start_sample || global_start >= timestamp_keep_span.end_sample) { diff --git a/tests/unittests/test_audio_chunking.cpp b/tests/unittests/test_audio_chunking.cpp index 73ab83da..cf7d9489 100644 --- a/tests/unittests/test_audio_chunking.cpp +++ b/tests/unittests/test_audio_chunking.cpp @@ -836,16 +836,6 @@ void test_chunk_word_timestamp_merge_rejects_invalid_spans() { }, "inverted chunk span"); - require_throws( - []() { - std::vector merged; - engine::audio::append_chunk_word_timestamps( - merged, - {word("outside", 120, 140)}, - engine::runtime::TimeSpan{1000, 1100}); - }, - "word outside chunk"); - require_throws( []() { std::vector merged; @@ -871,6 +861,24 @@ void test_chunk_word_timestamp_merge_rejects_invalid_spans() { "invalid source sample rate"); } +void test_chunk_word_timestamp_merge_drops_outside_words() { + std::vector merged; + engine::audio::append_chunk_word_timestamps( + merged, + { + word("kept", 20, 40), + word("outside", 120, 140), + word("also_kept", 50, 80), + }, + engine::runtime::TimeSpan{1000, 1100}); + + engine::test::require_eq(merged.size(), static_cast(2), "outside word dropped"); + engine::test::require_eq(merged[0].word, std::string("kept"), "first valid word kept"); + require_span(merged[0].span, 1020, 1040, "first valid word span"); + engine::test::require_eq(merged[1].word, std::string("also_kept"), "second valid word kept"); + require_span(merged[1].span, 1050, 1080, "second valid word span"); +} + } // namespace int main() { @@ -903,6 +911,7 @@ int main() { test_chunk_word_timestamp_merge_rescales_chunk_domain(); test_chunk_speech_metadata_merge_rescales_chunk_domain(); test_chunk_word_timestamp_merge_rejects_invalid_spans(); + test_chunk_word_timestamp_merge_drops_outside_words(); std::cout << "audio_chunking_test passed\n"; } catch (const std::exception & ex) { std::cerr << "audio_chunking_test failed: " << ex.what() << "\n";