Files
CoRE.Vision/backend/app/transcode.py
T
2026-05-30 00:08:59 +05:00

89 lines
3.2 KiB
Python

"""Общие параметры перекодирования 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)