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_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: 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"