From 250702de59f32e38176be97b05488e901621ad7c Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Sat, 29 Aug 2026 12:00:52 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20worker=20=E9=9F=B3=E9=A2=91=20mime?= =?UTF-8?q?=20=E6=8E=A8=E6=96=AD=E8=A1=A5=E5=85=85=20.m4a/.mp3/.wav/.flac/?= =?UTF-8?q?.ogg/.aac/.wma/.amr/.opus/.weba?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit infer_mime_type_from_storage_key 此前只识别视频后缀,其他一律返回 image/jpeg,导致所有音频文件在 ingest 后被标记为 file_type=image, 配音上传和克隆音色上传均失败。 补充音频后缀分支,返回对应 audio/... mime type。 新增 10 个音频单测,共 13 测试全过。 --- apps/worker/worker_app/core/asset_types.py | 23 +++++++++++ tests/unit/test_worker_ingest.py | 45 ++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/apps/worker/worker_app/core/asset_types.py b/apps/worker/worker_app/core/asset_types.py index f798848d5..d28cb758a 100644 --- a/apps/worker/worker_app/core/asset_types.py +++ b/apps/worker/worker_app/core/asset_types.py @@ -1,7 +1,30 @@ def infer_mime_type_from_storage_key(storage_key: str) -> str: lower_filename = storage_key.rsplit("/", 1)[-1].lower() + # Video if lower_filename.endswith(".mov"): return "video/quicktime" if lower_filename.endswith((".mp4", ".m4v", ".avi", ".mkv", ".webm")): return "video/mp4" + # Audio + if lower_filename.endswith(".m4a"): + return "audio/mp4" + if lower_filename.endswith(".mp3"): + return "audio/mpeg" + if lower_filename.endswith(".wav"): + return "audio/wav" + if lower_filename.endswith(".flac"): + return "audio/flac" + if lower_filename.endswith(".ogg"): + return "audio/ogg" + if lower_filename.endswith(".aac"): + return "audio/aac" + if lower_filename.endswith(".wma"): + return "audio/x-ms-wma" + if lower_filename.endswith(".amr"): + return "audio/amr" + if lower_filename.endswith(".opus"): + return "audio/opus" + if lower_filename.endswith(".weba"): + return "audio/webm" + # Default fallback return "image/jpeg" diff --git a/tests/unit/test_worker_ingest.py b/tests/unit/test_worker_ingest.py index a40a495a5..012c05f21 100644 --- a/tests/unit/test_worker_ingest.py +++ b/tests/unit/test_worker_ingest.py @@ -17,3 +17,48 @@ def test_infer_mime_type_treats_common_video_extensions_as_video(): def test_infer_mime_type_keeps_unknown_files_as_image_placeholder(): assert infer_mime_type_from_storage_key("uploads/abc/photo.jpg") == "image/jpeg" + + +# ─── Audio extensions ─────────────────────────────────────────────── + + +def test_infer_mime_type_audio_m4a(): + assert infer_mime_type_from_storage_key("uploads/abc/voice.m4a") == "audio/mp4" + # case-insensitive + assert infer_mime_type_from_storage_key("uploads/abc/VOICE.M4A") == "audio/mp4" + + +def test_infer_mime_type_audio_mp3(): + assert infer_mime_type_from_storage_key("uploads/abc/song.mp3") == "audio/mpeg" + + +def test_infer_mime_type_audio_wav(): + assert infer_mime_type_from_storage_key("uploads/abc/recording.wav") == "audio/wav" + + +def test_infer_mime_type_audio_flac(): + assert infer_mime_type_from_storage_key("uploads/abc/hifi.flac") == "audio/flac" + + +def test_infer_mime_type_audio_ogg(): + assert infer_mime_type_from_storage_key("uploads/abc/podcast.ogg") == "audio/ogg" + + +def test_infer_mime_type_audio_aac(): + assert infer_mime_type_from_storage_key("uploads/abc/stream.aac") == "audio/aac" + + +def test_infer_mime_type_audio_wma(): + assert infer_mime_type_from_storage_key("uploads/abc/old.wma") == "audio/x-ms-wma" + + +def test_infer_mime_type_audio_amr(): + assert infer_mime_type_from_storage_key("uploads/abc/voice_msg.amr") == "audio/amr" + + +def test_infer_mime_type_audio_opus(): + assert infer_mime_type_from_storage_key("uploads/abc/voip.opus") == "audio/opus" + + +def test_infer_mime_type_audio_weba(): + assert infer_mime_type_from_storage_key("uploads/abc/web_audio.weba") == "audio/webm" -- 2.54.0 From 81bc72f86a376747f841633eebc01fe2ad80ed25 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Sat, 29 Aug 2026 12:20:18 +0800 Subject: [PATCH 2/3] ci: trigger re-run -- 2.54.0 From 874893900dd28a3c2b4209ebadae14efcd3038bd Mon Sep 17 00:00:00 2001 From: CI Bot Date: Sat, 29 Aug 2026 04:25:30 +0000 Subject: [PATCH 3/3] style: auto-format with black + isort + prettier [skip ci-format-check] --- tests/unit/test_generation_cover.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_generation_cover.py b/tests/unit/test_generation_cover.py index 1398c5cba..e7065b34d 100644 --- a/tests/unit/test_generation_cover.py +++ b/tests/unit/test_generation_cover.py @@ -707,9 +707,9 @@ class TestStrayLoggerRemoved: source = inspect.getsource(generation_cover) # The stray call was logger.info(\n plan_id,\n generation_task_id,\n) # with no format string — should not exist - assert "logger.info(\n plan_id," not in source, ( - "Stray logger.info(plan_id, generation_task_id) should be removed" - ) + assert ( + "logger.info(\n plan_id," not in source + ), "Stray logger.info(plan_id, generation_task_id) should be removed" class TestUploadCoverType: -- 2.54.0