Simplify conversion to one fail-safe H.264 profile
This commit is contained in:
@@ -54,11 +54,11 @@ the `.env.example` values through Coolify's environment-variable UI.
|
||||
|
||||
## Codec policy
|
||||
|
||||
Cached video is H.264 High Profile, Level 4.1, 8-bit `yuv420p`, CRF 18, capped
|
||||
at 15 Mbps. Existing audio, subtitles, chapters, and Matroska attachments are
|
||||
preserved when the container supports them. Ten-bit SDR is converted with
|
||||
error-diffusion dithering; HDR10, HLG, and Dolby Vision-labelled sources are
|
||||
tone-mapped to BT.709 SDR before encoding.
|
||||
Cached video is H.264 High Profile, 8-bit `yuv420p`, CRF 18, capped at 15 Mbps.
|
||||
Resolution and frame rate are preserved. Existing audio, subtitles, chapters,
|
||||
and Matroska attachments are copied. Ten-bit SDR is converted with
|
||||
error-diffusion dithering; sources carrying explicit HDR10 or HLG transfer
|
||||
metadata are tone-mapped to BT.709 SDR.
|
||||
|
||||
The fixed source blacklist is:
|
||||
|
||||
|
||||
+10
-15
@@ -39,7 +39,7 @@ H264_CRF = os.environ.get("H264_CRF", "18")
|
||||
H264_PRESET = os.environ.get("H264_PRESET", "medium")
|
||||
H264_MAXRATE = os.environ.get("H264_MAXRATE", "15M")
|
||||
H264_BUFSIZE = os.environ.get("H264_BUFSIZE", "30M")
|
||||
ENCODE_PROFILE = f"h264-high41-8bit-crf{H264_CRF}-{H264_PRESET}-{H264_MAXRATE}-quality-v2"
|
||||
ENCODE_PROFILE = f"h264-high-8bit-crf{H264_CRF}-{H264_PRESET}-{H264_MAXRATE}-quality-v3"
|
||||
FFMPEG = os.environ.get("FFMPEG", "/usr/bin/ffmpeg")
|
||||
FFPROBE = os.environ.get("FFPROBE", "/usr/bin/ffprobe")
|
||||
|
||||
@@ -389,8 +389,10 @@ class Manager:
|
||||
continue
|
||||
old = inventory.get(relative) or {}
|
||||
if old.get("fingerprint") == current_fingerprint:
|
||||
if relative in catalog and catalog[relative].get("item_id"):
|
||||
old["item_id"] = catalog[relative]["item_id"]
|
||||
if relative in catalog:
|
||||
for key in ("item_id", "color_transfer", "color_primaries", "color_space"):
|
||||
if catalog[relative].get(key):
|
||||
old[key] = catalog[relative][key]
|
||||
continue
|
||||
details = catalog.get(relative)
|
||||
view = VIEW_ROOT / relative
|
||||
@@ -469,13 +471,8 @@ class Manager:
|
||||
profile = (info.get("profile") or "").lower()
|
||||
return codec in BLACKLISTED_CODECS or (codec == "h264" and (depth > 8 or "10" in profile))
|
||||
|
||||
def is_hdr(self, info, source):
|
||||
transfer = (info.get("color_transfer") or "").lower()
|
||||
name = source.name.lower()
|
||||
return (
|
||||
transfer in {"smpte2084", "arib-std-b67"}
|
||||
or any(token in name for token in ("hdr10", "hdr.", ".hdr", "dovi", "dolby.vision"))
|
||||
)
|
||||
def is_hdr(self, info):
|
||||
return (info.get("color_transfer") or "").lower() in {"smpte2084", "arib-std-b67"}
|
||||
|
||||
def candidate_list(self):
|
||||
now = time.time()
|
||||
@@ -581,15 +578,13 @@ class Manager:
|
||||
self.process = None
|
||||
|
||||
def ffmpeg_command(self, source, partial, info):
|
||||
hdr = self.is_hdr(info, source)
|
||||
hdr = self.is_hdr(info)
|
||||
if hdr:
|
||||
transfer = (info.get("color_transfer") or "").lower()
|
||||
if transfer == "arib-std-b67":
|
||||
input_colors = "tin=arib-std-b67:pin=bt2020:min=bt2020nc:"
|
||||
elif transfer == "smpte2084":
|
||||
input_colors = ""
|
||||
else:
|
||||
input_colors = "tin=smpte2084:pin=bt2020:min=bt2020nc:"
|
||||
input_colors = ""
|
||||
video_filter = (
|
||||
f"zscale={input_colors}t=linear:npl=100,format=gbrpf32le,"
|
||||
"zscale=p=bt709,tonemap=tonemap=hable:desat=0,"
|
||||
@@ -604,7 +599,7 @@ class Manager:
|
||||
"-vf", video_filter,
|
||||
"-c:v", "libx264", "-preset", H264_PRESET, "-crf", H264_CRF,
|
||||
"-maxrate", H264_MAXRATE, "-bufsize", H264_BUFSIZE,
|
||||
"-pix_fmt", "yuv420p", "-profile:v", "high", "-level:v", "4.1",
|
||||
"-pix_fmt", "yuv420p", "-profile:v", "high",
|
||||
"-c:a", "copy", "-c:s", "copy",
|
||||
]
|
||||
if hdr:
|
||||
|
||||
Reference in New Issue
Block a user