Add WHIP ingest toggle to Edit page with _upsertProcess patch

- Import WHIPControl from misc/controls/WHIP
- Render WHIPControl bound to control.whip_ingest before the WHEP section
- Monkey-patch props.restreamer._upsertProcess in handleDone so that
  whip_ingest.enabled is injected into the main ingest process config
  before it reaches the Core API. The SDK's UpsertIngest does not
  forward control.whip_ingest, so this intercept is required.
- Note: enable (no trailing d) is used in UI state to match WHEP.js convention;
  it maps to enabled (with d) in the Core API JSON body.
This commit is contained in:
Zac Gaetano 2026-05-09 17:15:37 -04:00
parent ab8432d372
commit 0f5163e262

View file

@ -36,6 +36,7 @@ import RTMPControl from '../../misc/controls/RTMP';
import SnapshotControl from '../../misc/controls/Snapshot';
import SRTControl from '../../misc/controls/SRT';
import WHEPControl from '../../misc/controls/WHEP';
import WHIPControl from '../../misc/controls/WHIP';
import TabPanel from '../../misc/TabPanel';
import TabsVerticalGrid from '../../misc/TabsVerticalGrid';
@ -304,8 +305,29 @@ export default function Edit(props) {
return false;
}
// Create/update the ingest
let [, err] = await props.restreamer.UpsertIngest(_channelid, global, inputs, outputs, control);
// Monkey-patch _upsertProcess so that whip_ingest.enabled is injected
// into the main ingest process config before it reaches the Core API.
// The SDK's UpsertIngest does not forward control.whip_ingest, so we
// intercept here. The snapshot process is excluded from patching.
const origUpsertProcess = props.restreamer._upsertProcess.bind(props.restreamer);
props.restreamer._upsertProcess = async function whipPatchedUpsert(id, config) {
if (!id.endsWith('_snapshot') && !id.endsWith('_probe')) {
config.whip_ingest = {
enabled: !!(control.whip_ingest && control.whip_ingest.enable),
};
}
return origUpsertProcess(id, config);
};
// Create/update the ingest (patch is active during this call)
let upsertResult;
try {
upsertResult = await props.restreamer.UpsertIngest(_channelid, global, inputs, outputs, control);
} finally {
props.restreamer._upsertProcess = origUpsertProcess;
}
const [, err] = upsertResult;
if (err !== null) {
notify.Dispatch('error', 'save:ingest', i18n._(t`Failed to update ingest process (${err.message})`));
return false;
@ -318,9 +340,9 @@ export default function Edit(props) {
}
// Create/update the ingest snapshot process
[, err] = await props.restreamer.UpsertIngestSnapshot(_channelid, control);
if (err !== null) {
notify.Dispatch('error', 'save:ingest', i18n._(t`Failed to update ingest snapshot process (${err.message})`));
const [, snapErr] = await props.restreamer.UpsertIngestSnapshot(_channelid, control);
if (snapErr !== null) {
notify.Dispatch('error', 'save:ingest', i18n._(t`Failed to update ingest snapshot process (${snapErr.message})`));
}
// Create/update the player
@ -539,6 +561,20 @@ export default function Edit(props) {
<Grid item xs={12}>
<Divider />
</Grid>
<Grid item xs={12}>
<Typography variant="h3">
<Trans>WebRTC ingest (WHIP)</Trans>
</Typography>
</Grid>
<Grid item xs={12}>
<WHIPControl
settings={$data.control.whip_ingest || {}}
onChange={handleControlChange('whip_ingest')}
/>
</Grid>
<Grid item xs={12}>
<Divider />
</Grid>
<Grid item xs={12}>
<Typography variant="h3">
<Trans>WebRTC output (WHEP)</Trans>