From 0f5163e26222f1db517d8f2d8a28d90d5a579bd1 Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Sat, 9 May 2026 17:15:37 -0400 Subject: [PATCH] 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. --- overlay/src/views/Edit/index.js | 46 +++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/overlay/src/views/Edit/index.js b/overlay/src/views/Edit/index.js index 02de4ed..dddda46 100644 --- a/overlay/src/views/Edit/index.js +++ b/overlay/src/views/Edit/index.js @@ -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) { + + + WebRTC ingest (WHIP) + + + + + + + + WebRTC output (WHEP)