"""Общие параметры перекодирования H.264 (профиль, битрейт, пресет, GOP).""" from __future__ import annotations H264_PROFILES = ("baseline", "main", "high") BITRATES = ("500k", "1000k", "2000k", "4000k", "8000k", "10000k", "16000k", "20000k", "24000k") PRESETS = ("ultrafast", "superfast") KEYINTS = (1, 2, 5) # интервал ключевых кадров, секунды CODECS = ("h264", "vp9") DEFAULT_PROFILE = "main" DEFAULT_BITRATE = "2000k" DEFAULT_PRESET = "superfast" DEFAULT_KEYINT = 2 DEFAULT_CODEC = "h264" def norm_profile(p: str | None) -> str: return p if p in H264_PROFILES else DEFAULT_PROFILE def norm_codec(c: str | None) -> str: return c if c in CODECS else DEFAULT_CODEC def norm_bitrate(b: str | None) -> str: return b if b in BITRATES else DEFAULT_BITRATE def norm_preset(p: str | None) -> str: return p if p in PRESETS else DEFAULT_PRESET def norm_keyint(k) -> int: try: k = int(k) except (TypeError, ValueError): return DEFAULT_KEYINT return k if k in KEYINTS else DEFAULT_KEYINT def x264_args(profile: str, bitrate: str, low_latency: bool = False, preset: str | None = None, keyint_sec=None) -> list[str]: """Аргументы libx264: профиль, битрейт, пресет и интервал ключевых кадров. Ключевые кадры расставляются по времени (через -force_key_frames), поэтому интервал в секундах соблюдается независимо от fps камеры.""" bufsize = f"{int(bitrate[:-1]) * 2}k" preset = norm_preset(preset) sec = norm_keyint(keyint_sec) args = [ "-c:v", "libx264", "-preset", preset, "-profile:v", profile, "-b:v", bitrate, "-maxrate", bitrate, "-bufsize", bufsize, "-force_key_frames", f"expr:gte(t,n_forced*{sec})", "-pix_fmt", "yuv420p", ] if low_latency: args += ["-tune", "zerolatency"] return args def vp9_args(bitrate: str, low_latency: bool = False, preset: str | None = None, keyint_sec=None) -> list[str]: """Аргументы кодировщика libvpx-VP9 (профиль H.264 неприменим).""" sec = norm_keyint(keyint_sec) # быстрый пресет → выше cpu-used (быстрее, ниже качество); realtime для live cpu = "8" if norm_preset(preset) == "ultrafast" else "6" return [ "-c:v", "libvpx-vp9", "-b:v", bitrate, "-maxrate", bitrate, "-deadline", "realtime", "-cpu-used", cpu, "-row-mt", "1", "-force_key_frames", f"expr:gte(t,n_forced*{sec})", "-pix_fmt", "yuv420p", ] def encode_args(codec: str, profile: str, bitrate: str, low_latency: bool = False, preset: str | None = None, keyint_sec=None) -> list[str]: """Аргументы видеокодировщика под выбранный кодек (h264 | vp9).""" if norm_codec(codec) == "vp9": return vp9_args(bitrate, low_latency, preset, keyint_sec) return x264_args(profile, bitrate, low_latency, preset, keyint_sec)