Fix ffprobe handling for WebM and format families

This commit is contained in:
Abel Luck 2026-04-01 17:13:19 +02:00
parent 0504013c5a
commit 05ac6ce20d
4 changed files with 500 additions and 169 deletions

View file

@ -77,7 +77,7 @@ def probe_media(file_path) -> Dict[str, Any]:
def bitrate(info) -> float:
try:
return int(info["format"]["bit_rate"])
except KeyError | ValueError:
except (KeyError, ValueError):
logger.error("extracting bitrate from ffprobe failed")
return math.inf
@ -85,16 +85,34 @@ def bitrate(info) -> float:
def format_name(info) -> Optional[str]:
try:
return info["format"]["format_name"]
except KeyError | ValueError:
except (KeyError, ValueError):
logger.error("extracting format from ffprobe failed")
return None
def _stream_duration_sort_key(stream: Dict[str, Any]) -> tuple[int, float]:
duration_ts = _int_value(stream.get("duration_ts"))
if duration_ts is not None:
return 1, float(duration_ts)
try:
duration = float(str(stream.get("duration", "")))
except (TypeError, ValueError):
duration = 0.0
return 0, duration
def _matches_format(probe: Dict[str, Any], expected: str) -> bool:
current = format_name(probe)
if current is None:
return False
return expected in current.split(",")
def primary_video_stream(probe):
video_streams = [
stream for stream in probe["streams"] if stream["codec_type"] == "video"
]
video_streams = sorted(video_streams, key=lambda x: x["duration_ts"], reverse=True)
video_streams = sorted(video_streams, key=_stream_duration_sort_key, reverse=True)
if not video_streams:
return None
if len(video_streams) > 1:
@ -108,7 +126,7 @@ def primary_audio_stream(probe):
audio_streams = [
stream for stream in probe["streams"] if stream["codec_type"] == "audio"
]
audio_streams = sorted(audio_streams, key=lambda x: x["duration_ts"], reverse=True)
audio_streams = sorted(audio_streams, key=_stream_duration_sort_key, reverse=True)
if not audio_streams:
return None
if len(audio_streams) > 1:
@ -126,7 +144,7 @@ def get_resolution(probe) -> Tuple[Optional[float], Optional[float]]:
width = int(video_stream["width"])
height = int(video_stream["height"])
return width, height
except KeyError | ValueError:
except (KeyError, ValueError):
logger.error("extracting resolution from ffprobe failed")
return None, None
@ -137,7 +155,7 @@ def get_vcodec_name(probe) -> Optional[str]:
if not video_stream:
return None
return video_stream["codec_name"]
except KeyError | ValueError:
except (KeyError, ValueError):
logger.error("extracting video codec_name from ffprobe failed")
return None
@ -147,8 +165,11 @@ def get_acodec_info(probe) -> Tuple[Optional[str], Optional[int]]:
audio_stream = primary_audio_stream(probe)
if not audio_stream:
return None, None
return audio_stream["codec_name"], int(audio_stream["bit_rate"])
except KeyError | ValueError:
audio_bitrate = _int_value(
audio_stream.get("bit_rate") or probe["format"].get("bit_rate")
)
return audio_stream["codec_name"], audio_bitrate
except (KeyError, ValueError):
logger.error("extracting audio codec_name from ffprobe failed")
return None, None
@ -218,7 +239,7 @@ def audio_transcode_params(
is_br = True
else:
is_br = False
if format_name(probe_result) == fmt:
if _matches_format(probe_result, fmt):
is_fmt = True
else:
is_fmt = False
@ -289,11 +310,7 @@ def video_transcode_params(
# TODO: turn this into an exception and catch it for reporting
return None
current_container_many = format_name(probe_result)
is_container = False
if current_container_many is not None:
if target_container in current_container_many.split(","):
is_container = True
is_container = _matches_format(probe_result, target_container)
is_vcodec = vcodec == target_vcodec
is_acodec = acodec == target_acodec