From 38a975b023ac55d358ce21a67045b3daf3450d49 Mon Sep 17 00:00:00 2001 From: Krzysztof Bulanda Date: Sun, 30 Nov 2025 12:42:41 +0100 Subject: [PATCH 1/2] feat: support loose language selection --- src/ffmpeg2obj/helper.py | 26 ++++++++++++++++++++++---- src/ffmpeg2obj/script.py | 10 ++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/ffmpeg2obj/helper.py b/src/ffmpeg2obj/helper.py index 7631efe..7ee924f 100644 --- a/src/ffmpeg2obj/helper.py +++ b/src/ffmpeg2obj/helper.py @@ -9,7 +9,7 @@ import tempfile import time from datetime import timedelta -from typing import Any +from typing import Any, Optional import boto3 import botocore @@ -35,6 +35,7 @@ def __init__( video_codec: str, pix_fmt: str, langs: list[str], + loose_langs: bool, target_qp: int, target_crf: int, ) -> None: @@ -42,6 +43,7 @@ def __init__( self.video_codec = video_codec self.pix_fmt = pix_fmt self.langs = langs + self.loose_langs = loose_langs self.target_qp = target_qp self.target_crf = target_crf self.target_res: list[int] = [target_width, target_height] @@ -77,6 +79,7 @@ def __init__( self.dst_hashed_path: str = ( self.dst_dir + self.hashed_name + "." + self.file_extension ) + self.probe_result: Optional[dict] = None def __str__(self) -> str: out = [] @@ -102,9 +105,10 @@ def update(self, obj_config: dict, bucket_name: str) -> None: def get_coded_res(self) -> list[int]: """Returns height and width for the file from real_path""" - probe_result = ffmpeg.probe(self.real_paths[0]) + if self.probe_result is None: + self.probe_result = ffmpeg.probe(self.real_paths[0]) video_stream = list( - filter(lambda x: x["codec_type"] == "video", probe_result["streams"]) + filter(lambda x: x["codec_type"] == "video", self.probe_result["streams"]) )[0] coded_res = [video_stream["coded_width"], video_stream["coded_height"]] return coded_res @@ -131,8 +135,22 @@ def convert(self, verbose: bool = False) -> tuple[str, str, bool, timedelta]: elif self.processing_params.target_qp is not None: opts_dict.update({"qp": str(self.processing_params.target_qp)}) if self.processing_params.langs != ["all"]: + requested_langs = set(self.processing_params.langs) + if self.processing_params.loose_langs: + langs = set() + if self.probe_result is None: + self.probe_result = ffmpeg.probe(self.real_paths[0]) + for stream in self.probe_result["streams"]: + try: + lang = stream["tags"]["language"] + if lang in requested_langs: + langs.add(lang) + except KeyError: + pass + else: + langs = requested_langs lang_map = [] - for lang in self.processing_params.langs: + for lang in langs: lang_map.append("0:m:language:" + lang) lang_dict = {"map": tuple(lang_map)} opts_dict.update(lang_dict) diff --git a/src/ffmpeg2obj/script.py b/src/ffmpeg2obj/script.py index 8fcb6bc..e36f20f 100644 --- a/src/ffmpeg2obj/script.py +++ b/src/ffmpeg2obj/script.py @@ -139,6 +139,15 @@ def parse_args() -> argparse.Namespace: help="selected languages transcoding of the media files, all keeps every track", ) + parser.add_argument( + "-ll", + "--loose-languages", + dest="loose_langs", + action="store_true", + default=False, + help="prevents ffmpeg failures if media to be transcoded lack requested languages", + ) + parser.add_argument( "--width", dest="target_width", @@ -471,6 +480,7 @@ def main(): args.video_codec, args.pix_fmt, args.langs, + args.loose_langs, args.target_qp, args.target_crf, ) From 2a1dbc48233dbc67db72098641c1964f3351b224 Mon Sep 17 00:00:00 2001 From: Krzysztof Bulanda Date: Sun, 30 Nov 2025 12:54:42 +0100 Subject: [PATCH 2/2] docs: update help section in readme --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f8ea947..8decd8a 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,9 @@ The built-in help provides handles and default values for implemented functions ```bash (venv) ~/ffmpeg2obj$ ffmpeg2obj --help usage: ffmpeg2obj [-h] [-v] [--noop] [--force-cleanup] [-s SRC_DIR] [-d DST_DIR] [-i IGNORED_SUBDIR] [-o OBJ_PREFIX] - [--source-file-extension SOURCE_FILE_EXTENSION] [-e FILE_EXTENSION] [-vc VIDEO_CODEC] [--pix-fmt PIX_FMT] - [-l LANGS] [--width TARGET_WIDTH] [--resize] [--concat] [--height TARGET_HEIGHT] - (-b BUCKET_NAME | --disable-upload) [-qp TARGET_QP | -crf TARGET_CRF] + [--source-file-extension SOURCE_FILE_EXTENSION] [-e FILE_EXTENSION] [-vc VIDEO_CODEC] [--pix-fmt PIX_FMT] [-l LANGS] + [-ll] [--width TARGET_WIDTH] [--resize] [--concat] [--height TARGET_HEIGHT] (-b BUCKET_NAME | --disable-upload) + [-qp TARGET_QP | -crf TARGET_CRF] Simple tool to compress blu ray movie library and store it in obj @@ -84,6 +84,8 @@ options: --pix-fmt PIX_FMT pix fmt for transcoding of the media files -l LANGS, --languages LANGS selected languages transcoding of the media files, all keeps every track + -ll, --loose-languages + prevents ffmpeg failures if media to be transcoded lack requested languages --width TARGET_WIDTH target width for the media files to be transcoded --resize scale input files to height x width --concat concatenates files within same directory