node-av 3.1.3 → 5.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.
Files changed (192) hide show
  1. package/README.md +88 -52
  2. package/binding.gyp +23 -11
  3. package/dist/api/audio-frame-buffer.d.ts +201 -0
  4. package/dist/api/audio-frame-buffer.js +275 -0
  5. package/dist/api/audio-frame-buffer.js.map +1 -0
  6. package/dist/api/bitstream-filter.d.ts +320 -78
  7. package/dist/api/bitstream-filter.js +684 -151
  8. package/dist/api/bitstream-filter.js.map +1 -1
  9. package/dist/api/constants.d.ts +44 -0
  10. package/dist/api/constants.js +45 -0
  11. package/dist/api/constants.js.map +1 -0
  12. package/dist/api/data/test_av1.ivf +0 -0
  13. package/dist/api/data/test_mjpeg.mjpeg +0 -0
  14. package/dist/api/data/test_vp8.ivf +0 -0
  15. package/dist/api/data/test_vp9.ivf +0 -0
  16. package/dist/api/decoder.d.ts +454 -77
  17. package/dist/api/decoder.js +1081 -271
  18. package/dist/api/decoder.js.map +1 -1
  19. package/dist/api/{media-input.d.ts → demuxer.d.ts} +295 -45
  20. package/dist/api/demuxer.js +1965 -0
  21. package/dist/api/demuxer.js.map +1 -0
  22. package/dist/api/encoder.d.ts +423 -132
  23. package/dist/api/encoder.js +1089 -240
  24. package/dist/api/encoder.js.map +1 -1
  25. package/dist/api/filter-complex.d.ts +769 -0
  26. package/dist/api/filter-complex.js +1596 -0
  27. package/dist/api/filter-complex.js.map +1 -0
  28. package/dist/api/filter-presets.d.ts +80 -5
  29. package/dist/api/filter-presets.js +117 -7
  30. package/dist/api/filter-presets.js.map +1 -1
  31. package/dist/api/filter.d.ts +561 -125
  32. package/dist/api/filter.js +1083 -274
  33. package/dist/api/filter.js.map +1 -1
  34. package/dist/api/{fmp4.d.ts → fmp4-stream.d.ts} +141 -140
  35. package/dist/api/fmp4-stream.js +539 -0
  36. package/dist/api/fmp4-stream.js.map +1 -0
  37. package/dist/api/hardware.d.ts +58 -6
  38. package/dist/api/hardware.js +127 -11
  39. package/dist/api/hardware.js.map +1 -1
  40. package/dist/api/index.d.ts +8 -4
  41. package/dist/api/index.js +17 -8
  42. package/dist/api/index.js.map +1 -1
  43. package/dist/api/io-stream.d.ts +6 -6
  44. package/dist/api/io-stream.js +5 -4
  45. package/dist/api/io-stream.js.map +1 -1
  46. package/dist/api/{media-output.d.ts → muxer.d.ts} +280 -66
  47. package/dist/api/muxer.js +1934 -0
  48. package/dist/api/muxer.js.map +1 -0
  49. package/dist/api/pipeline.d.ts +77 -29
  50. package/dist/api/pipeline.js +449 -439
  51. package/dist/api/pipeline.js.map +1 -1
  52. package/dist/api/rtp-stream.d.ts +312 -0
  53. package/dist/api/rtp-stream.js +630 -0
  54. package/dist/api/rtp-stream.js.map +1 -0
  55. package/dist/api/types.d.ts +533 -56
  56. package/dist/api/utilities/async-queue.d.ts +91 -0
  57. package/dist/api/utilities/async-queue.js +162 -0
  58. package/dist/api/utilities/async-queue.js.map +1 -0
  59. package/dist/api/utilities/audio-sample.d.ts +11 -1
  60. package/dist/api/utilities/audio-sample.js +10 -0
  61. package/dist/api/utilities/audio-sample.js.map +1 -1
  62. package/dist/api/utilities/channel-layout.d.ts +1 -0
  63. package/dist/api/utilities/channel-layout.js +1 -0
  64. package/dist/api/utilities/channel-layout.js.map +1 -1
  65. package/dist/api/utilities/image.d.ts +39 -1
  66. package/dist/api/utilities/image.js +38 -0
  67. package/dist/api/utilities/image.js.map +1 -1
  68. package/dist/api/utilities/index.d.ts +3 -0
  69. package/dist/api/utilities/index.js +6 -0
  70. package/dist/api/utilities/index.js.map +1 -1
  71. package/dist/api/utilities/media-type.d.ts +2 -1
  72. package/dist/api/utilities/media-type.js +1 -0
  73. package/dist/api/utilities/media-type.js.map +1 -1
  74. package/dist/api/utilities/pixel-format.d.ts +4 -1
  75. package/dist/api/utilities/pixel-format.js +3 -0
  76. package/dist/api/utilities/pixel-format.js.map +1 -1
  77. package/dist/api/utilities/sample-format.d.ts +6 -1
  78. package/dist/api/utilities/sample-format.js +5 -0
  79. package/dist/api/utilities/sample-format.js.map +1 -1
  80. package/dist/api/utilities/scheduler.d.ts +138 -0
  81. package/dist/api/utilities/scheduler.js +98 -0
  82. package/dist/api/utilities/scheduler.js.map +1 -0
  83. package/dist/api/utilities/streaming.d.ts +105 -15
  84. package/dist/api/utilities/streaming.js +201 -12
  85. package/dist/api/utilities/streaming.js.map +1 -1
  86. package/dist/api/utilities/timestamp.d.ts +15 -1
  87. package/dist/api/utilities/timestamp.js +14 -0
  88. package/dist/api/utilities/timestamp.js.map +1 -1
  89. package/dist/api/utilities/whisper-model.d.ts +310 -0
  90. package/dist/api/utilities/whisper-model.js +528 -0
  91. package/dist/api/utilities/whisper-model.js.map +1 -0
  92. package/dist/api/webrtc-stream.d.ts +288 -0
  93. package/dist/api/webrtc-stream.js +440 -0
  94. package/dist/api/webrtc-stream.js.map +1 -0
  95. package/dist/api/whisper.d.ts +324 -0
  96. package/dist/api/whisper.js +362 -0
  97. package/dist/api/whisper.js.map +1 -0
  98. package/dist/constants/constants.d.ts +54 -2
  99. package/dist/constants/constants.js +48 -1
  100. package/dist/constants/constants.js.map +1 -1
  101. package/dist/constants/encoders.d.ts +2 -1
  102. package/dist/constants/encoders.js +4 -3
  103. package/dist/constants/encoders.js.map +1 -1
  104. package/dist/constants/hardware.d.ts +26 -0
  105. package/dist/constants/hardware.js +27 -0
  106. package/dist/constants/hardware.js.map +1 -0
  107. package/dist/constants/index.d.ts +1 -0
  108. package/dist/constants/index.js +1 -0
  109. package/dist/constants/index.js.map +1 -1
  110. package/dist/ffmpeg/index.d.ts +3 -3
  111. package/dist/ffmpeg/index.js +3 -3
  112. package/dist/ffmpeg/utils.d.ts +27 -0
  113. package/dist/ffmpeg/utils.js +28 -16
  114. package/dist/ffmpeg/utils.js.map +1 -1
  115. package/dist/lib/binding.d.ts +22 -11
  116. package/dist/lib/binding.js.map +1 -1
  117. package/dist/lib/codec-context.d.ts +87 -0
  118. package/dist/lib/codec-context.js +125 -4
  119. package/dist/lib/codec-context.js.map +1 -1
  120. package/dist/lib/codec-parameters.d.ts +229 -1
  121. package/dist/lib/codec-parameters.js +264 -0
  122. package/dist/lib/codec-parameters.js.map +1 -1
  123. package/dist/lib/codec-parser.d.ts +23 -0
  124. package/dist/lib/codec-parser.js +25 -0
  125. package/dist/lib/codec-parser.js.map +1 -1
  126. package/dist/lib/codec.d.ts +26 -4
  127. package/dist/lib/codec.js +35 -0
  128. package/dist/lib/codec.js.map +1 -1
  129. package/dist/lib/dictionary.js +1 -0
  130. package/dist/lib/dictionary.js.map +1 -1
  131. package/dist/lib/error.js +1 -1
  132. package/dist/lib/error.js.map +1 -1
  133. package/dist/lib/fifo.d.ts +416 -0
  134. package/dist/lib/fifo.js +453 -0
  135. package/dist/lib/fifo.js.map +1 -0
  136. package/dist/lib/filter-context.d.ts +52 -11
  137. package/dist/lib/filter-context.js +56 -12
  138. package/dist/lib/filter-context.js.map +1 -1
  139. package/dist/lib/filter-graph.d.ts +9 -0
  140. package/dist/lib/filter-graph.js +13 -0
  141. package/dist/lib/filter-graph.js.map +1 -1
  142. package/dist/lib/filter.d.ts +21 -0
  143. package/dist/lib/filter.js +28 -0
  144. package/dist/lib/filter.js.map +1 -1
  145. package/dist/lib/format-context.d.ts +48 -14
  146. package/dist/lib/format-context.js +76 -7
  147. package/dist/lib/format-context.js.map +1 -1
  148. package/dist/lib/frame.d.ts +264 -1
  149. package/dist/lib/frame.js +351 -1
  150. package/dist/lib/frame.js.map +1 -1
  151. package/dist/lib/hardware-device-context.d.ts +3 -2
  152. package/dist/lib/hardware-device-context.js.map +1 -1
  153. package/dist/lib/index.d.ts +2 -0
  154. package/dist/lib/index.js +4 -0
  155. package/dist/lib/index.js.map +1 -1
  156. package/dist/lib/input-format.d.ts +21 -0
  157. package/dist/lib/input-format.js +42 -2
  158. package/dist/lib/input-format.js.map +1 -1
  159. package/dist/lib/native-types.d.ts +76 -27
  160. package/dist/lib/option.d.ts +25 -13
  161. package/dist/lib/option.js +28 -0
  162. package/dist/lib/option.js.map +1 -1
  163. package/dist/lib/output-format.d.ts +22 -1
  164. package/dist/lib/output-format.js +28 -0
  165. package/dist/lib/output-format.js.map +1 -1
  166. package/dist/lib/packet.d.ts +35 -0
  167. package/dist/lib/packet.js +52 -2
  168. package/dist/lib/packet.js.map +1 -1
  169. package/dist/lib/rational.d.ts +18 -0
  170. package/dist/lib/rational.js +19 -0
  171. package/dist/lib/rational.js.map +1 -1
  172. package/dist/lib/stream.d.ts +126 -0
  173. package/dist/lib/stream.js +188 -5
  174. package/dist/lib/stream.js.map +1 -1
  175. package/dist/lib/sync-queue.d.ts +179 -0
  176. package/dist/lib/sync-queue.js +197 -0
  177. package/dist/lib/sync-queue.js.map +1 -0
  178. package/dist/lib/types.d.ts +49 -1
  179. package/dist/lib/utilities.d.ts +281 -53
  180. package/dist/lib/utilities.js +298 -55
  181. package/dist/lib/utilities.js.map +1 -1
  182. package/install/check.js +2 -2
  183. package/package.json +37 -26
  184. package/dist/api/fmp4.js +0 -710
  185. package/dist/api/fmp4.js.map +0 -1
  186. package/dist/api/media-input.js +0 -1075
  187. package/dist/api/media-input.js.map +0 -1
  188. package/dist/api/media-output.js +0 -1040
  189. package/dist/api/media-output.js.map +0 -1
  190. package/dist/api/webrtc.d.ts +0 -664
  191. package/dist/api/webrtc.js +0 -1132
  192. package/dist/api/webrtc.js.map +0 -1
