init
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""Общие параметры перекодирования 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)
|
||||
Reference in New Issue
Block a user