@ozaiya/openclaw-channel 0.10.29 → 0.10.30
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/src/api.d.ts +6 -2
- package/dist/src/api.js +7 -3
- package/dist/src/api.js.map +1 -1
- package/dist/src/channel.js +19 -2
- package/dist/src/channel.js.map +1 -1
- package/dist/src/crypto.d.ts +13 -0
- package/dist/src/crypto.js +21 -0
- package/dist/src/crypto.js.map +1 -1
- package/dist/src/gateway.js +72 -16
- package/dist/src/gateway.js.map +1 -1
- package/dist/src/h264Packetizer.d.ts +55 -0
- package/dist/src/h264Packetizer.js +153 -0
- package/dist/src/h264Packetizer.js.map +1 -0
- package/dist/src/sandboxScreenCdp.d.ts +8 -0
- package/dist/src/sandboxScreenCdp.js +37 -0
- package/dist/src/sandboxScreenCdp.js.map +1 -1
- package/dist/src/sandboxScreenH264.d.ts +26 -0
- package/dist/src/sandboxScreenH264.js +184 -0
- package/dist/src/sandboxScreenH264.js.map +1 -0
- package/dist/src/sandboxScreenRtc.d.ts +11 -0
- package/dist/src/sandboxScreenRtc.js +164 -59
- package/dist/src/sandboxScreenRtc.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,14 +9,23 @@
|
|
|
9
9
|
* stateless self-contained JPEGs, so they render cleanly over the DataChannel
|
|
10
10
|
* (unlike the old stateful VNC/RFB stream, which stalled).
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* On top of the DataChannel, when the gateway has a working ffmpeg (enableVideo)
|
|
13
|
+
* and the viewer's offer includes an m=video section, we ALSO answer with a
|
|
14
|
+
* sendonly H.264 media track — the JPEG poll then feeds an ffmpeg transcoder and
|
|
15
|
+
* the video rides RTP/SRTP with native browser decode (mirrors the machine-screen
|
|
16
|
+
* daemon's proven werift media mode). Inter-frame compression carries ~20fps where
|
|
17
|
+
* independent JPEGs managed ~10 on the same uplink. Ladder: H.264 media track →
|
|
18
|
+
* JPEG DataChannel → JPEG relay.
|
|
19
|
+
*
|
|
20
|
+
* Transport ladder fallback is automatic: if the channel never opens or drops, the
|
|
21
|
+
* relay (kept connected as the signaling pipe) resumes carrying frames. Signaling
|
|
22
|
+
* rides the existing sandbox-screen relay WS as JSON **text**; the server never has
|
|
23
|
+
* to parse anything.
|
|
16
24
|
*
|
|
17
25
|
* The viewer is the OFFERER (mirrors the machine-screen path); this plugin is the
|
|
18
|
-
* ANSWERER.
|
|
19
|
-
*
|
|
26
|
+
* ANSWERER. The peer connection is built lazily when the offer arrives, so codec
|
|
27
|
+
* config can depend on what the viewer offered. `werift` is pure-TS (no native
|
|
28
|
+
* build) and loaded lazily, so a gateway without it simply keeps using the relay.
|
|
20
29
|
*/
|
|
21
30
|
import { createRequire } from "node:module";
|
|
22
31
|
const esmRequire = createRequire(import.meta.url);
|
|
@@ -32,6 +41,27 @@ function getWerift() {
|
|
|
32
41
|
}
|
|
33
42
|
return weriftModule;
|
|
34
43
|
}
|
|
44
|
+
let packetizerModule;
|
|
45
|
+
function getPacketizer() {
|
|
46
|
+
if (packetizerModule === undefined) {
|
|
47
|
+
try {
|
|
48
|
+
// Static import would make werift a hard dependency of the plugin entry;
|
|
49
|
+
// resolved lazily so a werift-less install still loads (relay-only).
|
|
50
|
+
packetizerModule = esmRequire("./h264Packetizer.js");
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
packetizerModule = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return packetizerModule;
|
|
57
|
+
}
|
|
58
|
+
const H264_RTCP_FEEDBACK = [
|
|
59
|
+
{ type: "nack" },
|
|
60
|
+
{ type: "nack", parameter: "pli" },
|
|
61
|
+
{ type: "goog-remb" },
|
|
62
|
+
{ type: "transport-cc" },
|
|
63
|
+
{ type: "ccm", parameter: "fir" },
|
|
64
|
+
];
|
|
35
65
|
/**
|
|
36
66
|
* Create an answerer WebRTC session for one viewer. Returns null when werift is
|
|
37
67
|
* unavailable so the caller transparently falls back to the relay pipe.
|
|
@@ -45,78 +75,132 @@ export function createSandboxRtcSession(opts) {
|
|
|
45
75
|
const iceServers = opts.iceServers && opts.iceServers.length
|
|
46
76
|
? opts.iceServers
|
|
47
77
|
: [{ urls: "stun:stun.l.google.com:19302" }];
|
|
48
|
-
let pc;
|
|
78
|
+
let pc = null;
|
|
49
79
|
let dc = null;
|
|
50
80
|
let active = false;
|
|
51
81
|
let closed = false;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
pc.onIceCandidate.subscribe((candidate) => {
|
|
60
|
-
if (!candidate || closed)
|
|
82
|
+
let mediaReady = false;
|
|
83
|
+
let videoTrack = null;
|
|
84
|
+
let packetizer = null;
|
|
85
|
+
let tsBaseNs = null;
|
|
86
|
+
const earlyIce = []; // candidates that beat the offer
|
|
87
|
+
const setMediaReady = (ready) => {
|
|
88
|
+
if (mediaReady === ready)
|
|
61
89
|
return;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
mediaReady = ready;
|
|
91
|
+
opts.onMediaStateChange?.(ready);
|
|
92
|
+
};
|
|
93
|
+
/** Build the peer once the offer is known (codec config depends on it). */
|
|
94
|
+
function buildPeer(offerSdp) {
|
|
95
|
+
const pkt = getPacketizer();
|
|
96
|
+
const wantsVideo = !!opts.enableVideo && /\bm=video\b/.test(offerSdp) && !!pkt;
|
|
97
|
+
const config = { iceServers };
|
|
98
|
+
if (wantsVideo) {
|
|
99
|
+
config.codecs = {
|
|
100
|
+
video: [
|
|
101
|
+
new werift.RTCRtpCodecParameters({
|
|
102
|
+
mimeType: "video/H264",
|
|
103
|
+
clockRate: 90000,
|
|
104
|
+
rtcpFeedback: H264_RTCP_FEEDBACK,
|
|
105
|
+
parameters: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f",
|
|
106
|
+
}),
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
config.headerExtensions = {
|
|
110
|
+
video: [werift.useSdesMid(), werift.useAbsSendTime(), werift.useTransportWideCC()],
|
|
111
|
+
};
|
|
76
112
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
113
|
+
pc = new werift.RTCPeerConnection(config);
|
|
114
|
+
if (wantsVideo && pkt) {
|
|
115
|
+
videoTrack = new werift.MediaStreamTrack({ kind: "video" });
|
|
116
|
+
const transceiver = pc.addTransceiver(videoTrack, { direction: "sendonly" });
|
|
117
|
+
packetizer = new pkt.H264Packetizer();
|
|
118
|
+
// Viewer lost frames it can't recover via NACK — with a ≤1s GOP the next
|
|
119
|
+
// IDR lands soon, so PLI is informational here.
|
|
120
|
+
transceiver.sender.onPictureLossIndication.subscribe(() => {
|
|
121
|
+
opts.log?.info?.("[sandbox-rtc] PLI from viewer (next keyframe ≤1s away)");
|
|
122
|
+
});
|
|
123
|
+
opts.log?.info?.("[sandbox-rtc] answering with sendonly H.264 track");
|
|
124
|
+
}
|
|
125
|
+
pc.onIceCandidate.subscribe((candidate) => {
|
|
126
|
+
if (!candidate || closed)
|
|
83
127
|
return;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
128
|
+
opts.sendSignal(JSON.stringify({
|
|
129
|
+
type: "rtc-ice",
|
|
130
|
+
candidate: JSON.stringify({
|
|
131
|
+
candidate: candidate.candidate,
|
|
132
|
+
sdpMid: candidate.sdpMid ?? null,
|
|
133
|
+
sdpMLineIndex: candidate.sdpMLineIndex ?? null,
|
|
134
|
+
}),
|
|
135
|
+
}));
|
|
90
136
|
});
|
|
91
|
-
|
|
92
|
-
if (
|
|
137
|
+
pc.connectionStateChange.subscribe((state) => {
|
|
138
|
+
if (closed)
|
|
93
139
|
return;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (!closed)
|
|
140
|
+
if (state === "connected") {
|
|
141
|
+
if (videoTrack)
|
|
142
|
+
setMediaReady(true);
|
|
143
|
+
}
|
|
144
|
+
else if (state === "failed" || state === "closed" || state === "disconnected") {
|
|
145
|
+
setMediaReady(false);
|
|
146
|
+
// Terminal failure before the channel ever opened → let the caller keep
|
|
147
|
+
// the relay alive (it does anyway). 'disconnected' may recover.
|
|
148
|
+
if ((state === "failed" || state === "closed") && !active)
|
|
104
149
|
opts.onClosed();
|
|
105
150
|
}
|
|
106
151
|
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
152
|
+
pc.onDataChannel.subscribe((channel) => {
|
|
153
|
+
dc = channel;
|
|
154
|
+
opts.log?.info?.(`[sandbox-rtc] onDataChannel readyState=${channel.readyState}`);
|
|
155
|
+
channel.onMessage.subscribe((msg) => {
|
|
156
|
+
if (closed)
|
|
157
|
+
return;
|
|
158
|
+
// Preserve text vs binary: text = JSON control (input/viewport), binary =
|
|
159
|
+
// the app's compact input encoding.
|
|
160
|
+
if (typeof msg === "string")
|
|
161
|
+
opts.onData(msg);
|
|
162
|
+
else
|
|
163
|
+
opts.onData(Buffer.isBuffer(msg) ? msg : Buffer.from(msg));
|
|
164
|
+
});
|
|
165
|
+
const markOpen = () => {
|
|
166
|
+
if (active || closed)
|
|
167
|
+
return;
|
|
168
|
+
active = true;
|
|
169
|
+
opts.log?.info?.("[sandbox-rtc] DataChannel open — P2P carrying the screencast");
|
|
170
|
+
opts.onActive();
|
|
171
|
+
};
|
|
172
|
+
channel.stateChanged.subscribe((state) => {
|
|
173
|
+
if (state === "open")
|
|
174
|
+
markOpen();
|
|
175
|
+
else if (state === "closed") {
|
|
176
|
+
active = false;
|
|
177
|
+
if (!closed)
|
|
178
|
+
opts.onClosed();
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// werift may hand over an ALREADY-open channel (more likely over the slower
|
|
182
|
+
// TURN-relayed path) — stateChanged won't re-fire 'open', so check now.
|
|
183
|
+
if (channel.readyState === "open")
|
|
184
|
+
markOpen();
|
|
185
|
+
});
|
|
186
|
+
}
|
|
112
187
|
async function handleOffer(sdp) {
|
|
188
|
+
if (!pc)
|
|
189
|
+
buildPeer(sdp);
|
|
113
190
|
await pc.setRemoteDescription({ type: "offer", sdp });
|
|
114
191
|
const answer = await pc.createAnswer();
|
|
115
192
|
await pc.setLocalDescription(answer);
|
|
116
193
|
opts.sendSignal(JSON.stringify({ type: "rtc-answer", sdp: pc.localDescription?.sdp ?? answer.sdp }));
|
|
194
|
+
for (const c of earlyIce.splice(0)) {
|
|
195
|
+
pc.addIceCandidate(c).catch(() => { });
|
|
196
|
+
}
|
|
117
197
|
}
|
|
118
198
|
async function handleIce(candidate) {
|
|
119
199
|
const parsed = typeof candidate === "string" ? JSON.parse(candidate) : candidate;
|
|
200
|
+
if (!pc) {
|
|
201
|
+
earlyIce.push(parsed);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
120
204
|
await pc.addIceCandidate(parsed);
|
|
121
205
|
}
|
|
122
206
|
return {
|
|
@@ -156,9 +240,30 @@ export function createSandboxRtcSession(opts) {
|
|
|
156
240
|
return 0;
|
|
157
241
|
}
|
|
158
242
|
},
|
|
243
|
+
isMediaReady: () => mediaReady && !closed,
|
|
244
|
+
sendVideoFrame: (accessUnit) => {
|
|
245
|
+
if (closed || !mediaReady || !videoTrack || !packetizer)
|
|
246
|
+
return false;
|
|
247
|
+
const now = process.hrtime.bigint();
|
|
248
|
+
if (tsBaseNs === null)
|
|
249
|
+
tsBaseNs = now;
|
|
250
|
+
// 90 kHz RTP timestamp from a monotonic clock — inter-frame spacing stays
|
|
251
|
+
// accurate regardless of the (backpressure-varying) capture rate.
|
|
252
|
+
const rtpTs = Number(((now - tsBaseNs) * 90000n) / 1000000000n) >>> 0;
|
|
253
|
+
try {
|
|
254
|
+
for (const p of packetizer.packetize(accessUnit, rtpTs)) {
|
|
255
|
+
videoTrack.writeRtp(p);
|
|
256
|
+
}
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
},
|
|
159
263
|
close: () => {
|
|
160
264
|
closed = true;
|
|
161
265
|
active = false;
|
|
266
|
+
setMediaReady(false);
|
|
162
267
|
try {
|
|
163
268
|
dc?.close?.();
|
|
164
269
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandboxScreenRtc.js","sourceRoot":"","sources":["../../src/sandboxScreenRtc.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sandboxScreenRtc.js","sourceRoot":"","sources":["../../src/sandboxScreenRtc.ts"],"names":[],"mappings":"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"}
|