@@ -0,0 +1,440 @@
1
+ import { MediaStreamTrack, RTCIceCandidate, RTCPeerConnection, RTCRtpCodecParameters, RTCSessionDescription } from 'werift';
2
+ import { AV_CODEC_ID_AV1, AV_CODEC_ID_H264, AV_CODEC_ID_HEVC, AV_CODEC_ID_OPUS, AV_CODEC_ID_PCM_ALAW, AV_CODEC_ID_PCM_MULAW, AV_CODEC_ID_VP8, AV_CODEC_ID_VP9, } from '../constants/constants.js';
3
+ import { RTPStream } from './rtp-stream.js';
4
+ /**
5
+ * Complete WebRTC session management with werift integration.
6
+ *
7
+ * Provides end-to-end WebRTC streaming with automatic SDP negotiation,
8
+ * ICE candidate handling, and peer connection management.
9
+ * Built on top of {@link RTPStream} for generic RTP streaming with WebRTC-specific
10
+ * protocol details handled automatically.
11
+ * Integrates with werift library for RTCPeerConnection and media track handling.
12
+ * Ideal for building complete WebRTC streaming applications with minimal code.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { WebRTCStream } from 'node-av/api';
17
+ *
18
+ * // Create session from media source
19
+ * const session = await WebRTCStream.create('rtsp://camera.local/stream', {
20
+ * mtu: 1200,
21
+ * hardware: 'auto',
22
+ * iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
23
+ * onIceCandidate: (candidate) => {
24
+ * sendToClient({ type: 'candidate', value: candidate });
25
+ * }
26
+ * });
27
+ *
28
+ * // Process SDP offer from client
29
+ * const answer = await session.setOffer(clientOffer);
30
+ * sendToClient({ type: 'answer', value: answer });
31
+ *
32
+ * // Start streaming
33
+ * await session.start();
34
+ * ```
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // Complete WebSocket signaling server
39
+ * import { WebSocket } from 'ws';
40
+ *
41
+ * ws.on('message', async (data) => {
42
+ * const msg = JSON.parse(data);
43
+ *
44
+ * if (msg.type === 'offer') {
45
+ * const session = await WebRTCStream.create(msg.url, {
46
+ * hardware: 'auto',
47
+ * onIceCandidate: (candidate) => {
48
+ * ws.send(JSON.stringify({ type: 'candidate', value: candidate }));
49
+ * }
50
+ * });
51
+ *
52
+ * const answer = await session.setOffer(msg.value);
53
+ * ws.send(JSON.stringify({ type: 'answer', value: answer }));
54
+ *
55
+ * await session.start();
56
+ * } else if (msg.type === 'candidate') {
57
+ * session.addIceCandidate(msg.value);
58
+ * }
59
+ * });
60
+ * ```
61
+ *
62
+ * @see {@link RTPStream} For library-agnostic RTP streaming
63
+ * @see {@link Demuxer} For input media handling
64
+ * @see {@link HardwareContext} For GPU acceleration
65
+ */
66
+ export class WebRTCStream {
67
+ stream;
68
+ pc = null;
69
+ videoTrack = null;
70
+ audioTrack = null;
71
+ options;
72
+ pendingIceCandidates = [];
73
+ /**
74
+ * @param options - Session configuration options
75
+ *
76
+ * Use {@link create} factory method
77
+ *
78
+ * @internal
79
+ */
80
+ constructor(options) {
81
+ this.options = {
82
+ onIceCandidate: options.onIceCandidate ?? (() => { }),
83
+ onClose: options.onClose ?? (() => { }),
84
+ iceServers: options.iceServers ?? [],
85
+ ...options,
86
+ };
87
+ }
88
+ /**
89
+ * Create a WebRTC session from a media source.
90
+ *
91
+ * Opens the input media, creates internal streaming components, and prepares
92
+ * for WebRTC peer connection negotiation. Does not start streaming yet.
93
+ * Call {@link setOffer} to negotiate SDP and {@link start} to begin streaming.
94
+ *
95
+ * @param inputUrl - Media source URL (RTSP, file path, HTTP, etc.)
96
+ *
97
+ * @param options - Session configuration options
98
+ *
99
+ * @returns Configured WebRTC session instance
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const session = await WebRTCStream.create('rtsp://camera.local/stream', {
104
+ * mtu: 1200,
105
+ * hardware: 'auto',
106
+ * iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
107
+ * });
108
+ * ```
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * // Session from file with hardware acceleration
113
+ * const session = await WebRTCStream.create('video.mp4', {
114
+ * hardware: {
115
+ * deviceType: AV_HWDEVICE_TYPE_CUDA
116
+ * }
117
+ * });
118
+ * ```
119
+ */
120
+ static create(inputUrl, options = {}) {
121
+ const session = new WebRTCStream(options);
122
+ // Create stream with WebRTC-specific codec support
123
+ session.stream = RTPStream.create(inputUrl, {
124
+ video: options.video,
125
+ audio: options.audio,
126
+ hardware: options.hardware,
127
+ inputOptions: options.inputOptions,
128
+ supportedVideoCodecs: [AV_CODEC_ID_H264, AV_CODEC_ID_HEVC, AV_CODEC_ID_VP8, AV_CODEC_ID_VP9, AV_CODEC_ID_AV1],
129
+ supportedAudioCodecs: [AV_CODEC_ID_OPUS, AV_CODEC_ID_PCM_ALAW, AV_CODEC_ID_PCM_MULAW],
130
+ onVideoPacket: (rtp) => {
131
+ session.videoTrack?.writeRtp(rtp);
132
+ },
133
+ onAudioPacket: (rtp) => {
134
+ session.audioTrack?.writeRtp(rtp);
135
+ },
136
+ onClose: (error) => {
137
+ session.options.onClose?.(error);
138
+ },
139
+ });
140
+ return session;
141
+ }
142
+ /**
143
+ * Start streaming media to WebRTC peer connection.
144
+ *
145
+ * Begins the media processing pipeline, reading packets from input,
146
+ * transcoding if necessary, and sending RTP packets to media tracks.
147
+ * Note: The stream is automatically started by {@link setOffer}, so calling
148
+ * this method explicitly is optional. This method is provided for cases where
149
+ * you need explicit control over when streaming begins.
150
+ *
151
+ * @returns Promise that resolves when streaming completes
152
+ *
153
+ * @throws {FFmpegError} If transcoding or muxing fails
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const session = await WebRTCStream.create('input.mp4');
158
+ * session.onIceCandidate = (c) => sendToRemote(c);
159
+ *
160
+ * const answer = await session.setOffer(remoteOffer);
161
+ * sendToRemote(answer);
162
+ * // Stream is already started by setOffer
163
+ * ```
164
+ */
165
+ async start() {
166
+ await this.stream.start();
167
+ }
168
+ /**
169
+ * Stop streaming gracefully and clean up all resources.
170
+ *
171
+ * Stops the stream, closes peer connection, and releases all resources.
172
+ * Safe to call multiple times. After stopping, you can call start() again
173
+ * to restart the session.
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * const session = await WebRTCStream.create('input.mp4');
178
+ * await session.start();
179
+ *
180
+ * // Stop after 10 seconds
181
+ * setTimeout(async () => await session.stop(), 10000);
182
+ * ```
183
+ */
184
+ async stop() {
185
+ await this.stream.stop();
186
+ this.pc?.close();
187
+ this.videoTrack = null;
188
+ this.audioTrack = null;
189
+ this.pc = null;
190
+ this.pendingIceCandidates = [];
191
+ }
192
+ /**
193
+ * Get detected codec information.
194
+ *
195
+ * Returns RTP codec parameters and FFmpeg codec IDs for video and audio.
196
+ * Useful for inspecting what codecs will be used in the WebRTC session.
197
+ * The input is automatically opened during {@link create}, so codecs can be
198
+ * detected immediately after session creation.
199
+ *
200
+ * @returns Codec configuration for video and audio streams
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * const session = await WebRTCStream.create('input.mp4');
205
+ * const codecs = session.getCodecs();
206
+ *
207
+ * console.log('Video:', codecs.video.mimeType);
208
+ * console.log('Audio:', codecs.audio?.mimeType);
209
+ * ```
210
+ */
211
+ getCodecs() {
212
+ const input = this.stream.getInput();
213
+ if (!input) {
214
+ return {
215
+ video: undefined,
216
+ audio: undefined,
217
+ };
218
+ }
219
+ const videoStream = input.video();
220
+ const audioStream = input.audio();
221
+ return {
222
+ video: this.getVideoCodecConfig(videoStream?.codecpar.codecId),
223
+ audio: this.getAudioCodecConfig(audioStream?.codecpar.codecId),
224
+ };
225
+ }
226
+ /**
227
+ * Process SDP offer from remote peer and generate SDP answer.
228
+ *
229
+ * Creates RTCPeerConnection with detected codecs, sets up media tracks,
230
+ * processes the remote SDP offer, and generates a local SDP answer.
231
+ * Also configures ICE candidate handling via {@link onIceCandidate} callback.
232
+ * Must be called before {@link start}.
233
+ *
234
+ * @param offerSdp - SDP offer string from remote WebRTC peer
235
+ *
236
+ * @returns SDP answer string to send back to remote peer
237
+ *
238
+ * @example
239
+ * ```typescript
240
+ * const session = await WebRTCStream.create('input.mp4');
241
+ *
242
+ * // Setup ICE candidate handler first
243
+ * session.onIceCandidate = (candidate) => {
244
+ * sendToRemote({ type: 'candidate', value: candidate });
245
+ * };
246
+ *
247
+ * // Process offer and send answer
248
+ * const answer = await session.setOffer(remoteOffer);
249
+ * sendToRemote({ type: 'answer', value: answer });
250
+ *
251
+ * // Start streaming
252
+ * await session.start();
253
+ * ```
254
+ */
255
+ async setOffer(offerSdp) {
256
+ const codecs = this.getCodecs();
257
+ const videoConfig = codecs.video;
258
+ delete videoConfig.codecId;
259
+ const audioConfig = codecs.audio ?? {
260
+ mimeType: 'audio/opus',
261
+ clockRate: 48000,
262
+ channels: 2,
263
+ payloadType: 111,
264
+ };
265
+ delete audioConfig.codecId;
266
+ // Create PeerConnection with detected codecs
267
+ const codecParams = {
268
+ video: [
269
+ new RTCRtpCodecParameters({
270
+ ...videoConfig,
271
+ }),
272
+ ],
273
+ audio: [
274
+ new RTCRtpCodecParameters({
275
+ ...audioConfig,
276
+ }),
277
+ ],
278
+ };
279
+ this.pc = new RTCPeerConnection({
280
+ codecs: codecParams,
281
+ iceServers: this.options.iceServers,
282
+ });
283
+ // Setup ICE candidate handling
284
+ this.pc.onIceCandidate.subscribe((candidate) => {
285
+ if (candidate?.candidate && this.options.onIceCandidate) {
286
+ this.options.onIceCandidate(candidate.candidate);
287
+ }
288
+ });
289
+ // Setup tracks
290
+ this.pc.onRemoteTransceiverAdded.subscribe(async (transceiver) => {
291
+ if (transceiver.kind === 'video') {
292
+ this.videoTrack = new MediaStreamTrack({ kind: 'video' });
293
+ transceiver.sender.replaceTrack(this.videoTrack);
294
+ transceiver.setDirection('sendonly');
295
+ }
296
+ else if (transceiver.kind === 'audio' && this.audioTrack === null) {
297
+ this.audioTrack = new MediaStreamTrack({ kind: 'audio' });
298
+ transceiver.sender.replaceTrack(this.audioTrack);
299
+ transceiver.setDirection('sendonly');
300
+ }
301
+ else if (transceiver.kind === 'audio') {
302
+ // Backchannel
303
+ const [track] = await transceiver.onTrack.asPromise();
304
+ const input = this.stream.getInput();
305
+ const ctx = input?.getFormatContext();
306
+ const streams = ctx?.getRTSPStreamInfo();
307
+ const backchannel = streams?.find((s) => s.direction === 'sendonly' && s.mediaType === 'audio');
308
+ track.onReceiveRtp.subscribe(async (rtp) => {
309
+ if (backchannel && this.stream.isStreamActive) {
310
+ try {
311
+ await ctx?.sendRTSPPacket(backchannel.streamIndex, rtp.serialize());
312
+ }
313
+ catch {
314
+ // Ignore send errors
315
+ }
316
+ }
317
+ });
318
+ }
319
+ });
320
+ // Set remote description and create answer
321
+ await this.pc.setRemoteDescription(new RTCSessionDescription(offerSdp, 'offer'));
322
+ const answer = await this.pc.createAnswer();
323
+ this.pc.setLocalDescription(answer);
324
+ // Apply any buffered ICE candidates now that remote description is set
325
+ if (this.pendingIceCandidates.length > 0) {
326
+ for (const candidate of this.pendingIceCandidates) {
327
+ this.pc.addIceCandidate(new RTCIceCandidate({ candidate }));
328
+ }
329
+ this.pendingIceCandidates = [];
330
+ }
331
+ return this.pc.localDescription?.sdp ?? '';
332
+ }
333
+ /**
334
+ * Add ICE candidate from remote peer.
335
+ *
336
+ * Processes ICE candidates received from the remote peer via signaling channel.
337
+ * Should be called whenever a new candidate message arrives from remote peer.
338
+ * Can be called multiple times as candidates are discovered.
339
+ *
340
+ * Supports ICE trickling: If called before {@link setOffer}, candidates are buffered
341
+ * and applied automatically once the remote description is set.
342
+ *
343
+ * @param candidate - ICE candidate string from remote peer
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * // In signaling message handler
348
+ * if (msg.type === 'candidate') {
349
+ * session.addIceCandidate(msg.value);
350
+ * }
351
+ * ```
352
+ */
353
+ addIceCandidate(candidate) {
354
+ // Buffer candidates if peer connection not ready yet (ICE trickling)
355
+ if (!this.pc?.remoteDescription) {
356
+ this.pendingIceCandidates.push(candidate);
357
+ return;
358
+ }
359
+ // Apply candidate immediately if peer connection is ready
360
+ this.pc.addIceCandidate(new RTCIceCandidate({ candidate }));
361
+ }
362
+ /**
363
+ * Get video codec configuration from input stream.
364
+ *
365
+ * @param codecId - FFmpeg codec ID
366
+ *
367
+ * @returns RTP codec parameters with codec ID or undefined if unsupported
368
+ *
369
+ * @internal
370
+ */
371
+ getVideoCodecConfig(codecId) {
372
+ let mimeType;
373
+ const clockRate = 90000;
374
+ let payloadType;
375
+ switch (codecId) {
376
+ case AV_CODEC_ID_H264:
377
+ mimeType = 'video/H264';
378
+ payloadType = 96;
379
+ break;
380
+ case AV_CODEC_ID_HEVC:
381
+ mimeType = 'video/H265';
382
+ payloadType = 96;
383
+ break;
384
+ case AV_CODEC_ID_VP8:
385
+ mimeType = 'video/VP8';
386
+ payloadType = 96;
387
+ break;
388
+ case AV_CODEC_ID_VP9:
389
+ mimeType = 'video/VP9';
390
+ payloadType = 98;
391
+ break;
392
+ case AV_CODEC_ID_AV1:
393
+ mimeType = 'video/AV1';
394
+ payloadType = 98;
395
+ break;
396
+ default:
397
+ return undefined;
398
+ }
399
+ return { mimeType, clockRate, payloadType, codecId };
400
+ }
401
+ /**
402
+ * Get audio codec configuration from input stream.
403
+ *
404
+ * @param codecId - FFmpeg codec ID
405
+ *
406
+ * @returns RTP codec parameters with codec ID or undefined if unsupported
407
+ *
408
+ * @internal
409
+ */
410
+ getAudioCodecConfig(codecId) {
411
+ let mimeType;
412
+ let clockRate;
413
+ let channels;
414
+ let payloadType;
415
+ switch (codecId) {
416
+ case AV_CODEC_ID_OPUS:
417
+ mimeType = 'audio/opus';
418
+ clockRate = 48000;
419
+ channels = 2;
420
+ payloadType = 111;
421
+ break;
422
+ case AV_CODEC_ID_PCM_ALAW:
423
+ mimeType = 'audio/PCMA';
424
+ clockRate = 8000;
425
+ channels = 1;
426
+ payloadType = 8;
427
+ break;
428
+ case AV_CODEC_ID_PCM_MULAW:
429
+ mimeType = 'audio/PCMU';
430
+ clockRate = 8000;
431
+ channels = 1;
432
+ payloadType = 0;
433
+ break;
434
+ default:
435
+ return undefined;
436
+ }
437
+ return { mimeType, clockRate, channels, payloadType, codecId };
438
+ }
439
+ }
440
+ //# sourceMappingURL=webrtc-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webrtc-stream.js","sourceRoot":"","sources":["../../src/api/webrtc-stream.ts"],"names":[],"mappings":"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"}