fix(capture): working All-Intra HEVC NVENC config (validated on L4)
NVENC rejects -g 1 ("GopLength > numBFrames+1" at InitializeEncoder), so
true all-intra is achieved with -bf 0 -forced-idr 1 -g 600 plus
-force_key_frames expr:1 (forces an IDR on every frame). ffprobe confirms
all frames are pict_type=I. Container is fragmented MOV; MXF muxing of HEVC
fails on this ffmpeg build ("Operation not permitted").
Validated end-to-end via direct ffmpeg on zampp2/L4:
hevc, Main 10, 1920x1080, yuv420p10le, ptypes=[IIIIII...]
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f2542bc929
commit
9210b41589
1 changed files with 21 additions and 8 deletions
|
|
@ -29,15 +29,28 @@ const VIDEO_CODECS = {
|
||||||
h264_nvenc: { args: ['-c:v', 'h264_nvenc', '-preset', 'p5'], bitrateControl: true, pixFmt: 'yuv420p' },
|
h264_nvenc: { args: ['-c:v', 'h264_nvenc', '-preset', 'p5'], bitrateControl: true, pixFmt: 'yuv420p' },
|
||||||
h265: { args: ['-c:v', 'libx265', '-preset', 'medium'], bitrateControl: true, pixFmt: 'yuv420p' },
|
h265: { args: ['-c:v', 'libx265', '-preset', 'medium'], bitrateControl: true, pixFmt: 'yuv420p' },
|
||||||
// All-Intra HEVC on NVENC — the growing-file master codec.
|
// All-Intra HEVC on NVENC — the growing-file master codec.
|
||||||
// -g 1 -bf 0: every frame is an IDR (all-intra), no B-frames.
|
// Goal: every frame an IDR (all-intra), so a still-growing file is decodable
|
||||||
// Required for growing-file edit-while-record (partial file must be
|
// to its last complete frame — the prerequisite for edit-while-record.
|
||||||
// decodable to the last complete frame without a full GOP).
|
//
|
||||||
// -rc vbr: variable bitrate; pair with a high target bitrate (100–160 Mbps
|
// NVENC will NOT accept `-g 1`: InitializeEncoder enforces
|
||||||
// for 1080i) to rival ProRes HQ quality.
|
// "GopLength > numBFrames + 1", so with -bf 0 the minimum GOP is 2 and -g 1
|
||||||
// -profile:v main10 / p010le: 10-bit 4:2:0 — the closest NVENC HEVC can
|
// is rejected with EINVAL (validated on the L4, driver 595). The working
|
||||||
// get to ProRes 4:2:2 10-bit. If strict 4:2:2 is needed, use prores_hq.
|
// recipe for true all-intra is therefore:
|
||||||
|
// -bf 0 no B-frames
|
||||||
|
// -g 600 large GOP just to satisfy the init check
|
||||||
|
// -forced-idr 1 forced keyframes are emitted as IDR
|
||||||
|
// -force_key_frames expr:1 force a keyframe on EVERY frame
|
||||||
|
// → ffprobe confirms pict_type = I for all frames.
|
||||||
|
//
|
||||||
|
// Container: fragmented MOV (+frag_keyframe+empty_moov+default_base_moof),
|
||||||
|
// NOT MXF — this ffmpeg's MXF muxer rejects HEVC ("Operation not permitted").
|
||||||
|
// The frag-MOV index is not deferred to EOF, so the file stays readable while
|
||||||
|
// growing. (See docs/design/2026-05-29-all-intra-hevc-ingest.md §8.)
|
||||||
|
//
|
||||||
|
// -profile:v main10 / p010le: 10-bit 4:2:0 — the closest NVENC HEVC can get
|
||||||
|
// to ProRes 4:2:2 10-bit. If strict 4:2:2 is required, use prores_hq (CPU).
|
||||||
hevc_nvenc: {
|
hevc_nvenc: {
|
||||||
args: ['-c:v', 'hevc_nvenc', '-preset', 'p4', '-rc', 'vbr', '-g', '1', '-bf', '0', '-profile:v', 'main10'],
|
args: ['-c:v', 'hevc_nvenc', '-preset', 'p4', '-rc', 'vbr', '-bf', '0', '-forced-idr', '1', '-g', '600', '-force_key_frames', 'expr:1', '-profile:v', 'main10'],
|
||||||
bitrateControl: true,
|
bitrateControl: true,
|
||||||
pixFmt: 'p010le',
|
pixFmt: 'p010le',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue