replicas-computer 0.3.10 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3 -2
- package/dist/stream-viewer.js +63 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2937,7 +2937,7 @@ async function computerStatusCommand() {
|
|
|
2937
2937
|
}
|
|
2938
2938
|
|
|
2939
2939
|
// src/version.ts
|
|
2940
|
-
var COMPUTER_USE_VERSION = "0.3.
|
|
2940
|
+
var COMPUTER_USE_VERSION = "0.3.11";
|
|
2941
2941
|
var COMPUTER_USE_PROTOCOL_VERSION = 1;
|
|
2942
2942
|
|
|
2943
2943
|
// src/program.ts
|
|
@@ -3592,7 +3592,8 @@ var DESKTOP_WEBRTC_FAILURE_REASONS = {
|
|
|
3592
3592
|
codec_unsupported: "browser cannot receive H.264 over WebRTC",
|
|
3593
3593
|
negotiation_failed: "negotiation failed",
|
|
3594
3594
|
video_timeout: "WebRTC did not decode video in time",
|
|
3595
|
-
video_stalled: "WebRTC video stopped arriving"
|
|
3595
|
+
video_stalled: "WebRTC video stopped arriving",
|
|
3596
|
+
full_chroma_undecodable: "WebRTC could not decode H.264 High 4:4:4"
|
|
3596
3597
|
};
|
|
3597
3598
|
function isDesktopWebRtcFailure(value) {
|
|
3598
3599
|
if (!isRecord(value) || typeof value.reasonCode !== "string" || !Object.hasOwn(DESKTOP_WEBRTC_FAILURE_REASONS, value.reasonCode) || typeof value.turnConfigured !== "boolean") return false;
|
package/dist/stream-viewer.js
CHANGED
|
@@ -42,7 +42,8 @@ var DESKTOP_WEBRTC_FAILURE_REASONS = {
|
|
|
42
42
|
codec_unsupported: "browser cannot receive H.264 over WebRTC",
|
|
43
43
|
negotiation_failed: "negotiation failed",
|
|
44
44
|
video_timeout: "WebRTC did not decode video in time",
|
|
45
|
-
video_stalled: "WebRTC video stopped arriving"
|
|
45
|
+
video_stalled: "WebRTC video stopped arriving",
|
|
46
|
+
full_chroma_undecodable: "WebRTC could not decode H.264 High 4:4:4"
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
// src/input-validation.ts
|
|
@@ -99,6 +100,13 @@ diagnostics.classList.toggle("visible", showDiagnostics);
|
|
|
99
100
|
var webrtcFrameTimeoutMs = 6e3;
|
|
100
101
|
var webrtcSkipsAfterFailure = 3;
|
|
101
102
|
var pointerIntervalMs = 4;
|
|
103
|
+
var fullChromaFailureKey = "replicas-desktop-4:4:4-failed";
|
|
104
|
+
var skipFullChroma = false;
|
|
105
|
+
var fullChromaFailure;
|
|
106
|
+
try {
|
|
107
|
+
skipFullChroma = localStorage.getItem(fullChromaFailureKey) === navigator.userAgent;
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
102
110
|
var socket;
|
|
103
111
|
var config;
|
|
104
112
|
var transport;
|
|
@@ -397,38 +405,40 @@ var unlockAudio = () => {
|
|
|
397
405
|
});
|
|
398
406
|
});
|
|
399
407
|
};
|
|
408
|
+
var captureFailure = (reasonCode, current) => {
|
|
409
|
+
const captured = {
|
|
410
|
+
id: crypto.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
411
|
+
reasonCode,
|
|
412
|
+
elapsedMs: Math.round(performance.now() - connectionStartedAt),
|
|
413
|
+
connectionState: peer?.connectionState ?? "unavailable",
|
|
414
|
+
iceConnectionState: peer?.iceConnectionState ?? "unavailable",
|
|
415
|
+
iceGatheringState: peer?.iceGatheringState ?? "unavailable",
|
|
416
|
+
signalingState: peer?.signalingState ?? "unavailable",
|
|
417
|
+
iceTransportPolicy: request.iceTransportPolicy,
|
|
418
|
+
turnConfigured: current.iceServers?.some((server) => /^turns?:/i.test(server.urls)) ?? false,
|
|
419
|
+
serverVersion: current.serverVersion ?? "unknown",
|
|
420
|
+
serverUnavailableReason: current.webrtcUnavailableReason ?? "",
|
|
421
|
+
localCandidateTypes: [...localCandidateTypes].join(","),
|
|
422
|
+
remoteCandidateTypes: [...remoteCandidateTypes].join(","),
|
|
423
|
+
iceErrorCodes: [...iceErrorCodes].join(","),
|
|
424
|
+
candidateErrors,
|
|
425
|
+
errorName: negotiationErrorName,
|
|
426
|
+
path: route.path,
|
|
427
|
+
codec: route.codec,
|
|
428
|
+
framesDecoded: inbound?.framesDecoded ?? 0,
|
|
429
|
+
packetsReceived: inbound?.packetsReceived ?? 0,
|
|
430
|
+
packetsLost: inbound?.packetsLost ?? 0,
|
|
431
|
+
bytesReceived: inbound?.bytesReceived ?? 0,
|
|
432
|
+
lastFrameAgeMs: lastFrameAt ? Math.round(performance.now() - lastFrameAt) : -1,
|
|
433
|
+
encoderFps: telemetry?.encoder.fps ?? -1
|
|
434
|
+
};
|
|
435
|
+
state.lastWebRtcFailure = captured;
|
|
436
|
+
return captured;
|
|
437
|
+
};
|
|
400
438
|
var useFallback = (reasonCode, failed = false) => {
|
|
401
439
|
if (transport === "websocket" || !config) return;
|
|
402
440
|
const reason = reasonCode === "websocket_selected" ? "WebSocket transport selected" : reasonCode === "recent_failure" ? "recent WebRTC failure" : DESKTOP_WEBRTC_FAILURE_REASONS[reasonCode];
|
|
403
|
-
if (request.transport === "webrtc" && reasonCode !== "websocket_selected" && reasonCode !== "recent_failure")
|
|
404
|
-
failure = {
|
|
405
|
-
id: crypto.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
406
|
-
reasonCode,
|
|
407
|
-
elapsedMs: Math.round(performance.now() - connectionStartedAt),
|
|
408
|
-
connectionState: peer?.connectionState ?? "unavailable",
|
|
409
|
-
iceConnectionState: peer?.iceConnectionState ?? "unavailable",
|
|
410
|
-
iceGatheringState: peer?.iceGatheringState ?? "unavailable",
|
|
411
|
-
signalingState: peer?.signalingState ?? "unavailable",
|
|
412
|
-
iceTransportPolicy: request.iceTransportPolicy,
|
|
413
|
-
turnConfigured: config.iceServers?.some((server) => /^turns?:/i.test(server.urls)) ?? false,
|
|
414
|
-
serverVersion: config.serverVersion ?? "unknown",
|
|
415
|
-
serverUnavailableReason: config.webrtcUnavailableReason ?? "",
|
|
416
|
-
localCandidateTypes: [...localCandidateTypes].join(","),
|
|
417
|
-
remoteCandidateTypes: [...remoteCandidateTypes].join(","),
|
|
418
|
-
iceErrorCodes: [...iceErrorCodes].join(","),
|
|
419
|
-
candidateErrors,
|
|
420
|
-
errorName: negotiationErrorName,
|
|
421
|
-
path: route.path,
|
|
422
|
-
codec: route.codec,
|
|
423
|
-
framesDecoded: inbound?.framesDecoded ?? 0,
|
|
424
|
-
packetsReceived: inbound?.packetsReceived ?? 0,
|
|
425
|
-
packetsLost: inbound?.packetsLost ?? 0,
|
|
426
|
-
bytesReceived: inbound?.bytesReceived ?? 0,
|
|
427
|
-
lastFrameAgeMs: lastFrameAt ? Math.round(performance.now() - lastFrameAt) : -1,
|
|
428
|
-
encoderFps: telemetry?.encoder.fps ?? -1
|
|
429
|
-
};
|
|
430
|
-
state.lastWebRtcFailure = failure;
|
|
431
|
-
}
|
|
441
|
+
if (request.transport === "webrtc" && reasonCode !== "websocket_selected" && reasonCode !== "recent_failure") failure = captureFailure(reasonCode, config);
|
|
432
442
|
closePeer();
|
|
433
443
|
if (failed) webrtcSkips = webrtcSkipsAfterFailure;
|
|
434
444
|
note("fallback to socket", reason);
|
|
@@ -504,6 +514,10 @@ var negotiate = async (sdp) => {
|
|
|
504
514
|
try {
|
|
505
515
|
await pc.setRemoteDescription({ type: "offer", sdp });
|
|
506
516
|
if (peer !== pc) return;
|
|
517
|
+
if (skipFullChroma) {
|
|
518
|
+
const codecs = RTCRtpReceiver.getCapabilities("video")?.codecs.filter((codec) => h264ProfileLabel(codec.sdpFmtpLine ?? "") !== H264_PROFILES.high444.label);
|
|
519
|
+
if (codecs) pc.getTransceivers().find((transceiver) => transceiver.receiver.track.kind === "video")?.setCodecPreferences(codecs);
|
|
520
|
+
}
|
|
507
521
|
const answer = await pc.createAnswer();
|
|
508
522
|
if (peer !== pc) return;
|
|
509
523
|
await pc.setLocalDescription(answer);
|
|
@@ -573,7 +587,16 @@ var handleServerMessage = (message, viaSocket) => {
|
|
|
573
587
|
useFallback("recent_failure");
|
|
574
588
|
} else if (!transport) {
|
|
575
589
|
showStatus("Establishing connection\u2026", true);
|
|
576
|
-
webrtcDeadline ??= setTimeout(() =>
|
|
590
|
+
webrtcDeadline ??= setTimeout(() => {
|
|
591
|
+
if (skipFullChroma || !inbound?.packetsReceived || !route.codec.endsWith(H264_PROFILES.high444.label)) {
|
|
592
|
+
useFallback("video_timeout", true);
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
skipFullChroma = true;
|
|
596
|
+
if (config) fullChromaFailure = captureFailure("full_chroma_undecodable", config);
|
|
597
|
+
note("retrying WebRTC without 4:4:4");
|
|
598
|
+
socket?.close();
|
|
599
|
+
}, webrtcFrameTimeoutMs);
|
|
577
600
|
}
|
|
578
601
|
};
|
|
579
602
|
var handleServerText = (data, viaSocket) => {
|
|
@@ -794,6 +817,15 @@ var reportWebRtcStats = async (pc, stats) => {
|
|
|
794
817
|
lastFrameAt = now;
|
|
795
818
|
clearTimeout(webrtcDeadline);
|
|
796
819
|
webrtcDeadline = void 0;
|
|
820
|
+
if (fullChromaFailure) {
|
|
821
|
+
try {
|
|
822
|
+
localStorage.setItem(fullChromaFailureKey, navigator.userAgent);
|
|
823
|
+
} catch {
|
|
824
|
+
}
|
|
825
|
+
failure = fullChromaFailure;
|
|
826
|
+
fullChromaFailure = void 0;
|
|
827
|
+
announceTransport();
|
|
828
|
+
}
|
|
797
829
|
}
|
|
798
830
|
if (inbound && (inbound.id !== counters.id || counters.framesDecoded < inbound.framesDecoded)) inbound = void 0;
|
|
799
831
|
if (!inbound) inboundHistory = [];
|