@ozaiya/openclaw-channel 0.10.29 → 0.10.31
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 +140 -39
- 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 +28 -0
- package/dist/src/sandboxScreenCdp.js +417 -37
- package/dist/src/sandboxScreenCdp.js.map +1 -1
- package/dist/src/sandboxScreenH264.d.ts +26 -0
- package/dist/src/sandboxScreenH264.js +198 -0
- package/dist/src/sandboxScreenH264.js.map +1 -0
- package/dist/src/sandboxScreenRtc.d.ts +11 -0
- package/dist/src/sandboxScreenRtc.js +221 -63
- package/dist/src/sandboxScreenRtc.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 6184 H.264 RTP packetizer for WebRTC media tracks.
|
|
3
|
+
*
|
|
4
|
+
* The native capture addon (ScreenCaptureKit + VideoToolbox) emits one
|
|
5
|
+
* Annex-B access unit (one encoded frame, start-code delimited NAL units) per
|
|
6
|
+
* `onFrame` callback. To send it over a werift WebRTC video track we must
|
|
7
|
+
* convert each access unit into a sequence of RTP payloads:
|
|
8
|
+
*
|
|
9
|
+
* - Single NAL unit packet — NALU that fits in one RTP packet (type 1-23)
|
|
10
|
+
* - FU-A fragmentation — NALU too large for one RTP packet (type 28)
|
|
11
|
+
*
|
|
12
|
+
* We deliberately do NOT emit STAP-A aggregation packets: the consumer is a
|
|
13
|
+
* browser's native WebRTC depacketizer, which handles single-NAL + FU-A
|
|
14
|
+
* universally, and keeping SPS/PPS/IDR as separate single-NAL packets is
|
|
15
|
+
* simpler and equally correct.
|
|
16
|
+
*
|
|
17
|
+
* werift's RTCRtpSender rewrites ssrc / payloadType / sequenceNumber on send
|
|
18
|
+
* (see rtpSender.ts `sendRtp`), so the packetizer only needs to produce correct
|
|
19
|
+
* `marker` (set on the final packet of an access unit) and `timestamp`
|
|
20
|
+
* (90 kHz). We still supply a monotonic 16-bit sequence number — werift bases
|
|
21
|
+
* its sequence offset on the first packet it observes.
|
|
22
|
+
*/
|
|
23
|
+
import { RtpPacket, RtpHeader } from 'werift';
|
|
24
|
+
/** Conservative RTP payload size — keeps packets under the common 1280-byte
|
|
25
|
+
* path MTU after IP/UDP/SRTP/DTLS overhead, avoiding IP fragmentation. */
|
|
26
|
+
const RTP_MTU_PAYLOAD = 1200;
|
|
27
|
+
/** H.264 90 kHz RTP clock rate. */
|
|
28
|
+
export const H264_CLOCK_RATE = 90000;
|
|
29
|
+
/** NAL unit type for FU-A fragmentation units (RFC 6184 §5.8). */
|
|
30
|
+
const NALU_TYPE_FU_A = 28;
|
|
31
|
+
/** NAL unit type for IDR (instantaneous decoder refresh) slices — a keyframe. */
|
|
32
|
+
const NALU_TYPE_IDR = 5;
|
|
33
|
+
/** NAL unit type for sequence parameter set. */
|
|
34
|
+
const NALU_TYPE_SPS = 7;
|
|
35
|
+
/**
|
|
36
|
+
* Split an Annex-B byte stream (one access unit) into raw NAL units with the
|
|
37
|
+
* start codes (00 00 01 or 00 00 00 01) stripped. Each returned buffer begins
|
|
38
|
+
* with the 1-byte NAL header.
|
|
39
|
+
*/
|
|
40
|
+
export function splitNalUnits(annexB) {
|
|
41
|
+
const nalus = [];
|
|
42
|
+
const len = annexB.length;
|
|
43
|
+
// Find the offset of each start code.
|
|
44
|
+
let i = 0;
|
|
45
|
+
let naluStart = -1;
|
|
46
|
+
const isStartCode3 = (p) => p + 2 < len && annexB[p] === 0 && annexB[p + 1] === 0 && annexB[p + 2] === 1;
|
|
47
|
+
const isStartCode4 = (p) => p + 3 < len && annexB[p] === 0 && annexB[p + 1] === 0 && annexB[p + 2] === 0 && annexB[p + 3] === 1;
|
|
48
|
+
while (i < len) {
|
|
49
|
+
if (isStartCode4(i)) {
|
|
50
|
+
if (naluStart >= 0 && i > naluStart)
|
|
51
|
+
nalus.push(annexB.subarray(naluStart, i));
|
|
52
|
+
i += 4;
|
|
53
|
+
naluStart = i;
|
|
54
|
+
}
|
|
55
|
+
else if (isStartCode3(i)) {
|
|
56
|
+
if (naluStart >= 0 && i > naluStart)
|
|
57
|
+
nalus.push(annexB.subarray(naluStart, i));
|
|
58
|
+
i += 3;
|
|
59
|
+
naluStart = i;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
i++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (naluStart >= 0 && naluStart < len)
|
|
66
|
+
nalus.push(annexB.subarray(naluStart, len));
|
|
67
|
+
// If no start codes were found, treat the whole buffer as one NAL unit
|
|
68
|
+
// (some encoders emit AVCC-less raw NALUs). This keeps us robust.
|
|
69
|
+
if (nalus.length === 0 && len > 0)
|
|
70
|
+
nalus.push(annexB);
|
|
71
|
+
return nalus;
|
|
72
|
+
}
|
|
73
|
+
/** True if the access unit contains an IDR slice (i.e. is a keyframe). */
|
|
74
|
+
export function isKeyframeAccessUnit(annexB) {
|
|
75
|
+
for (const nalu of splitNalUnits(annexB)) {
|
|
76
|
+
const type = nalu[0] & 0x1f;
|
|
77
|
+
if (type === NALU_TYPE_IDR || type === NALU_TYPE_SPS)
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Stateful packetizer — owns the rolling RTP sequence number for one track.
|
|
84
|
+
*/
|
|
85
|
+
export class H264Packetizer {
|
|
86
|
+
/** 16-bit rolling sequence number; werift offsets from the first value. */
|
|
87
|
+
sequenceNumber;
|
|
88
|
+
payloadType;
|
|
89
|
+
ssrc;
|
|
90
|
+
constructor(opts) {
|
|
91
|
+
// werift overrides payloadType/ssrc on send; these are placeholders.
|
|
92
|
+
this.payloadType = opts?.payloadType ?? 96;
|
|
93
|
+
this.ssrc = opts?.ssrc ?? 0;
|
|
94
|
+
// Start from a fixed-but-arbitrary value; varying it is unnecessary since
|
|
95
|
+
// werift rewrites the on-wire sequence numbers.
|
|
96
|
+
this.sequenceNumber = (opts?.initialSequenceNumber ?? 0) & 0xffff;
|
|
97
|
+
}
|
|
98
|
+
nextSeq() {
|
|
99
|
+
const s = this.sequenceNumber;
|
|
100
|
+
this.sequenceNumber = (this.sequenceNumber + 1) & 0xffff;
|
|
101
|
+
return s;
|
|
102
|
+
}
|
|
103
|
+
makePacket(payload, timestamp, marker) {
|
|
104
|
+
const header = new RtpHeader({
|
|
105
|
+
version: 2,
|
|
106
|
+
payloadType: this.payloadType,
|
|
107
|
+
sequenceNumber: this.nextSeq(),
|
|
108
|
+
timestamp: timestamp >>> 0,
|
|
109
|
+
ssrc: this.ssrc,
|
|
110
|
+
marker,
|
|
111
|
+
});
|
|
112
|
+
return new RtpPacket(header, payload);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Packetize one Annex-B access unit into RTP packets.
|
|
116
|
+
* @param accessUnit Annex-B encoded frame (start-code delimited NALUs).
|
|
117
|
+
* @param rtpTimestamp 90 kHz RTP timestamp for this frame.
|
|
118
|
+
*/
|
|
119
|
+
packetize(accessUnit, rtpTimestamp) {
|
|
120
|
+
const nalus = splitNalUnits(accessUnit);
|
|
121
|
+
if (nalus.length === 0)
|
|
122
|
+
return [];
|
|
123
|
+
// Build the payloads first so we know which is the final one (marker bit).
|
|
124
|
+
const payloads = [];
|
|
125
|
+
for (const nalu of nalus) {
|
|
126
|
+
if (nalu.length <= RTP_MTU_PAYLOAD) {
|
|
127
|
+
// Single NAL unit packet — payload is the NALU verbatim.
|
|
128
|
+
payloads.push(nalu);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// FU-A fragmentation.
|
|
132
|
+
const naluHeader = nalu[0];
|
|
133
|
+
const fIndicator = naluHeader & 0xe0; // F + NRI bits
|
|
134
|
+
const naluType = naluHeader & 0x1f;
|
|
135
|
+
const body = nalu.subarray(1); // drop the 1-byte NAL header
|
|
136
|
+
const chunkSize = RTP_MTU_PAYLOAD - 2; // 2 bytes FU indicator + FU header
|
|
137
|
+
const total = Math.ceil(body.length / chunkSize);
|
|
138
|
+
for (let f = 0; f < total; f++) {
|
|
139
|
+
const start = f === 0 ? 1 : 0;
|
|
140
|
+
const end = f === total - 1 ? 1 : 0;
|
|
141
|
+
const fuIndicator = fIndicator | NALU_TYPE_FU_A;
|
|
142
|
+
const fuHeader = (start << 7) | (end << 6) | naluType; // R bit = 0
|
|
143
|
+
const slice = body.subarray(f * chunkSize, (f + 1) * chunkSize);
|
|
144
|
+
payloads.push(Buffer.concat([Buffer.from([fuIndicator, fuHeader]), slice]));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const ts = rtpTimestamp >>> 0;
|
|
149
|
+
const lastIndex = payloads.length - 1;
|
|
150
|
+
return payloads.map((p, idx) => this.makePacket(p, ts, idx === lastIndex));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=h264Packetizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"h264Packetizer.js","sourceRoot":"","sources":["../../src/h264Packetizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,18 @@ export interface CdpScreencastOptions {
|
|
|
15
15
|
width: number;
|
|
16
16
|
height: number;
|
|
17
17
|
}) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Pointer moved/clicked inside the sandbox page (viewport CSS px — 1:1 with
|
|
20
|
+
* frame pixels at dpr=1). Sourced from a page-injected listener, so it sees
|
|
21
|
+
* BOTH the agent's synthetic CDP input and viewer takeover input. JPEG/H.264
|
|
22
|
+
* frames carry no pointer at all (headless screenshots have no OS cursor),
|
|
23
|
+
* so this is the viewer's only way to draw one. `shape` is the CSS cursor
|
|
24
|
+
* under the pointer, reported only when it changes (hover affordance).
|
|
25
|
+
*/
|
|
26
|
+
onCursor?: (x: number, y: number, click: boolean, shape?: string) => void;
|
|
27
|
+
/** Text copied/cut inside the sandbox page (same probe) — the sandbox
|
|
28
|
+
* clipboard is unreachable any other way. */
|
|
29
|
+
onClipboard?: (text: string) => void;
|
|
18
30
|
quality?: number;
|
|
19
31
|
minIntervalMs?: number;
|
|
20
32
|
/**
|
|
@@ -38,3 +50,19 @@ export interface CdpScreencastOptions {
|
|
|
38
50
|
};
|
|
39
51
|
}
|
|
40
52
|
export declare function createCdpScreencast(opts: CdpScreencastOptions): Promise<CdpScreencast | null>;
|
|
53
|
+
export interface SharedViewerHooks {
|
|
54
|
+
onFrame: (jpeg: Buffer) => void;
|
|
55
|
+
onCursor?: (x: number, y: number, click: boolean, shape?: string) => void;
|
|
56
|
+
onClipboard?: (text: string) => void;
|
|
57
|
+
getQuality?: () => number;
|
|
58
|
+
getMinIntervalMs?: () => number;
|
|
59
|
+
getBackpressure?: () => number;
|
|
60
|
+
}
|
|
61
|
+
export declare function acquireCdpScreencast(opts: {
|
|
62
|
+
host: string;
|
|
63
|
+
port: number;
|
|
64
|
+
quality?: number;
|
|
65
|
+
minIntervalMs?: number;
|
|
66
|
+
log?: CdpScreencastOptions["log"];
|
|
67
|
+
}, viewerId: string, hooks: SharedViewerHooks): Promise<CdpScreencast | null>;
|
|
68
|
+
export declare function releaseCdpScreencast(host: string, port: number, viewerId: string): void;
|