feat(ui): show + select growing codec (AVCI-100 CPU vs HEVC-NVENC GPU)
This commit is contained in:
parent
6af5d77d62
commit
f7447e6ec2
2 changed files with 30 additions and 5 deletions
|
|
@ -154,7 +154,7 @@ const RECORDER_FIELDS = [
|
||||||
'proxy_audio_codec', 'proxy_audio_bitrate', 'proxy_audio_channels',
|
'proxy_audio_codec', 'proxy_audio_bitrate', 'proxy_audio_channels',
|
||||||
'proxy_container',
|
'proxy_container',
|
||||||
'project_id', 'node_id', 'device_index',
|
'project_id', 'node_id', 'device_index',
|
||||||
'growing_enabled', 'label',
|
'growing_enabled', 'growing_codec', 'label',
|
||||||
];
|
];
|
||||||
|
|
||||||
function pickRecorderFields(body) {
|
function pickRecorderFields(body) {
|
||||||
|
|
|
||||||
|
|
@ -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 _seedBitrate = (recorder.recording_video_bitrate || (recorder.growing_enabled === true ? '50' : '25')).replace(/M$/i, '');
|
||||||
const [bitrate, setBitrate] = React.useState(_seedBitrate);
|
const [bitrate, setBitrate] = React.useState(_seedBitrate);
|
||||||
const [growing, setGrowing] = React.useState(recorder.growing_enabled === true);
|
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 [projectId, setProjectId] = React.useState(recorder.project_id || PROJECTS[0]?.id || '');
|
||||||
const [saving, setSaving] = React.useState(false);
|
const [saving, setSaving] = React.useState(false);
|
||||||
const [err, setErr] = React.useState(null);
|
const [err, setErr] = React.useState(null);
|
||||||
|
|
@ -636,6 +637,7 @@ function RecorderConfigModal({ recorder, onClose, onSaved }) {
|
||||||
label: label.trim() || null,
|
label: label.trim() || null,
|
||||||
recording_codec: effCodec,
|
recording_codec: effCodec,
|
||||||
growing_enabled: growing,
|
growing_enabled: growing,
|
||||||
|
growing_codec: growing ? growingCodec : undefined,
|
||||||
project_id: projectId || null,
|
project_id: projectId || null,
|
||||||
};
|
};
|
||||||
if (showBitrate && bitrate) body.recording_video_bitrate = String(bitrate).replace(/M$/i, '') + 'M';
|
if (showBitrate && bitrate) body.recording_video_bitrate = String(bitrate).replace(/M$/i, '') + 'M';
|
||||||
|
|
@ -706,7 +708,7 @@ function RecorderConfigModal({ recorder, onClose, onSaved }) {
|
||||||
</div>
|
</div>
|
||||||
<div className="rec-mode-hint">
|
<div className="rec-mode-hint">
|
||||||
{growing
|
{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.'}
|
: 'Encodes a GPU master (HEVC/H.264) streamed straight to the library on stop.'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -735,15 +737,31 @@ function RecorderConfigModal({ recorder, onClose, onSaved }) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
<div className="rec-cfg-grid">
|
||||||
<div className="field">
|
<div className="field">
|
||||||
<label className="field-label">XDCAM HD422 bitrate (Mbps)</label>
|
<label className="field-label">Growing codec</label>
|
||||||
|
<select className="field-input" value={growingCodec}
|
||||||
|
onChange={e => setGrowingCodec(e.target.value)} disabled={isRec}
|
||||||
|
style={{ appearance: 'auto' }}>
|
||||||
|
<option value="avci100">AVC-Intra 100 (CPU, MXF · Premiere-native)</option>
|
||||||
|
<option value="hevc_nvenc">HEVC all-intra (GPU/NVENC, frag-MOV)</option>
|
||||||
|
</select>
|
||||||
|
<div className="mono" style={{ fontSize: 10.5, color: 'var(--text-3)', marginTop: 4 }}>
|
||||||
|
{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.'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field">
|
||||||
|
<label className="field-label">Bitrate (Mbps)</label>
|
||||||
<input className="field-input" type="number" min="1" max="400" step="1"
|
<input className="field-input" type="number" min="1" max="400" step="1"
|
||||||
value={bitrate} disabled={isRec}
|
value={bitrate} disabled={isRec}
|
||||||
onChange={e => setBitrate(e.target.value)} />
|
onChange={e => setBitrate(e.target.value)} />
|
||||||
<div className="mono" style={{ fontSize: 10.5, color: 'var(--text-3)', marginTop: 4 }}>
|
<div className="mono" style={{ fontSize: 10.5, color: 'var(--text-3)', marginTop: 4 }}>
|
||||||
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.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="field">
|
<div className="field">
|
||||||
|
|
@ -799,6 +817,7 @@ function _normRecorder(r) {
|
||||||
res: r.recording_resolution || '·',
|
res: r.recording_resolution || '·',
|
||||||
framerate: r.recording_framerate || 'native',
|
framerate: r.recording_framerate || 'native',
|
||||||
growing: r.growing_enabled === true,
|
growing: r.growing_enabled === true,
|
||||||
|
growingCodec: r.growing_codec === 'hevc_nvenc' ? 'hevc_nvenc' : 'avci100',
|
||||||
nodeId: r.node_id || null,
|
nodeId: r.node_id || null,
|
||||||
node: r.node_id ? r.node_id.slice(0, 8) : 'primary',
|
node: r.node_id ? r.node_id.slice(0, 8) : 'primary',
|
||||||
deviceIndex: portIdx ?? null,
|
deviceIndex: portIdx ?? null,
|
||||||
|
|
@ -1107,7 +1126,13 @@ function RecorderRow({ recorder: initialRecorder, onRefresh, onConfigure, nodeOn
|
||||||
<Icon name="signal" size={10} style={{ marginRight: 4, verticalAlign: -1 }} />{recorder.capturePort}
|
<Icon name="signal" size={10} style={{ marginRight: 4, verticalAlign: -1 }} />{recorder.capturePort}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{recorder.growing && <span className="badge accent" title="Growing-file (edit-while-record)">GROWING</span>}
|
{recorder.growing && (
|
||||||
|
<span className="badge accent" title={recorder.growingCodec === 'hevc_nvenc'
|
||||||
|
? 'Growing-file · HEVC all-intra (NVENC GPU, fragmented MOV)'
|
||||||
|
: 'Growing-file · AVC-Intra 100 (CPU, MXF OP1a)'}>
|
||||||
|
GROWING · {recorder.growingCodec === 'hevc_nvenc' ? 'GPU/HEVC' : 'CPU/AVCI'}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="recorder-sub">
|
<div className="recorder-sub">
|
||||||
<span>{recorder.codec}</span><span className="recorder-sub-sep">·</span>
|
<span>{recorder.codec}</span><span className="recorder-sub-sep">·</span>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue