From 628a729afd5b0399f8349ab14115dad005e84149 Mon Sep 17 00:00:00 2001 From: Myron Blair Date: Mon, 27 Jul 2026 20:41:30 -0500 Subject: [PATCH] Speed up ABR transcoding: cap variants at 2, drop x264 preset to superfast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Host CPU is an old Xeon E5530 (2010-era, no hardware encode available at all) already fairly loaded, so raw compute is the real bottleneck. Two changes: - Cap ABR renditions to the 2 highest applicable instead of up to 4 — roughly halves total encode work per job while still giving a real high/low adaptive-bitrate pair. - veryfast -> superfast x264 preset, a meaningful further speed win at the cost of somewhat larger files and slightly softer quality per bitrate. Combined, remaining variants also get more threads each since fewer variants now share the same TRANSCODE_THREADS budget. --- backend/transcode.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/transcode.py b/backend/transcode.py index 6ecf201..79a5668 100644 --- a/backend/transcode.py +++ b/backend/transcode.py @@ -64,13 +64,16 @@ ALL_VARIANTS = [ def variants_for_source(src_height: int) -> List[Tuple[int, str, str, str, str]]: - """Pick variants ≤ source height. Always include at least one (smallest).""" + """Pick up to 2 variants ≤ source height (the two highest applicable renditions — + ALL_VARIANTS is ordered highest-to-lowest, so slicing keeps the best pair). Capped at 2 + instead of the full ladder to roughly halve ABR encode time on this host's aging CPU, while + still giving a real high/low adaptive-bitrate pair for most connections.""" if src_height <= 0: return [ALL_VARIANTS[2]] # safe default 480p chosen = [v for v in ALL_VARIANTS if v[0] <= src_height] if not chosen: chosen = [ALL_VARIANTS[-1]] - return chosen + return chosen[:2] async def transcode_audio_fix(source: Path, out_dir: Path, on_status: Callable[..., Awaitable]) -> None: @@ -133,7 +136,7 @@ async def transcode_abr(source: Path, out_dir: Path, on_status: Callable[..., Aw filter_complex = ";".join(fc_parts) # Per-variant thread count, not the full cap each — x264 threads are set per encoder - # instance, so giving every one of the (up to 4) variants the full TRANSCODE_THREADS + # instance, so giving every one of the (up to 2) variants the full TRANSCODE_THREADS # budget lets them all run near-full-tilt simultaneously and still saturate the host. per_variant_threads = max(1, TRANSCODE_THREADS // n) @@ -143,7 +146,7 @@ async def transcode_abr(source: Path, out_dir: Path, on_status: Callable[..., Aw cmd += [ "-map", f"[v{i}out]", f"-c:v:{i}", "libx264", - f"-preset:v:{i}", "veryfast", + f"-preset:v:{i}", "superfast", f"-threads:v:{i}", str(per_variant_threads), f"-profile:v:{i}", "main", f"-pix_fmt:v:{i}", "yuv420p",