CHANGE: maps codec/container/file_extension more accurate
Build and Push Docker Image / build-and-push-backend (pull_request) Failing after 19m21s
Build and Push Docker Image / build-and-push-frontend (pull_request) Successful in 54s
Build and Push Docker Image / notify-deployment-server (pull_request) Successful in 11s

This commit is contained in:
2026-08-19 11:12:48 +05:00
parent c27f832c95
commit 02b730b082
3 changed files with 192 additions and 81 deletions
+84 -9
View File
@@ -1,16 +1,79 @@
"""Container format decision and validation."""
from typing import Dict, Optional
from .constants import FORMAT_INFO
def determine_output_format(stream_info, user_format, transcode_audio):
def determine_default_format(container: Optional[str], codec: Optional[str]) -> Optional[str]:
"""
Given the container format and audio codec, determine the recommended output format.
This is used when the user has not explicitly specified a format.
It prioritizes the codec to choose the most appropriate container/extension.
Args:
container: Container name (e.g., 'ogg', 'mp4', 'matroska') as returned by get_container_format().
codec: Audio codec name (e.g., 'opus', 'aac', 'mp3') as returned by get_audio_codec().
Returns:
Format name (e.g., 'opus', 'm4a', 'mp3') or None if unknown.
"""
if not container:
return None
# Codec-based decisions (highest priority)
if codec == 'opus':
return 'opus'
if codec in ('aac', 'alac', 'he-aac'):
return 'm4a'
if codec == 'mp3':
return 'mp3'
if codec == 'vorbis':
return 'ogg'
if codec == 'flac':
return 'flac'
# Container-based fallback (lower priority)
if container in ('mp4', 'm4a', 'mov', '3gp'):
return 'mp4'
if container in ('matroska', 'webm'):
return 'matroska'
if container in ('ogg',):
return 'ogg'
if container in ('mp3', 'mpeg'):
return 'mp3'
if container == 'flac':
return 'flac'
if container == 'wav':
return 'wav'
if container == 'aac':
return 'aac'
if container == 'opus':
return 'opus'
if container == 'amr':
return 'amr'
return None
def determine_output_format(stream_info: Dict, user_format: Optional[str],
transcode_audio: Optional[str], input_file: Optional[str] = None) -> str:
"""
Decide which container format to use.
If user_format is provided, use it.
Else, try to detect the input file's container and codec, and use the recommended format.
If detection fails or format is not supported, fallback to:
- MKV if video/subtitles exist
- MP3 if the audio codec is MP3
- MP4 (M4A) otherwise
Args:
stream_info: Dict from get_stream_info().
user_format: Userrequested format (or None).
transcode_audio: Audio codec to transcode to (or None).
transcode_audio: Audio codec to transcode to (or None) (unused in this function).
input_file: Path to the input file (optional, used to detect container and codec).
Returns:
A format name that exists in FORMAT_INFO.
@@ -18,11 +81,22 @@ def determine_output_format(stream_info, user_format, transcode_audio):
if user_format:
return user_format
# If video or subtitles exist, use MKV (which supports everything).
if stream_info['has_video'] or stream_info['has_subtitle']:
return 'matroska'
# If input_file is provided, try to detect container and codec
if input_file:
try:
from .ffmpeg import get_container_format, get_audio_codec
container = get_container_format(input_file)
codec = get_audio_codec(input_file)
fmt = determine_default_format(container, codec)
if fmt in FORMAT_INFO:
return fmt
except Exception:
# If detection fails, fall through to legacy logic
pass
# Audioonly: choose based on the current audio codec.
# Fallback: legacy behavior
if stream_info.get('has_video') or stream_info.get('has_subtitle'):
return 'matroska'
audio_codec = stream_info.get('audio_codec', '')
if audio_codec == 'mp3':
return 'mp3'
@@ -30,7 +104,8 @@ def determine_output_format(stream_info, user_format, transcode_audio):
return 'mp4' # .m4a
def validate_format_compatibility(format_name, stream_info, drop_video, drop_subs):
def validate_format_compatibility(format_name: str, stream_info: Dict,
drop_video: bool, drop_subs: bool) -> None:
"""
Ensure the chosen container can accommodate the streams we intend to keep.
@@ -43,12 +118,12 @@ def validate_format_compatibility(format_name, stream_info, drop_video, drop_sub
return
if info['audio_only']:
if stream_info['has_video'] and not drop_video:
if stream_info.get('has_video') and not drop_video:
raise ValueError(
f"Format '{format_name}' does not support video streams. "
"Please use --drop-video or choose a container that supports video."
)
if stream_info['has_subtitle'] and not drop_subs:
if stream_info.get('has_subtitle') and not drop_subs:
raise ValueError(
f"Format '{format_name}' does not support subtitle streams. "
"Please use --drop-subs or choose a container that supports subtitles."