Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion astrbot/core/utils/media_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = 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")
):
return audio_path

if output_path is None:
Expand Down
28 changes: 28 additions & 0 deletions tests/test_media_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading