From 42806b5e10f670626f25925cc80c8ca322b1bc3b Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Thu, 4 Jun 2026 17:56:08 +0000 Subject: [PATCH] fix(growing): use stable H.264 High All-Intra for 1080p59.94 MXF XDCAM HD422 does not strictly support 1080p59.94, and ffmpeg/raw2bmx failed to negotiate the stream. Reverted to h264_nvenc (High profile, all-intra GOP 1, yuv420p) which raw2bmx can reliably wrap as OP1a (--avc_high) at 60000/1001. This restores NVENC hardware acceleration and Premiere edit-while-record compatibility. --- services/capture/src/capture-manager.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/services/capture/src/capture-manager.js b/services/capture/src/capture-manager.js index 141d829..8271a99 100644 --- a/services/capture/src/capture-manager.js +++ b/services/capture/src/capture-manager.js @@ -360,10 +360,10 @@ const CONTAINER_EXT = { // keeps a short GOP. Muxed to a raw `mpeg2video` elementary stream (no // container) so raw2bmx ingests it via --mpeg2lg_*. const GROWING_VIDEO_ELEMENTARY_ARGS = [ - '-c:v', 'h264_nvenc', '-profile:v', 'high422', + '-c:v', 'h264_nvenc', '-profile:v', 'high', '-preset', 'p1', '-tune', 'll', '-rc', 'constqp', '-qp', '21', - '-pix_fmt', 'yuv422p', + '-pix_fmt', 'yuv420p', '-g', '1', ]; const GROWING_DEFAULT_BITRATE = '25M'; @@ -437,12 +437,12 @@ function deriveGrowingRaster(resolution, framerate, scanHint = null) { let rawFlag; if (height >= 1080) { - rawFlag = (scan === 'p') ? '--avci100_1080p' : '--avci100_1080i'; + rawFlag = '--avc_high'; } else if (height >= 720) { - rawFlag = '--avci100_720p'; // 720 is always progressive + rawFlag = '--avc_high'; if (fpsNum == null) { r.ff = '60000/1001'; r.raw = '60000/1001'; } } else { - rawFlag = '--mpeg2lg_422p_ml_576i'; // SD 576i (PAL); 25 fps + rawFlag = '--mpeg2lg_422p_ml_576i'; r.ff = '25'; r.raw = '25'; } @@ -910,13 +910,13 @@ class CaptureManager { // on stop, so the inline Python dur-patch below overwrites the header Duration // fields with the live frame count every 3s (Premiere reads the header // Duration on each refresh; without the patch it sees duration=N/A). - const bmx = [ - 'raw2bmx', '-t', 'rdd9', '-o', '"$OUT"', '-f', frameRate, - '--part', String(GROWING_PART_INTERVAL_FRAMES), - '--index-follows', - rawFlag, '"$VF"', - '-s', '48000', '-q', '16', '--audio-chan', String(ach), '--pcm', '"$AF"', - ]; +const bmx = [ + 'raw2bmx', '-t', 'op1a', '-o', '"$OUT"', '-f', frameRate, + '--part', String(GROWING_PART_INTERVAL_FRAMES), + '--index-follows', + rawFlag, '"$VF"', + '-s', '48000', '-q', '16', '--audio-chan', String(ach), '--pcm', '"$AF"', +]; const bmxLine = bmx .map((t) => (t.startsWith('"$') ? t : sh(t))) .join(' ');