diff --git a/src/utils/files.py b/src/utils/files.py index 56212da6..b57a691c 100644 --- a/src/utils/files.py +++ b/src/utils/files.py @@ -151,7 +151,8 @@ class AudioProcessor: suffix = self.get_output_suffix(filename, content_type) normalized_filename = self.ensure_audio_filename(filename, suffix) normalized_content_type = self.normalize_content_type(filename, content_type) - self._probe_audio_duration_seconds( + await asyncio.to_thread( + self._probe_audio_duration_seconds, content, suffix, ) diff --git a/tests/utils/test_audio_processing.py b/tests/utils/test_audio_processing.py index e8768ed8..f951ed14 100644 --- a/tests/utils/test_audio_processing.py +++ b/tests/utils/test_audio_processing.py @@ -149,6 +149,31 @@ async def test_audio_processor_extract_text_transcribes_directly(): assert "transcription_fallback_used" not in extracted.metadata +@pytest.mark.asyncio +async def test_audio_processor_extract_text_probes_in_background_thread(): + processor = AudioProcessor() + mock_probe = AsyncMock(return_value=1.0) + to_thread = AsyncMock(return_value=1.0) + + with ( + patch.object(processor, "_probe_audio_duration_seconds", mock_probe), + patch("src.utils.files.asyncio.to_thread", to_thread), + patch("src.utils.files.transcribe_audio", new=AsyncMock(return_value="ok")), + ): + extracted = await processor.extract_text( + b"bytes", + filename="voice-note.mp3", + content_type="audio/mpeg", + ) + + to_thread.assert_awaited_once_with( + mock_probe, + b"bytes", + ".mp3", + ) + assert extracted.text == "ok" + + @pytest.mark.asyncio async def test_audio_processor_extract_text_allows_empty_transcript(): processor = AudioProcessor()