@agentdance/node-webrtc-sdp 1.0.0

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.
@@ -0,0 +1,4 @@
1
+ import type { SessionDescription, IceCandidate } from './types.js';
2
+ export declare function serializeCandidate(c: IceCandidate): string;
3
+ export declare function serialize(desc: SessionDescription): string;
4
+ //# sourceMappingURL=serializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAElB,YAAY,EAGb,MAAM,YAAY,CAAC;AAMpB,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAoB1D;AA2ID,wBAAgB,SAAS,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAyB1D"}
@@ -0,0 +1,158 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Candidate serializer (exported for standalone use)
3
+ // ---------------------------------------------------------------------------
4
+ export function serializeCandidate(c) {
5
+ let line = `${c.foundation} ${c.component} ${c.transport} ${c.priority} ` +
6
+ `${c.address} ${c.port} typ ${c.type}`;
7
+ if (c.relatedAddress !== undefined)
8
+ line += ` raddr ${c.relatedAddress}`;
9
+ if (c.relatedPort !== undefined)
10
+ line += ` rport ${c.relatedPort}`;
11
+ if (c.tcpType !== undefined)
12
+ line += ` tcptype ${c.tcpType}`;
13
+ if (c.generation !== undefined)
14
+ line += ` generation ${c.generation}`;
15
+ if (c.ufrag !== undefined)
16
+ line += ` ufrag ${c.ufrag}`;
17
+ if (c.networkId !== undefined)
18
+ line += ` network-id ${c.networkId}`;
19
+ if (c.networkCost !== undefined)
20
+ line += ` network-cost ${c.networkCost}`;
21
+ if (c.extensions) {
22
+ for (const [k, v] of Object.entries(c.extensions)) {
23
+ line += ` ${k} ${v}`;
24
+ }
25
+ }
26
+ return line;
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Helpers
30
+ // ---------------------------------------------------------------------------
31
+ function serializeRtcpAttr(r) {
32
+ if (r.networkType !== undefined &&
33
+ r.addressType !== undefined &&
34
+ r.address !== undefined) {
35
+ return `${r.port} ${r.networkType} ${r.addressType} ${r.address}`;
36
+ }
37
+ return `${r.port}`;
38
+ }
39
+ function serializeExtmap(e) {
40
+ const idPart = e.direction !== undefined ? `${e.id}/${e.direction}` : `${e.id}`;
41
+ let s = `${idPart} ${e.uri}`;
42
+ if (e.attributes !== undefined)
43
+ s += ` ${e.attributes}`;
44
+ return s;
45
+ }
46
+ function serializeMedia(m) {
47
+ const lines = [];
48
+ const ptStr = m.payloadTypes.join(' ');
49
+ lines.push(`m=${m.type} ${m.port} ${m.protocol} ${ptStr}`);
50
+ if (m.connection) {
51
+ lines.push(`c=${m.connection.networkType} ${m.connection.addressType} ${m.connection.address}`);
52
+ }
53
+ if (m.bandwidth) {
54
+ lines.push(`b=${m.bandwidth.type}:${m.bandwidth.bandwidth}`);
55
+ }
56
+ if (m.rtcp) {
57
+ lines.push(`a=rtcp:${serializeRtcpAttr(m.rtcp)}`);
58
+ }
59
+ if (m.iceUfrag !== undefined)
60
+ lines.push(`a=ice-ufrag:${m.iceUfrag}`);
61
+ if (m.icePwd !== undefined)
62
+ lines.push(`a=ice-pwd:${m.icePwd}`);
63
+ if (m.iceOptions !== undefined)
64
+ lines.push(`a=ice-options:${m.iceOptions}`);
65
+ if (m.iceGatheringState !== undefined)
66
+ lines.push(`a=ice-gathering-state:${m.iceGatheringState}`);
67
+ if (m.fingerprint) {
68
+ lines.push(`a=fingerprint:${m.fingerprint.algorithm} ${m.fingerprint.value}`);
69
+ }
70
+ if (m.setup !== undefined)
71
+ lines.push(`a=setup:${m.setup}`);
72
+ if (m.mid !== undefined)
73
+ lines.push(`a=mid:${m.mid}`);
74
+ for (const e of m.extmaps) {
75
+ lines.push(`a=extmap:${serializeExtmap(e)}`);
76
+ }
77
+ if (m.direction !== undefined)
78
+ lines.push(`a=${m.direction}`);
79
+ if (m.msid !== undefined)
80
+ lines.push(`a=msid:${m.msid}`);
81
+ if (m.rtcpMux === true)
82
+ lines.push('a=rtcp-mux');
83
+ if (m.rtcpRsize === true)
84
+ lines.push('a=rtcp-rsize');
85
+ for (const rm of m.rtpMaps) {
86
+ const encStr = rm.encodingParams !== undefined
87
+ ? `${rm.encoding}/${rm.clockRate}/${rm.encodingParams}`
88
+ : `${rm.encoding}/${rm.clockRate}`;
89
+ lines.push(`a=rtpmap:${rm.payloadType} ${encStr}`);
90
+ // Emit rtcp-fb for this payload type
91
+ for (const fb of m.rtcpFbs.filter((f) => f.payloadType === rm.payloadType)) {
92
+ const fbLine = fb.parameter !== undefined
93
+ ? `a=rtcp-fb:${fb.payloadType} ${fb.type} ${fb.parameter}`
94
+ : `a=rtcp-fb:${fb.payloadType} ${fb.type}`;
95
+ lines.push(fbLine);
96
+ }
97
+ // Emit fmtp for this payload type
98
+ for (const fmtp of m.fmtps.filter((f) => f.payloadType === rm.payloadType)) {
99
+ lines.push(`a=fmtp:${fmtp.payloadType} ${fmtp.parameters}`);
100
+ }
101
+ }
102
+ // Emit any rtcp-fb / fmtp entries whose payloadType is not in rtpMaps
103
+ // (shouldn't normally happen, but be safe)
104
+ const mappedPts = new Set(m.rtpMaps.map((r) => r.payloadType));
105
+ for (const fb of m.rtcpFbs.filter((f) => !mappedPts.has(f.payloadType))) {
106
+ const fbLine = fb.parameter !== undefined
107
+ ? `a=rtcp-fb:${fb.payloadType} ${fb.type} ${fb.parameter}`
108
+ : `a=rtcp-fb:${fb.payloadType} ${fb.type}`;
109
+ lines.push(fbLine);
110
+ }
111
+ for (const fmtp of m.fmtps.filter((f) => !mappedPts.has(f.payloadType))) {
112
+ lines.push(`a=fmtp:${fmtp.payloadType} ${fmtp.parameters}`);
113
+ }
114
+ for (const sg of m.ssrcGroups) {
115
+ lines.push(`a=ssrc-group:${sg.semantic} ${sg.ssrcIds.join(' ')}`);
116
+ }
117
+ for (const ssrc of m.ssrcs) {
118
+ if (ssrc.value !== undefined) {
119
+ lines.push(`a=ssrc:${ssrc.id} ${ssrc.attribute}:${ssrc.value}`);
120
+ }
121
+ else {
122
+ lines.push(`a=ssrc:${ssrc.id} ${ssrc.attribute}`);
123
+ }
124
+ }
125
+ for (const cand of m.candidates) {
126
+ lines.push(`a=candidate:${serializeCandidate(cand)}`);
127
+ }
128
+ if (m.sctpPort !== undefined)
129
+ lines.push(`a=sctp-port:${m.sctpPort}`);
130
+ if (m.maxMessageSize !== undefined)
131
+ lines.push(`a=max-message-size:${m.maxMessageSize}`);
132
+ if (m.endOfCandidates === true)
133
+ lines.push('a=end-of-candidates');
134
+ return lines.join('\r\n');
135
+ }
136
+ // ---------------------------------------------------------------------------
137
+ // Main serializer
138
+ // ---------------------------------------------------------------------------
139
+ export function serialize(desc) {
140
+ const lines = [];
141
+ lines.push(`v=${desc.version}`);
142
+ lines.push(`o=${desc.origin.username} ${desc.origin.sessionId} ${desc.origin.sessionVersion} ` +
143
+ `${desc.origin.networkType} ${desc.origin.addressType} ${desc.origin.unicastAddress}`);
144
+ lines.push(`s=${desc.sessionName}`);
145
+ lines.push(`t=${desc.timing.startTime} ${desc.timing.stopTime}`);
146
+ for (const g of desc.groups) {
147
+ lines.push(`a=group:${g.semantic} ${g.mids.join(' ')}`);
148
+ }
149
+ if (desc.msidSemantic !== undefined) {
150
+ lines.push(`a=msid-semantic: ${desc.msidSemantic}`);
151
+ }
152
+ for (const m of desc.mediaDescriptions) {
153
+ lines.push(serializeMedia(m));
154
+ }
155
+ // RFC 8866: SDP must end with CRLF
156
+ return lines.join('\r\n') + '\r\n';
157
+ }
158
+ //# sourceMappingURL=serializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.js","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ export interface SessionDescription {
2
+ version: number;
3
+ origin: Origin;
4
+ sessionName: string;
5
+ timing: Timing;
6
+ groups: Group[];
7
+ msidSemantic?: string;
8
+ mediaDescriptions: MediaDescription[];
9
+ }
10
+ export interface Origin {
11
+ username: string;
12
+ sessionId: string;
13
+ sessionVersion: number;
14
+ networkType: string;
15
+ addressType: string;
16
+ unicastAddress: string;
17
+ }
18
+ export interface Timing {
19
+ startTime: number;
20
+ stopTime: number;
21
+ }
22
+ export interface Group {
23
+ semantic: string;
24
+ mids: string[];
25
+ }
26
+ export interface MediaDescription {
27
+ type: string;
28
+ port: number;
29
+ protocol: string;
30
+ payloadTypes: number[];
31
+ connection?: Connection;
32
+ bandwidth?: Bandwidth;
33
+ rtpMaps: RtpMap[];
34
+ fmtps: Fmtp[];
35
+ rtcpFbs: RtcpFb[];
36
+ candidates: IceCandidate[];
37
+ iceUfrag?: string;
38
+ icePwd?: string;
39
+ iceOptions?: string;
40
+ iceGatheringState?: string;
41
+ fingerprint?: Fingerprint;
42
+ setup?: string;
43
+ mid?: string;
44
+ direction?: Direction;
45
+ rtcp?: RtcpAttr;
46
+ rtcpMux?: boolean;
47
+ rtcpRsize?: boolean;
48
+ ssrcs: Ssrc[];
49
+ ssrcGroups: SsrcGroup[];
50
+ msid?: string;
51
+ extmaps: Extmap[];
52
+ sctpPort?: number;
53
+ maxMessageSize?: number;
54
+ endOfCandidates?: boolean;
55
+ }
56
+ export type Direction = 'sendrecv' | 'sendonly' | 'recvonly' | 'inactive';
57
+ export interface RtpMap {
58
+ payloadType: number;
59
+ encoding: string;
60
+ clockRate: number;
61
+ encodingParams?: string;
62
+ }
63
+ export interface Fmtp {
64
+ payloadType: number;
65
+ parameters: string;
66
+ }
67
+ export interface RtcpFb {
68
+ payloadType: number;
69
+ type: string;
70
+ parameter?: string;
71
+ }
72
+ export interface IceCandidate {
73
+ foundation: string;
74
+ component: number;
75
+ transport: string;
76
+ priority: number;
77
+ address: string;
78
+ port: number;
79
+ type: string;
80
+ relatedAddress?: string;
81
+ relatedPort?: number;
82
+ tcpType?: string;
83
+ generation?: number;
84
+ ufrag?: string;
85
+ networkId?: number;
86
+ networkCost?: number;
87
+ extensions?: Record<string, string>;
88
+ }
89
+ export interface Fingerprint {
90
+ algorithm: string;
91
+ value: string;
92
+ }
93
+ export interface Connection {
94
+ networkType: string;
95
+ addressType: string;
96
+ address: string;
97
+ }
98
+ export interface Bandwidth {
99
+ type: string;
100
+ bandwidth: number;
101
+ }
102
+ export interface Ssrc {
103
+ id: number;
104
+ attribute: string;
105
+ value?: string;
106
+ }
107
+ export interface SsrcGroup {
108
+ semantic: string;
109
+ ssrcIds: number[];
110
+ }
111
+ export interface Extmap {
112
+ id: number;
113
+ direction?: string;
114
+ uri: string;
115
+ attributes?: string;
116
+ }
117
+ export interface RtcpAttr {
118
+ port: number;
119
+ networkType?: string;
120
+ addressType?: string;
121
+ address?: string;
122
+ }
123
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@agentdance/node-webrtc-sdp",
3
+ "version": "1.0.0",
4
+ "description": "WebRTC SDP parser and serializer — full parse/serialize round-trip, extmap, rtpmap/fmtp, ssrc/ssrc-group, BUNDLE, Chrome interop. Part of the @agentdance/node-webrtc stack.",
5
+ "keywords": [
6
+ "webrtc",
7
+ "sdp",
8
+ "rfc4566",
9
+ "sdp-parser",
10
+ "typescript",
11
+ "node"
12
+ ],
13
+ "license": "MIT",
14
+ "homepage": "https://github.com/agent-dance/node-webrtc#readme",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/agent-dance/node-webrtc.git",
18
+ "directory": "packages/sdp"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/agent-dance/node-webrtc/issues"
22
+ },
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "type": "module",
27
+ "main": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "import": "./dist/index.js",
32
+ "types": "./dist/index.d.ts"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "src"
38
+ ],
39
+ "sideEffects": false,
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "registry": "https://registry.npmjs.org/"
43
+ },
44
+ "devDependencies": {
45
+ "typescript": "*",
46
+ "vitest": "*",
47
+ "@types/node": "*"
48
+ },
49
+ "scripts": {
50
+ "build": "tsc",
51
+ "test": "vitest run",
52
+ "typecheck": "tsc --noEmit",
53
+ "clean": "rm -rf dist"
54
+ }
55
+ }
package/src/helpers.ts ADDED
@@ -0,0 +1,176 @@
1
+ import type { SessionDescription, MediaDescription } from './types.js';
2
+
3
+ let sessionIdCounter = BigInt(Date.now()) * BigInt(1000);
4
+
5
+ function nextSessionId(): string {
6
+ sessionIdCounter += BigInt(1);
7
+ return sessionIdCounter.toString();
8
+ }
9
+
10
+ function baseMedia(
11
+ type: string,
12
+ protocol: string,
13
+ payloadTypes: number[],
14
+ ): MediaDescription {
15
+ return {
16
+ type,
17
+ port: 9,
18
+ protocol,
19
+ payloadTypes,
20
+ rtpMaps: [],
21
+ fmtps: [],
22
+ rtcpFbs: [],
23
+ candidates: [],
24
+ ssrcs: [],
25
+ ssrcGroups: [],
26
+ extmaps: [],
27
+ connection: { networkType: 'IN', addressType: 'IP4', address: '0.0.0.0' },
28
+ rtcpMux: true,
29
+ };
30
+ }
31
+
32
+ function audioMedia(): MediaDescription {
33
+ const m = baseMedia('audio', 'UDP/TLS/RTP/SAVPF', [111]);
34
+ m.rtpMaps = [{ payloadType: 111, encoding: 'opus', clockRate: 48000, encodingParams: '2' }];
35
+ m.fmtps = [{ payloadType: 111, parameters: 'minptime=10;useinbandfec=1' }];
36
+ m.rtcpFbs = [{ payloadType: 111, type: 'transport-cc' }];
37
+ m.direction = 'sendrecv';
38
+ m.mid = '0';
39
+ return m;
40
+ }
41
+
42
+ function videoMedia(): MediaDescription {
43
+ const m = baseMedia('video', 'UDP/TLS/RTP/SAVPF', [96, 97]);
44
+ m.rtpMaps = [
45
+ { payloadType: 96, encoding: 'VP8', clockRate: 90000 },
46
+ { payloadType: 97, encoding: 'rtx', clockRate: 90000 },
47
+ ];
48
+ m.fmtps = [{ payloadType: 97, parameters: 'apt=96' }];
49
+ m.rtcpFbs = [
50
+ { payloadType: 96, type: 'goog-remb' },
51
+ { payloadType: 96, type: 'transport-cc' },
52
+ { payloadType: 96, type: 'ccm', parameter: 'fir' },
53
+ { payloadType: 96, type: 'nack' },
54
+ { payloadType: 96, type: 'nack', parameter: 'pli' },
55
+ ];
56
+ m.direction = 'sendrecv';
57
+ m.rtcpRsize = true;
58
+ m.mid = '1';
59
+ return m;
60
+ }
61
+
62
+ function dataMedia(): MediaDescription {
63
+ const m = baseMedia('application', 'UDP/DTLS/SCTP', [5000]);
64
+ m.payloadTypes = [];
65
+ // For data channels we use the "webrtc-datachannel" fmt instead of payload types
66
+ m.sctpPort = 5000;
67
+ m.maxMessageSize = 262144;
68
+ m.mid = '2';
69
+ return m;
70
+ }
71
+
72
+ export interface CreateOfferOptions {
73
+ audio?: boolean;
74
+ video?: boolean;
75
+ data?: boolean;
76
+ }
77
+
78
+ export function createOffer(options: CreateOfferOptions = {}): SessionDescription {
79
+ const { audio = true, video = true, data = false } = options;
80
+
81
+ const mediaDescriptions: MediaDescription[] = [];
82
+ const mids: string[] = [];
83
+
84
+ if (audio) {
85
+ const m = audioMedia();
86
+ m.setup = 'actpass';
87
+ mediaDescriptions.push(m);
88
+ if (m.mid !== undefined) mids.push(m.mid);
89
+ }
90
+
91
+ if (video) {
92
+ const m = videoMedia();
93
+ m.setup = 'actpass';
94
+ mediaDescriptions.push(m);
95
+ if (m.mid !== undefined) mids.push(m.mid);
96
+ }
97
+
98
+ if (data) {
99
+ const m = dataMedia();
100
+ m.setup = 'actpass';
101
+ mediaDescriptions.push(m);
102
+ if (m.mid !== undefined) mids.push(m.mid);
103
+ }
104
+
105
+ return {
106
+ version: 0,
107
+ origin: {
108
+ username: '-',
109
+ sessionId: nextSessionId(),
110
+ sessionVersion: 2,
111
+ networkType: 'IN',
112
+ addressType: 'IP4',
113
+ unicastAddress: '127.0.0.1',
114
+ },
115
+ sessionName: '-',
116
+ timing: { startTime: 0, stopTime: 0 },
117
+ groups: mids.length > 0 ? [{ semantic: 'BUNDLE', mids }] : [],
118
+ msidSemantic: 'WMS',
119
+ mediaDescriptions,
120
+ };
121
+ }
122
+
123
+ export function createAnswer(offer: SessionDescription): SessionDescription {
124
+ const mediaDescriptions: MediaDescription[] = offer.mediaDescriptions.map(
125
+ (offered) => {
126
+ const flippedDirection = flipDirection(offered.direction);
127
+ const m: MediaDescription = {
128
+ ...offered,
129
+ rtpMaps: [...offered.rtpMaps],
130
+ fmtps: [...offered.fmtps],
131
+ rtcpFbs: [...offered.rtcpFbs],
132
+ candidates: [],
133
+ ssrcs: [],
134
+ ssrcGroups: [],
135
+ extmaps: [...offered.extmaps],
136
+ setup: offered.setup === 'actpass' ? 'passive' : 'active',
137
+ };
138
+ if (flippedDirection !== undefined) {
139
+ m.direction = flippedDirection;
140
+ } else {
141
+ delete m.direction;
142
+ }
143
+ return m;
144
+ },
145
+ );
146
+
147
+ return {
148
+ version: 0,
149
+ origin: {
150
+ username: '-',
151
+ sessionId: nextSessionId(),
152
+ sessionVersion: 2,
153
+ networkType: 'IN',
154
+ addressType: 'IP4',
155
+ unicastAddress: '127.0.0.1',
156
+ },
157
+ sessionName: '-',
158
+ timing: { startTime: 0, stopTime: 0 },
159
+ groups: offer.groups.map((g) => ({ ...g, mids: [...g.mids] })),
160
+ ...(offer.msidSemantic !== undefined ? { msidSemantic: offer.msidSemantic } : {}),
161
+ mediaDescriptions,
162
+ };
163
+ }
164
+
165
+ function flipDirection(
166
+ dir: SessionDescription['mediaDescriptions'][0]['direction'],
167
+ ): SessionDescription['mediaDescriptions'][0]['direction'] {
168
+ switch (dir) {
169
+ case 'sendonly':
170
+ return 'recvonly';
171
+ case 'recvonly':
172
+ return 'sendonly';
173
+ default:
174
+ return dir; // sendrecv / inactive / undefined stay the same
175
+ }
176
+ }
package/src/index.ts ADDED
@@ -0,0 +1,24 @@
1
+ export type {
2
+ SessionDescription,
3
+ Origin,
4
+ Timing,
5
+ Group,
6
+ MediaDescription,
7
+ Direction,
8
+ RtpMap,
9
+ Fmtp,
10
+ RtcpFb,
11
+ IceCandidate,
12
+ Fingerprint,
13
+ Connection,
14
+ Bandwidth,
15
+ Ssrc,
16
+ SsrcGroup,
17
+ Extmap,
18
+ RtcpAttr,
19
+ } from './types.js';
20
+
21
+ export { parse, parseCandidate } from './parser.js';
22
+ export { serialize, serializeCandidate } from './serializer.js';
23
+ export { createOffer, createAnswer } from './helpers.js';
24
+ export type { CreateOfferOptions } from './helpers.js';