diff --git a/services/mam-api/src/routes/recorders.js b/services/mam-api/src/routes/recorders.js index 491534b..60ea7a7 100644 --- a/services/mam-api/src/routes/recorders.js +++ b/services/mam-api/src/routes/recorders.js @@ -154,7 +154,7 @@ const RECORDER_FIELDS = [ 'proxy_audio_codec', 'proxy_audio_bitrate', 'proxy_audio_channels', 'proxy_container', 'project_id', 'node_id', 'device_index', - 'growing_enabled', 'label', + 'growing_enabled', 'growing_codec', 'label', ]; function pickRecorderFields(body) { diff --git a/services/web-ui/public/screens-ingest.jsx b/services/web-ui/public/screens-ingest.jsx index fd210a5..46c18e5 100644 --- a/services/web-ui/public/screens-ingest.jsx +++ b/services/web-ui/public/screens-ingest.jsx @@ -619,6 +619,7 @@ function RecorderConfigModal({ recorder, onClose, onSaved }) { const _seedBitrate = (recorder.recording_video_bitrate || (recorder.growing_enabled === true ? '50' : '25')).replace(/M$/i, ''); const [bitrate, setBitrate] = React.useState(_seedBitrate); const [growing, setGrowing] = React.useState(recorder.growing_enabled === true); + const [growingCodec, setGrowingCodec] = React.useState(recorder.growing_codec === 'hevc_nvenc' ? 'hevc_nvenc' : 'avci100'); const [projectId, setProjectId] = React.useState(recorder.project_id || PROJECTS[0]?.id || ''); const [saving, setSaving] = React.useState(false); const [err, setErr] = React.useState(null); @@ -636,6 +637,7 @@ function RecorderConfigModal({ recorder, onClose, onSaved }) { label: label.trim() || null, recording_codec: effCodec, growing_enabled: growing, + growing_codec: growing ? growingCodec : undefined, project_id: projectId || null, }; if (showBitrate && bitrate) body.recording_video_bitrate = String(bitrate).replace(/M$/i, '') + 'M'; @@ -706,7 +708,7 @@ function RecorderConfigModal({ recorder, onClose, onSaved }) {
{growing - ? 'Writes a growing XDCAM HD422 MXF (OP1a) to the SMB share so editors can cut the clip live in Premiere.' + ? 'Writes a growing master to the SMB share so editors can cut the clip live (codec selectable below).' : 'Encodes a GPU master (HEVC/H.264) streamed straight to the library on stop.'}
@@ -735,15 +737,31 @@ function RecorderConfigModal({ recorder, onClose, onSaved }) { )} ) : ( +
- + + +
+ {growingCodec === 'hevc_nvenc' + ? 'GPU-offloaded HEVC 10-bit 4:2:0 in fragmented MOV. Frees CPU. NOTE: not all editors import frag-MOV growing files.' + : 'CPU AVC-Intra 100, 4:2:2 10-bit, true 1080p59.94 in MXF OP1a. Premiere-native growing.'} +
+
+
+ setBitrate(e.target.value)} />
- Target bitrate of the growing MXF essence. Broadcast XDCAM HD422 is 50 Mbps; raise for higher quality. + Target bitrate of the growing essence. AVC-Intra 100 is ~226 Mbps; HEVC tunable.
+
)}
@@ -799,6 +817,7 @@ function _normRecorder(r) { res: r.recording_resolution || '·', framerate: r.recording_framerate || 'native', growing: r.growing_enabled === true, + growingCodec: r.growing_codec === 'hevc_nvenc' ? 'hevc_nvenc' : 'avci100', nodeId: r.node_id || null, node: r.node_id ? r.node_id.slice(0, 8) : 'primary', deviceIndex: portIdx ?? null, @@ -1107,7 +1126,13 @@ function RecorderRow({ recorder: initialRecorder, onRefresh, onConfigure, nodeOn {recorder.capturePort} )} - {recorder.growing && GROWING} + {recorder.growing && ( + + GROWING · {recorder.growingCodec === 'hevc_nvenc' ? 'GPU/HEVC' : 'CPU/AVCI'} + + )}
{recorder.codec}·