Multistream Toggle 2 - #6166
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Several confirmed issues would cause inconsistent error handling and duplicate streaming status updates during live output editing (plus a couple of smaller correctness/documentation problems).
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Implements the next iteration of “Multistream Toggle” by expanding live output editing / stream-shift behavior across the streaming + restream services and updating the Go Live / Edit Stream UI to support mid-stream target updates with clearer checklist/error handling.
Changes:
- Adds live output editing–aware restream/streaming flows (target add/remove, display setup, error propagation, and reconciliation to live server targets).
- Updates Go Live / Edit Stream React UI (feature toggle cards, destination switchers, checklist steps, update cooldown UX, and “Manage Stream” entry point).
- Extends platform + i18n support (Kick gameName tracking, Twitch enhanced broadcasting gating, new live-output-editing strings, highlighter dismissable).
File summaries
| File | Description |
|---|---|
| app/styles/loader.less | Adds small spinner sizing. |
| app/services/streaming/streaming.ts | Live output editing streaming lifecycle + improved restream error handling. |
| app/services/streaming/streaming-view.ts | Gates/derives new streaming mode behaviors (live output editing, dual stream compatibility). |
| app/services/streaming/streaming-api.ts | Adds checklist state for custom destinations. |
| app/services/streaming/stream-error.ts | Adds/restyles restream error types and helper thrower. |
| app/services/settings/streaming/stream-settings.ts | Adds custom destination ID helper. |
| app/services/restream.ts | Live output editing + stream shift enhancements, ingest/target setup, and richer restream error typing. |
| app/services/platforms/twitch.ts | Disables enhanced broadcasting when live output editing is enabled. |
| app/services/platforms/kick.ts | Tracks Kick game id + name and hardens game search behavior. |
| app/services/dismissables.ts | Adds a new dismissable key and fixes dismiss-all iteration. |
| app/services/diagnostics.ts | Exposes last stream diagnostic record for stream-shift logic. |
| app/i18n/fallback.ts | Switches fallback bundle to new live-output-editing dictionary. |
| app/i18n/en-US/twitch.json | Adds enhanced broadcasting/live output editing string. |
| app/i18n/en-US/streaming.json | Removes deprecated enhanced broadcasting multistream string. |
| app/i18n/en-US/stream-shift.json | Adds “Switch Stream” string. |
| app/i18n/en-US/live-outputs.json | Removes old live-outputs dictionary. |
| app/i18n/en-US/live-output-editing.json | Adds new live output editing dictionary. |
| app/i18n/en-US/highlighter.json | Adds “Do not ask again” copy. |
| app/components-react/windows/go-live/useGoLiveSettings.ts | Edit-stream update handling, target diffing, and stream shift/live-output-editing exclusivity. |
| app/components-react/windows/go-live/SwitcherCard.tsx | Adds switch-level tooltip support and disabled styling. |
| app/components-react/windows/go-live/StreamShiftCard.tsx | New Stream Shift feature card and tooltip behavior. |
| app/components-react/windows/go-live/PlatformSettings.tsx | Reworks live settings cards area and section spacing. |
| app/components-react/windows/go-live/platforms/TwitchEditStreamInfo.tsx | Disables enhanced broadcasting under live output editing/update mode; tooltip updates. |
| app/components-react/windows/go-live/platforms/PlatformSettingsLayout.tsx | Extends platform params with live output editing state. |
| app/components-react/windows/go-live/LiveOutputEditingCard.tsx | New Live Output Editing feature card. |
| app/components-react/windows/go-live/GoLiveWindow.tsx | Stream shift prompt triggering reworked to use restream live status subscription. |
| app/components-react/windows/go-live/GoLiveSettings.tsx | Stream shift toggle gated behind live output editing feature flag. |
| app/components-react/windows/go-live/GoLiveInfoBanner.tsx | New reusable info banner wrapper for Go Live/Edit Stream. |
| app/components-react/windows/go-live/GoLiveError.tsx | Expands restream error-type coverage + improves message presentation. |
| app/components-react/windows/go-live/GoLiveChecklist.tsx | Adds Edit Stream checklist rendering for start/stop/continue targets/destinations. |
| app/components-react/windows/go-live/GoLive.m.less | Layout tweaks, button/spinner styles, and banner class rename. |
| app/components-react/windows/go-live/GameSelector.tsx | Updates Kick game selection to persist both id + name. |
| app/components-react/windows/go-live/EditStreamWindow.tsx | Major Edit Stream UI restructure + update cooldown UX. |
| app/components-react/windows/go-live/DestinationSwitchers.tsx | Adds disabled mode + prevents toggling off last platform per display orientation. |
| app/components-react/windows/go-live/DestinationSwitchers.m.less | Disabled card styling + tooltip wrapping fix. |
| app/components-react/windows/go-live/CommonPlatformFields.tsx | Disables common title editing when no eligible platforms exist mid-stream. |
| app/components-react/windows/go-live/AiHighlighterToggle.tsx | Adds dismissable banner behavior + update-mode handling. |
| app/components-react/windows/go-live/AiHighlighterToggle.m.less | Adds dismissable link styling. |
| app/components-react/shared/Spinner.tsx | Adds inline mode and size overrides. |
| app/components-react/shared/Spinner.m.less | Styles inline spinner layout. |
| app/components-react/shared/inputs/RadioInput.tsx | Allows per-option disabled state and icon styling. |
| app/components-react/shared/inputs/RadioInput.m.less | Styles disabled icons and single-option radius. |
| app/components-react/shared/DisplaySelector.tsx | Prevents changing display for live targets; dual-stream gating under live output editing. |
| app/components-react/root/StudioFooter.tsx | Adds “Manage Stream” button while live output editing is enabled and live. |
| app/components-react/root/StartStreamingButton.tsx | Routes stream-shift event handling through RestreamService + debounced checkIsLive. |
| app/components-react/root/LiveDock.tsx | Adds data-name to edit-stream icon for targeting/tests. |
Review details
Suppressed comments (2)
app/services/streaming/streaming.ts:2441
handleStartLiveOutputEditingStreamContextgenerates its own timestamp and has a redundantreturn;. Passing in the already-computedtimekeeps status timestamps consistent across signal handlers.
private handleStartLiveOutputEditingStreamContext(display: TDisplayType) {
this.SET_STREAMING_STATUS(EStreamingState.Live, display, new Date().toISOString());
this.streamingStatusChange.next(EStreamingState.Live);
return;
}
app/services/streaming/streaming.ts:3364
- After changing
handleStartLiveOutputEditingStreamContextto accept a timestamp, update this call site to pass the existingtimefrom the signal handler to avoid inconsistent status times.
if (this.isDisplayContext(context) && this.addingDisplayTargets.has(context)) {
this.addingDisplayTargets.delete(context);
this.handleStartLiveOutputEditingStreamContext(context);
this.numInstances++;
- Files reviewed: 8/8 changed files
- Comments generated: 5
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const streamKey = await this.resolveStreamKey(mode); | ||
|
|
||
| try { | ||
| // Fetch the key for this mode rather than deriving it, the same way `addTargets` does, so | ||
| // that targets are removed from the stream they were added to |
|
|
||
| // Await the settings for every display. Otherwise `beforeGoLive` resolves before the | ||
| // stream settings have been written and `createStreaming` reads stale values. | ||
| await Promise.allSettled( |
| if (context === 'horizontal') { | ||
| await this.handleStartStreaming(code, context); | ||
| } | ||
|
|
||
| if (context === 'vertical') { | ||
| } else if (context === 'vertical' && this.views.isLiveOutputEditingEnabled) { | ||
| this.handleStartLiveOutputEditingStreamContext('vertical'); | ||
| } else if (context === 'vertical') { |
| }, []); | ||
|
|
||
| useEffect(() => { | ||
| // 3-second countdown timer for cooldown after adding/removing targets |
| const streamError = createStreamError( | ||
| type, | ||
| resolvedType, | ||
| { status, statusText: $t('Multistream Error') + messages.join('. '), platform }, |
No description provided.