From 91e9b3196a66fcf84185b95b574301bae25dc328 Mon Sep 17 00:00:00 2001 From: KingKDot Date: Thu, 30 Jul 2026 14:39:10 -0500 Subject: [PATCH] default jpeg --- Overlord-Client/cmd/agent/capture/capture.go | 33 ++------------ .../cmd/agent/capture/h264_codec_test.go | 14 ++++++ Overlord-Server/public/assets/backstage.js | 39 +++++++--------- Overlord-Server/public/backstage.html | 12 +++-- .../src/server/ws-console-rd-backstage.ts | 45 +++---------------- 5 files changed, 47 insertions(+), 96 deletions(-) diff --git a/Overlord-Client/cmd/agent/capture/capture.go b/Overlord-Client/cmd/agent/capture/capture.go index d717451..b5268b1 100644 --- a/Overlord-Client/cmd/agent/capture/capture.go +++ b/Overlord-Client/cmd/agent/capture/capture.go @@ -1736,11 +1736,7 @@ func desktopCodec() string { } func backstageCodec() string { - codec := selectedCodec(&backstageOverrideCodec) - if codec == "hevc" { - return "jpeg" - } - return codec + return "jpeg" } func SetDesktopQualityAndCodec(quality int, codec string) { @@ -1792,36 +1788,15 @@ func SetDesktopQualityAndCodec(quality int, codec string) { } } -func SetBackstageQualityAndCodec(quality int, codec string) { - previousCodec := backstageCodec() +func SetBackstageQualityAndCodec(quality int, _ string) { if quality > 0 { if quality > 100 { quality = 100 } backstageOverrideQuality.Store(int64(quality)) } - s := strings.ToLower(strings.TrimSpace(codec)) - if s == "h264" && !h264Available() { - detail := h264AvailabilityDetail() - log.Printf("capture: requested backstage codec=h264 but unavailable (%s); forcing codec=jpeg", detail) - s = "jpeg" - } - switch s { - case "raw", "rgba", "jpeg", "h264": - backstageOverrideCodec.Store(s) - backstageH264WarnOnce = sync.Once{} - if s != "h264" { - resetH264Encoderbackstage() - } - if previousCodec != s && s == "h264" { - backstageLastKeyframe.Store(0) - webrtcpub.RequestKeyframe(webrtcpub.Kindbackstage) - } - case "": - default: - backstageOverrideCodec.Store("jpeg") - resetH264Encoderbackstage() - } + backstageOverrideCodec.Store("jpeg") + resetH264Encoderbackstage() } func Nowbackstage(ctx context.Context, env *rt.Env) error { diff --git a/Overlord-Client/cmd/agent/capture/h264_codec_test.go b/Overlord-Client/cmd/agent/capture/h264_codec_test.go index e18bffa..aaca938 100644 --- a/Overlord-Client/cmd/agent/capture/h264_codec_test.go +++ b/Overlord-Client/cmd/agent/capture/h264_codec_test.go @@ -77,6 +77,20 @@ func TestDesktopAndBackstageCodecSelectionsAreIndependent(t *testing.T) { } } +func TestBackstageCodecIsAlwaysJPEG(t *testing.T) { + t.Cleanup(resetCodecSelectionForTest) + + for _, requested := range []string{"", "raw", "rgba", "h264", "hevc", "invalid-codec"} { + SetBackstageQualityAndCodec(73, requested) + if got := backstageCodec(); got != "jpeg" { + t.Fatalf("backstage codec = %q after requesting %q, want jpeg", got, requested) + } + } + if got := backstageJPEGQuality(); got != 73 { + t.Fatalf("backstage quality = %d, want 73", got) + } +} + func TestSwitchingToH264RequestsRecoveryPoint(t *testing.T) { if !h264Available() { t.Skip("h264 is unavailable in this build") diff --git a/Overlord-Server/public/assets/backstage.js b/Overlord-Server/public/assets/backstage.js index 7a6c2ac..9dc855f 100644 --- a/Overlord-Server/public/assets/backstage.js +++ b/Overlord-Server/public/assets/backstage.js @@ -125,7 +125,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s const CANVAS_TRANSPORT_PREF_VERSION = 1; function getWebrtcMode() { - return webrtcMode ? String(webrtcMode.value || "off") : "off"; + return "off"; } function syncInputEnableState() { @@ -151,7 +151,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s let h264TimestampUs = 0; let h264AwaitingKeyframe = true; let h264RecoveryRequestedAt = 0; - let prefersH264 = typeof VideoDecoder === "function"; + let prefersH264 = false; const maxH264DecodeQueue = 4; const inputBackpressureBytes = 256 * 1024; let h264ErrorCount = 0; @@ -182,15 +182,13 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s savedDisplay = Number.isFinite(Number(settings.display)) ? Number(settings.display) : savedDisplay; setSelectValue(backstageResolutionSelect, settings.resolution); setSelectValue(targetFpsSelect, settings.targetFps); - setSelectValue(webrtcMode, settings.transportPreferenceVersion === CANVAS_TRANSPORT_PREF_VERSION ? settings.webrtcMode : "off"); + setSelectValue(webrtcMode, "off"); if (qualitySlider && settings.quality !== undefined) qualitySlider.value = String(settings.quality); if (mouseCtrl && typeof settings.mouse === "boolean") mouseCtrl.checked = settings.mouse; if (kbdCtrl && typeof settings.keyboard === "boolean") kbdCtrl.checked = settings.keyboard; if (clipboardSyncCtrl && typeof settings.clipboardSync === "boolean") clipboardSyncCtrl.checked = settings.clipboardSync; if (uiaCtrl && typeof settings.uia === "boolean") uiaCtrl.checked = settings.uia; - if (typeof settings.preferH264 === "boolean") { - prefersH264 = settings.preferH264 && typeof VideoDecoder === "function"; - } + prefersH264 = false; const cloneToggle = document.getElementById("backstageCloneToggle"); const cloneLiteToggle = document.getElementById("backstageCloneLiteToggle"); const killIfRunningToggle = document.getElementById("backstageKillIfRunningToggle"); @@ -208,8 +206,8 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s resolution: backstageResolutionSelect?.value || "1080", targetFps: Number(targetFpsSelect?.value || 120), quality: Number(qualitySlider?.value || 90), - preferH264: !!prefersH264, - webrtcMode: getWebrtcMode(), + preferH264: false, + webrtcMode: "off", transportPreferenceVersion: CANVAS_TRANSPORT_PREF_VERSION, mouse: !!mouseCtrl?.checked, keyboard: !!kbdCtrl?.checked, @@ -225,8 +223,12 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s const sharedSettingsSaver = createSharedUiSettingsSaver("backstage", readSharedSettings); if (codecH264) { - codecH264.checked = prefersH264; - codecH264.disabled = typeof VideoDecoder !== "function"; + codecH264.checked = false; + codecH264.disabled = true; + } + if (webrtcMode) { + webrtcMode.value = "off"; + webrtcMode.disabled = true; } function setCodecModeLabel(mode, detail) { @@ -235,7 +237,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s codecMode.textContent = `Codec: ${String(mode || "auto").toUpperCase()}${suffix}`; } - setCodecModeLabel(prefersH264 ? "h264" : "jpeg", "preferred"); + setCodecModeLabel("jpeg", "enforced"); setStreamState("connecting", "Connecting"); function updateFpsDisplay(agentValue) { @@ -1061,7 +1063,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s function pushQuality(val) { const q = Number(val) || 90; - const codec = q >= 100 ? "raw" : (prefersH264 ? "h264" : "jpeg"); + const codec = "jpeg"; console.debug("backstage: pushQuality val=", val, "q=", q, "codec=", codec); setCodecModeLabel(codec, "requested"); sendCmd("backstage_set_quality", { quality: q, codec }); @@ -1084,12 +1086,6 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s } function pushTransportQuality(mode) { - if (mode === "relayed" || mode === "p2p") { - const q = Number(qualitySlider?.value) || 90; - setCodecModeLabel("h264", "webrtc"); - sendCmd("backstage_set_quality", { quality: q, codec: "h264", source: "webrtc" }); - return; - } if (qualitySlider) { pushQuality(qualitySlider.value); } @@ -1097,10 +1093,9 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s if (codecH264) { codecH264.addEventListener("change", function () { - prefersH264 = !!codecH264.checked && typeof VideoDecoder === "function"; - if (!prefersH264) { - destroyVideoDecoder(); - } + prefersH264 = false; + codecH264.checked = false; + destroyVideoDecoder(); if (qualitySlider) { pushQuality(qualitySlider.value); } diff --git a/Overlord-Server/public/backstage.html b/Overlord-Server/public/backstage.html index a28290b..145faf7 100644 --- a/Overlord-Server/public/backstage.html +++ b/Overlord-Server/public/backstage.html @@ -152,10 +152,8 @@
- +
@@ -171,10 +169,10 @@
-
diff --git a/Overlord-Server/src/server/ws-console-rd-backstage.ts b/Overlord-Server/src/server/ws-console-rd-backstage.ts index 174631a..273cb4a 100644 --- a/Overlord-Server/src/server/ws-console-rd-backstage.ts +++ b/Overlord-Server/src/server/ws-console-rd-backstage.ts @@ -911,7 +911,7 @@ type backstageStreamingState = { }; function defaultbackstageStreamingState(): backstageStreamingState { - return { isStreaming: false, virtualMode: false, display: 0, quality: 90, codec: "", maxFps: 120, lastFps: 0 }; + return { isStreaming: false, virtualMode: false, display: 0, quality: 90, codec: "jpeg", maxFps: 120, lastFps: 0 }; } export const backstageStreamingState = new Map(); @@ -1279,26 +1279,9 @@ export function handlebackstageViewerMessage(ws: ServerWebSocket, ra sendbackstageCommand(target, "backstage_stop", {}); state.isStreaming = false; logger.debug(`[backstage] restarting stream to change virtual_mode=${state.virtualMode} -> ${virtualMode}`); - } + } if (!state.isStreaming) { - if ((payload as any).webrtc === true) { - const streamPath = webrtcStreamPathFor(clientId, "backstage"); - const token = issueWebrtcPublishToken(clientId); - sendbackstageCommand(target, "webrtc_publish", { - streamPath, - whipPath: `/api/webrtc/${streamPath}/whip`, - token, - kind: "backstage", - hasVideo: true, - hasAudio: false, - iceServers: issueTurnIceServers(`${clientId}:backstage:whip`), - }); - safeSendViewer(ws, { - type: "webrtc_ready", - streamPath, - whepPath: `/api/webrtc/${streamPath}/whep`, - }); - } + sendbackstageCommand(target, "backstage_set_quality", { quality: state.quality, codec: "jpeg" }); sendbackstageCommand(target, "backstage_set_fps", { fps: clampDesktopFps(state.maxFps) }); sendbackstageCommand(target, "backstage_start", { autoStartExplorer: false, @@ -1341,9 +1324,9 @@ export function handlebackstageViewerMessage(ws: ServerWebSocket, ra } case "backstage_set_quality": { const newQuality = Number(payload.quality) || 90; - const newCodec = String(payload.codec || "").toLowerCase(); - sendbackstageCommand(target, "backstage_set_quality", { quality: newQuality, codec: newCodec }); - if (state.quality !== newQuality || state.codec !== newCodec) { + const newCodec = "jpeg"; + sendbackstageCommand(target, "backstage_set_quality", { quality: newQuality, codec: newCodec }); + if (state.quality !== newQuality || state.codec !== newCodec) { state.quality = newQuality; state.codec = newCodec; backstageStreamingState.set(clientId, state); @@ -1512,24 +1495,10 @@ export function handlebackstageViewerMessage(ws: ServerWebSocket, ra break; } case "webrtc_p2p_offer": { - const sdp = typeof (payload as any).sdp === "string" ? (payload as any).sdp : ""; - if (!sdp) break; - const sessionId = createP2PSession(ws, clientId, "backstage"); - sendbackstageCommand(target, "webrtc_p2p_offer", { sessionId, sdp, kind: "backstage", hasVideo: true, hasAudio: false, iceServers: issueTurnIceServers(`${clientId}:backstage:${sessionId}`) }); + safeSendViewer(ws, { type: "error", reason: "Backstage supports JPEG canvas transport only" }); break; } case "webrtc_p2p_ice": { - const sessionId = getP2PSessionIdForViewer(ws); - if (!sessionId) break; - const candidate = typeof (payload as any).candidate === "string" ? (payload as any).candidate : ""; - if (!candidate) break; - sendbackstageCommand(target, "webrtc_p2p_ice", { - sessionId, - kind: "backstage", - candidate, - sdpMid: typeof (payload as any).sdpMid === "string" ? (payload as any).sdpMid : "", - sdpMLineIndex: Number((payload as any).sdpMLineIndex) || 0, - }); break; } case "webrtc_p2p_stop": {