diff --git a/src/framework/audio/chunking.cpp b/src/framework/audio/chunking.cpp index dcfa30d5..811d996b 100644 --- a/src/framework/audio/chunking.cpp +++ b/src/framework/audio/chunking.cpp @@ -648,8 +648,19 @@ void append_chunk_speech_metadata( const int64_t local_start = std::max(local_span.start_sample, 0); const int64_t local_end = std::min(local_span.end_sample, source_samples); if (local_start >= local_end) { - throw std::runtime_error(std::string("Audio chunker speech metadata merge received a ") + - label + " outside the chunk span"); + std::ostringstream warning; + warning << "dropping " << label << " outside chunk span" + << " local_start=" << local_span.start_sample + << " local_end=" << local_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()); + return std::optional{}; } runtime::TimeSpan global{ timestamp_source_span.start_sample + local_start, diff --git a/tests/unittests/test_audio_chunking.cpp b/tests/unittests/test_audio_chunking.cpp index cf7d9489..2d0686ca 100644 --- a/tests/unittests/test_audio_chunking.cpp +++ b/tests/unittests/test_audio_chunking.cpp @@ -879,6 +879,41 @@ void test_chunk_word_timestamp_merge_drops_outside_words() { require_span(merged[1].span, 1050, 1080, "second valid word span"); } +void test_chunk_speech_metadata_merge_drops_outside_spans() { + engine::runtime::TaskResult chunk; + auto kept_segment = speech(20, 40); + kept_segment.text = "kept segment"; + chunk.speech_segments.push_back(kept_segment); + auto outside_segment = speech(120, 140); + outside_segment.text = "outside segment"; + chunk.speech_segments.push_back(outside_segment); + + engine::runtime::SpeakerTurn kept_turn; + kept_turn.span = engine::runtime::TimeSpan{50, 80}; + kept_turn.speaker_id = "SPEAKER_00"; + chunk.speaker_turns.push_back(kept_turn); + engine::runtime::SpeakerTurn outside_turn; + outside_turn.span = engine::runtime::TimeSpan{120, 140}; + outside_turn.speaker_id = "SPEAKER_01"; + chunk.speaker_turns.push_back(outside_turn); + + engine::runtime::TaskResult merged; + engine::audio::append_chunk_speech_metadata( + merged, + chunk, + engine::runtime::TimeSpan{1000, 1100}, + engine::runtime::TimeSpan{1000, 1100}, + 16000, + 16000); + + engine::test::require_eq(merged.speech_segments.size(), static_cast(1), "outside speech segment dropped"); + engine::test::require_eq(merged.speech_segments[0].text, std::string("kept segment"), "valid speech segment kept"); + require_span(merged.speech_segments[0].span, 1020, 1040, "valid speech segment span"); + engine::test::require_eq(merged.speaker_turns.size(), static_cast(1), "outside speaker turn dropped"); + engine::test::require_eq(merged.speaker_turns[0].speaker_id, std::string("SPEAKER_00"), "valid speaker turn kept"); + require_span(merged.speaker_turns[0].span, 1050, 1080, "valid speaker turn span"); +} + } // namespace int main() { @@ -912,6 +947,7 @@ int main() { test_chunk_speech_metadata_merge_rescales_chunk_domain(); test_chunk_word_timestamp_merge_rejects_invalid_spans(); test_chunk_word_timestamp_merge_drops_outside_words(); + test_chunk_speech_metadata_merge_drops_outside_spans(); std::cout << "audio_chunking_test passed\n"; } catch (const std::exception & ex) { std::cerr << "audio_chunking_test failed: " << ex.what() << "\n";