From d2c2ba6fe557a23a8b3652b3e70e0f331cfa58a4 Mon Sep 17 00:00:00 2001 From: zzz27578 <2950506809@qq.com> Date: Mon, 20 Jul 2026 16:55:49 +0800 Subject: [PATCH 1/2] fix: convert mislabeled audio before STT --- astrbot/core/utils/media_utils.py | 6 +++++- tests/test_media_utils.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/astrbot/core/utils/media_utils.py b/astrbot/core/utils/media_utils.py index a3990775ac..a15d481799 100644 --- a/astrbot/core/utils/media_utils.py +++ b/astrbot/core/utils/media_utils.py @@ -1127,7 +1127,11 @@ async def convert_audio_format( Raises: Exception: Raised when ffmpeg is unavailable or conversion fails. """ - if audio_path.lower().endswith(f".{output_format}"): + detected_format = _get_audio_magic_type(audio_path) + if audio_path.lower().endswith(f".{output_format}") and ( + detected_format == output_format + or (output_format == "ogg" and detected_format == "opus") + ): return audio_path if output_path is None: diff --git a/tests/test_media_utils.py b/tests/test_media_utils.py index 0cc3c85a12..78cdc01b54 100644 --- a/tests/test_media_utils.py +++ b/tests/test_media_utils.py @@ -399,6 +399,34 @@ async def test_media_resolver_accepts_unpadded_base64_payloads(tmp_path, monkeyp assert not list(tmp_path.iterdir()) +@pytest.mark.asyncio +async def test_ensure_wav_converts_non_wav_bytes_with_wav_suffix(tmp_path, monkeypatch): + monkeypatch.setattr(media_utils, "get_astrbot_temp_path", lambda: str(tmp_path)) + source_path = tmp_path / "voice.wav" + source_path.write_bytes(b"#!AMR\n" + b"\x00" * 64) + + class _Process: + returncode = 0 + + async def communicate(self): + return b"", b"" + + async def fake_create_subprocess_exec(*args, **_kwargs): + Path(args[-1]).write_bytes(b"RIFF\x24\x00\x00\x00WAVEfmt " + b"\x00" * 16) + return _Process() + + monkeypatch.setattr( + media_utils.asyncio, + "create_subprocess_exec", + fake_create_subprocess_exec, + ) + + resolved_path = await media_utils.ensure_wav(str(source_path)) + + assert resolved_path != str(source_path) + assert Path(resolved_path).read_bytes().startswith(b"RIFF") + + @pytest.mark.asyncio async def test_media_resolver_cleans_materialized_file_when_audio_conversion_fails( tmp_path, monkeypatch From 7dd356b4114e1534a60d78a14a5e4036b798b910 Mon Sep 17 00:00:00 2001 From: zzz27578 <2950506809@qq.com> Date: Mon, 20 Jul 2026 17:13:37 +0800 Subject: [PATCH 2/2] fix: offload audio format probe --- astrbot/core/utils/media_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astrbot/core/utils/media_utils.py b/astrbot/core/utils/media_utils.py index a15d481799..0d5775acc7 100644 --- a/astrbot/core/utils/media_utils.py +++ b/astrbot/core/utils/media_utils.py @@ -1127,7 +1127,7 @@ async def convert_audio_format( Raises: Exception: Raised when ffmpeg is unavailable or conversion fails. """ - detected_format = _get_audio_magic_type(audio_path) + detected_format = await asyncio.to_thread(_get_audio_magic_type, audio_path) if audio_path.lower().endswith(f".{output_format}") and ( detected_format == output_format or (output_format == "ogg" and detected_format == "opus")