-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathframeCodec.ts
More file actions
50 lines (47 loc) · 1.89 KB
/
Copy pathframeCodec.ts
File metadata and controls
50 lines (47 loc) · 1.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* Binary WebSocket frame envelope for voice audio.
*
* client → server : raw Opus chunk, no header. The server already
* knows the sender from the authenticated session.
*
* server → client : `[u8 nameLen][utf-8 username][opus bytes...]`
* — identifies the speaker so the receiver can
* route the chunk to the right per-sender
* `MediaSource` / `SourceBuffer`. Essential in
* room mode where multiple speakers can stream
* concurrently and a single binary WS frame
* would otherwise be ambiguous.
*
* 1-byte length prefix is enough: this sample's usernames are all
* <= 16 chars; even doubling that fits in a byte. Throw on >255 so
* we'd notice if anyone fed it wider data.
*
* Returns `null` from `decodeIncoming` for any malformed buffer
* (too short, length-prefix exceeds payload). Callers should drop
* the frame and continue.
*/
export function encodeIncoming(senderUsername: string, opus: Uint8Array): Uint8Array {
const nameBytes = new TextEncoder().encode(senderUsername);
if (nameBytes.length > 255) {
throw new Error(
`frame envelope: username '${senderUsername}' is ${nameBytes.length} bytes, max 255`,
);
}
const out = new Uint8Array(1 + nameBytes.length + opus.byteLength);
out[0] = nameBytes.length;
out.set(nameBytes, 1);
out.set(opus, 1 + nameBytes.length);
return out;
}
export type DecodedFrame = {
readonly sender: string;
readonly opus: Uint8Array;
};
export function decodeIncoming(buffer: Uint8Array): DecodedFrame | null {
if (buffer.byteLength < 1) return null;
const nameLen = buffer[0]!;
if (buffer.byteLength < 1 + nameLen) return null;
const sender = new TextDecoder().decode(buffer.subarray(1, 1 + nameLen));
const opus = buffer.subarray(1 + nameLen);
return { sender, opus };
}