node-av-light 0.0.0 → 7.1.0-beta.1

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 (311) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +711 -0
  3. package/dist/api/audio-frame-buffer.d.ts +636 -0
  4. package/dist/api/audio-frame-buffer.js +1027 -0
  5. package/dist/api/audio-frame-buffer.js.map +1 -0
  6. package/dist/api/bitstream-filter.d.ts +938 -0
  7. package/dist/api/bitstream-filter.js +1427 -0
  8. package/dist/api/bitstream-filter.js.map +1 -0
  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_h264.h264 +0 -0
  14. package/dist/api/data/test_hevc.h265 +0 -0
  15. package/dist/api/data/test_mjpeg.mjpeg +0 -0
  16. package/dist/api/data/test_vp8.ivf +0 -0
  17. package/dist/api/data/test_vp9.ivf +0 -0
  18. package/dist/api/decoder.d.ts +1413 -0
  19. package/dist/api/decoder.js +2367 -0
  20. package/dist/api/decoder.js.map +1 -0
  21. package/dist/api/demuxer.d.ts +1295 -0
  22. package/dist/api/demuxer.js +2344 -0
  23. package/dist/api/demuxer.js.map +1 -0
  24. package/dist/api/device.d.ts +589 -0
  25. package/dist/api/device.js +964 -0
  26. package/dist/api/device.js.map +1 -0
  27. package/dist/api/encoder-pool.d.ts +262 -0
  28. package/dist/api/encoder-pool.js +397 -0
  29. package/dist/api/encoder-pool.js.map +1 -0
  30. package/dist/api/encoder.d.ts +1509 -0
  31. package/dist/api/encoder.js +2619 -0
  32. package/dist/api/encoder.js.map +1 -0
  33. package/dist/api/filter-complex.d.ts +828 -0
  34. package/dist/api/filter-complex.js +1661 -0
  35. package/dist/api/filter-complex.js.map +1 -0
  36. package/dist/api/filter-presets.d.ts +800 -0
  37. package/dist/api/filter-presets.js +1554 -0
  38. package/dist/api/filter-presets.js.map +1 -0
  39. package/dist/api/filter.d.ts +1339 -0
  40. package/dist/api/filter.js +2075 -0
  41. package/dist/api/filter.js.map +1 -0
  42. package/dist/api/fmp4-stream.d.ts +797 -0
  43. package/dist/api/fmp4-stream.js +1428 -0
  44. package/dist/api/fmp4-stream.js.map +1 -0
  45. package/dist/api/hardware.d.ts +677 -0
  46. package/dist/api/hardware.js +1300 -0
  47. package/dist/api/hardware.js.map +1 -0
  48. package/dist/api/index.d.ts +21 -0
  49. package/dist/api/index.js +38 -0
  50. package/dist/api/index.js.map +1 -0
  51. package/dist/api/io-stream.d.ts +308 -0
  52. package/dist/api/io-stream.js +358 -0
  53. package/dist/api/io-stream.js.map +1 -0
  54. package/dist/api/muxer.d.ts +1311 -0
  55. package/dist/api/muxer.js +2672 -0
  56. package/dist/api/muxer.js.map +1 -0
  57. package/dist/api/pipeline.d.ts +801 -0
  58. package/dist/api/pipeline.js +1344 -0
  59. package/dist/api/pipeline.js.map +1 -0
  60. package/dist/api/probe.d.ts +128 -0
  61. package/dist/api/probe.js +227 -0
  62. package/dist/api/probe.js.map +1 -0
  63. package/dist/api/rtp-stream.d.ts +497 -0
  64. package/dist/api/rtp-stream.js +1131 -0
  65. package/dist/api/rtp-stream.js.map +1 -0
  66. package/dist/api/scaler.d.ts +561 -0
  67. package/dist/api/scaler.js +918 -0
  68. package/dist/api/scaler.js.map +1 -0
  69. package/dist/api/types.d.ts +17 -0
  70. package/dist/api/types.js +2 -0
  71. package/dist/api/types.js.map +1 -0
  72. package/dist/api/utilities/async-queue.d.ts +149 -0
  73. package/dist/api/utilities/async-queue.js +254 -0
  74. package/dist/api/utilities/async-queue.js.map +1 -0
  75. package/dist/api/utilities/audio-sample.d.ts +117 -0
  76. package/dist/api/utilities/audio-sample.js +112 -0
  77. package/dist/api/utilities/audio-sample.js.map +1 -0
  78. package/dist/api/utilities/audio-transcode.d.ts +20 -0
  79. package/dist/api/utilities/audio-transcode.js +27 -0
  80. package/dist/api/utilities/audio-transcode.js.map +1 -0
  81. package/dist/api/utilities/channel-layout.d.ts +76 -0
  82. package/dist/api/utilities/channel-layout.js +80 -0
  83. package/dist/api/utilities/channel-layout.js.map +1 -0
  84. package/dist/api/utilities/codec-format.d.ts +87 -0
  85. package/dist/api/utilities/codec-format.js +117 -0
  86. package/dist/api/utilities/codec-format.js.map +1 -0
  87. package/dist/api/utilities/context-options.d.ts +25 -0
  88. package/dist/api/utilities/context-options.js +23 -0
  89. package/dist/api/utilities/context-options.js.map +1 -0
  90. package/dist/api/utilities/electron-shared-texture.d.ts +368 -0
  91. package/dist/api/utilities/electron-shared-texture.js +540 -0
  92. package/dist/api/utilities/electron-shared-texture.js.map +1 -0
  93. package/dist/api/utilities/image.d.ts +207 -0
  94. package/dist/api/utilities/image.js +213 -0
  95. package/dist/api/utilities/image.js.map +1 -0
  96. package/dist/api/utilities/index.d.ts +14 -0
  97. package/dist/api/utilities/index.js +27 -0
  98. package/dist/api/utilities/index.js.map +1 -0
  99. package/dist/api/utilities/live-decoding.d.ts +15 -0
  100. package/dist/api/utilities/live-decoding.js +32 -0
  101. package/dist/api/utilities/live-decoding.js.map +1 -0
  102. package/dist/api/utilities/media-type.d.ts +49 -0
  103. package/dist/api/utilities/media-type.js +53 -0
  104. package/dist/api/utilities/media-type.js.map +1 -0
  105. package/dist/api/utilities/packet-age-watchdog.d.ts +198 -0
  106. package/dist/api/utilities/packet-age-watchdog.js +594 -0
  107. package/dist/api/utilities/packet-age-watchdog.js.map +1 -0
  108. package/dist/api/utilities/pixel-format.d.ts +89 -0
  109. package/dist/api/utilities/pixel-format.js +97 -0
  110. package/dist/api/utilities/pixel-format.js.map +1 -0
  111. package/dist/api/utilities/sample-format.d.ts +129 -0
  112. package/dist/api/utilities/sample-format.js +141 -0
  113. package/dist/api/utilities/sample-format.js.map +1 -0
  114. package/dist/api/utilities/scale-size.d.ts +51 -0
  115. package/dist/api/utilities/scale-size.js +55 -0
  116. package/dist/api/utilities/scale-size.js.map +1 -0
  117. package/dist/api/utilities/scheduler.d.ts +138 -0
  118. package/dist/api/utilities/scheduler.js +98 -0
  119. package/dist/api/utilities/scheduler.js.map +1 -0
  120. package/dist/api/utilities/streaming.d.ts +186 -0
  121. package/dist/api/utilities/streaming.js +309 -0
  122. package/dist/api/utilities/streaming.js.map +1 -0
  123. package/dist/api/utilities/timestamp.d.ts +193 -0
  124. package/dist/api/utilities/timestamp.js +206 -0
  125. package/dist/api/utilities/timestamp.js.map +1 -0
  126. package/dist/api/utilities/video-transcode.d.ts +218 -0
  127. package/dist/api/utilities/video-transcode.js +624 -0
  128. package/dist/api/utilities/video-transcode.js.map +1 -0
  129. package/dist/api/utilities/whisper-model.d.ts +330 -0
  130. package/dist/api/utilities/whisper-model.js +587 -0
  131. package/dist/api/utilities/whisper-model.js.map +1 -0
  132. package/dist/api/utils.d.ts +19 -0
  133. package/dist/api/utils.js +39 -0
  134. package/dist/api/utils.js.map +1 -0
  135. package/dist/api/webrtc-stream.d.ts +294 -0
  136. package/dist/api/webrtc-stream.js +546 -0
  137. package/dist/api/webrtc-stream.js.map +1 -0
  138. package/dist/api/whisper.d.ts +326 -0
  139. package/dist/api/whisper.js +402 -0
  140. package/dist/api/whisper.js.map +1 -0
  141. package/dist/constants/bsf-options.d.ts +364 -0
  142. package/dist/constants/bsf-options.js +7 -0
  143. package/dist/constants/bsf-options.js.map +1 -0
  144. package/dist/constants/channel-layouts.d.ts +53 -0
  145. package/dist/constants/channel-layouts.js +57 -0
  146. package/dist/constants/channel-layouts.js.map +1 -0
  147. package/dist/constants/constants.d.ts +2435 -0
  148. package/dist/constants/constants.js +1989 -0
  149. package/dist/constants/constants.js.map +1 -0
  150. package/dist/constants/decoders.d.ts +651 -0
  151. package/dist/constants/decoders.js +641 -0
  152. package/dist/constants/decoders.js.map +1 -0
  153. package/dist/constants/encoders.d.ts +314 -0
  154. package/dist/constants/encoders.js +309 -0
  155. package/dist/constants/encoders.js.map +1 -0
  156. package/dist/constants/filter-options.d.ts +12099 -0
  157. package/dist/constants/filter-options.js +7 -0
  158. package/dist/constants/filter-options.js.map +1 -0
  159. package/dist/constants/format-options.d.ts +4319 -0
  160. package/dist/constants/format-options.js +7 -0
  161. package/dist/constants/format-options.js.map +1 -0
  162. package/dist/constants/formats.d.ts +18 -0
  163. package/dist/constants/formats.js +7 -0
  164. package/dist/constants/formats.js.map +1 -0
  165. package/dist/constants/hardware.d.ts +26 -0
  166. package/dist/constants/hardware.js +27 -0
  167. package/dist/constants/hardware.js.map +1 -0
  168. package/dist/constants/index.d.ts +10 -0
  169. package/dist/constants/index.js +6 -0
  170. package/dist/constants/index.js.map +1 -0
  171. package/dist/constants/options.d.ts +6217 -0
  172. package/dist/constants/options.js +7 -0
  173. package/dist/constants/options.js.map +1 -0
  174. package/dist/ffmpeg/index.d.ts +101 -0
  175. package/dist/ffmpeg/index.js +161 -0
  176. package/dist/ffmpeg/index.js.map +1 -0
  177. package/dist/ffmpeg/version.d.ts +6 -0
  178. package/dist/ffmpeg/version.js +7 -0
  179. package/dist/ffmpeg/version.js.map +1 -0
  180. package/dist/index.d.ts +4 -0
  181. package/dist/index.js +9 -0
  182. package/dist/index.js.map +1 -0
  183. package/dist/lib/audio-fifo.d.ts +399 -0
  184. package/dist/lib/audio-fifo.js +431 -0
  185. package/dist/lib/audio-fifo.js.map +1 -0
  186. package/dist/lib/binding.d.ts +242 -0
  187. package/dist/lib/binding.js +102 -0
  188. package/dist/lib/binding.js.map +1 -0
  189. package/dist/lib/bitstream-filter-context.d.ts +381 -0
  190. package/dist/lib/bitstream-filter-context.js +443 -0
  191. package/dist/lib/bitstream-filter-context.js.map +1 -0
  192. package/dist/lib/bitstream-filter.d.ts +140 -0
  193. package/dist/lib/bitstream-filter.js +154 -0
  194. package/dist/lib/bitstream-filter.js.map +1 -0
  195. package/dist/lib/codec-context.d.ts +1069 -0
  196. package/dist/lib/codec-context.js +1336 -0
  197. package/dist/lib/codec-context.js.map +1 -0
  198. package/dist/lib/codec-parameters.d.ts +664 -0
  199. package/dist/lib/codec-parameters.js +813 -0
  200. package/dist/lib/codec-parameters.js.map +1 -0
  201. package/dist/lib/codec-parser.d.ts +201 -0
  202. package/dist/lib/codec-parser.js +213 -0
  203. package/dist/lib/codec-parser.js.map +1 -0
  204. package/dist/lib/codec.d.ts +617 -0
  205. package/dist/lib/codec.js +746 -0
  206. package/dist/lib/codec.js.map +1 -0
  207. package/dist/lib/device.d.ts +294 -0
  208. package/dist/lib/device.js +326 -0
  209. package/dist/lib/device.js.map +1 -0
  210. package/dist/lib/dictionary.d.ts +333 -0
  211. package/dist/lib/dictionary.js +372 -0
  212. package/dist/lib/dictionary.js.map +1 -0
  213. package/dist/lib/error.d.ts +311 -0
  214. package/dist/lib/error.js +395 -0
  215. package/dist/lib/error.js.map +1 -0
  216. package/dist/lib/fifo.d.ts +416 -0
  217. package/dist/lib/fifo.js +453 -0
  218. package/dist/lib/fifo.js.map +1 -0
  219. package/dist/lib/filter-context.d.ts +714 -0
  220. package/dist/lib/filter-context.js +783 -0
  221. package/dist/lib/filter-context.js.map +1 -0
  222. package/dist/lib/filter-graph-segment.d.ts +161 -0
  223. package/dist/lib/filter-graph-segment.js +172 -0
  224. package/dist/lib/filter-graph-segment.js.map +1 -0
  225. package/dist/lib/filter-graph.d.ts +641 -0
  226. package/dist/lib/filter-graph.js +704 -0
  227. package/dist/lib/filter-graph.js.map +1 -0
  228. package/dist/lib/filter-inout.d.ts +202 -0
  229. package/dist/lib/filter-inout.js +261 -0
  230. package/dist/lib/filter-inout.js.map +1 -0
  231. package/dist/lib/filter.d.ts +243 -0
  232. package/dist/lib/filter.js +272 -0
  233. package/dist/lib/filter.js.map +1 -0
  234. package/dist/lib/format-context.d.ts +1335 -0
  235. package/dist/lib/format-context.js +1455 -0
  236. package/dist/lib/format-context.js.map +1 -0
  237. package/dist/lib/frame-utils.d.ts +116 -0
  238. package/dist/lib/frame-utils.js +98 -0
  239. package/dist/lib/frame-utils.js.map +1 -0
  240. package/dist/lib/frame.d.ts +1315 -0
  241. package/dist/lib/frame.js +1535 -0
  242. package/dist/lib/frame.js.map +1 -0
  243. package/dist/lib/hardware-device-context.d.ts +362 -0
  244. package/dist/lib/hardware-device-context.js +383 -0
  245. package/dist/lib/hardware-device-context.js.map +1 -0
  246. package/dist/lib/hardware-frames-context.d.ts +418 -0
  247. package/dist/lib/hardware-frames-context.js +471 -0
  248. package/dist/lib/hardware-frames-context.js.map +1 -0
  249. package/dist/lib/index.d.ts +35 -0
  250. package/dist/lib/index.js +60 -0
  251. package/dist/lib/index.js.map +1 -0
  252. package/dist/lib/input-format.d.ts +249 -0
  253. package/dist/lib/input-format.js +306 -0
  254. package/dist/lib/input-format.js.map +1 -0
  255. package/dist/lib/io-context.d.ts +698 -0
  256. package/dist/lib/io-context.js +771 -0
  257. package/dist/lib/io-context.js.map +1 -0
  258. package/dist/lib/log.d.ts +174 -0
  259. package/dist/lib/log.js +184 -0
  260. package/dist/lib/log.js.map +1 -0
  261. package/dist/lib/native-types.d.ts +1024 -0
  262. package/dist/lib/native-types.js +2 -0
  263. package/dist/lib/native-types.js.map +1 -0
  264. package/dist/lib/option.d.ts +953 -0
  265. package/dist/lib/option.js +1607 -0
  266. package/dist/lib/option.js.map +1 -0
  267. package/dist/lib/output-format.d.ts +222 -0
  268. package/dist/lib/output-format.js +259 -0
  269. package/dist/lib/output-format.js.map +1 -0
  270. package/dist/lib/packet.d.ts +521 -0
  271. package/dist/lib/packet.js +613 -0
  272. package/dist/lib/packet.js.map +1 -0
  273. package/dist/lib/rational.d.ts +251 -0
  274. package/dist/lib/rational.js +278 -0
  275. package/dist/lib/rational.js.map +1 -0
  276. package/dist/lib/software-resample-context.d.ts +552 -0
  277. package/dist/lib/software-resample-context.js +592 -0
  278. package/dist/lib/software-resample-context.js.map +1 -0
  279. package/dist/lib/software-scale-context.d.ts +344 -0
  280. package/dist/lib/software-scale-context.js +366 -0
  281. package/dist/lib/software-scale-context.js.map +1 -0
  282. package/dist/lib/stream.d.ts +383 -0
  283. package/dist/lib/stream.js +524 -0
  284. package/dist/lib/stream.js.map +1 -0
  285. package/dist/lib/sync-queue.d.ts +179 -0
  286. package/dist/lib/sync-queue.js +197 -0
  287. package/dist/lib/sync-queue.js.map +1 -0
  288. package/dist/lib/types.d.ts +34 -0
  289. package/dist/lib/types.js +2 -0
  290. package/dist/lib/types.js.map +1 -0
  291. package/dist/lib/utilities.d.ts +1198 -0
  292. package/dist/lib/utilities.js +1302 -0
  293. package/dist/lib/utilities.js.map +1 -0
  294. package/dist/utils/electron.d.ts +49 -0
  295. package/dist/utils/electron.js +63 -0
  296. package/dist/utils/electron.js.map +1 -0
  297. package/dist/utils/index.d.ts +6 -0
  298. package/dist/utils/index.js +7 -0
  299. package/dist/utils/index.js.map +1 -0
  300. package/dist/utils/libc.d.ts +11 -0
  301. package/dist/utils/libc.js +35 -0
  302. package/dist/utils/libc.js.map +1 -0
  303. package/dist/utils/variant.d.ts +26 -0
  304. package/dist/utils/variant.js +31 -0
  305. package/dist/utils/variant.js.map +1 -0
  306. package/dist/webrtc/index.d.ts +4 -0
  307. package/dist/webrtc/index.js +7 -0
  308. package/dist/webrtc/index.js.map +1 -0
  309. package/install/check.js +124 -0
  310. package/install/ffmpeg.js +66 -0
  311. package/package.json +165 -3
@@ -0,0 +1,546 @@
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 { isMediaFrameSource, 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
+ */
65
+ export class WebRTCStream {
66
+ stream;
67
+ pc = null;
68
+ videoTrack = null;
69
+ audioTrack = null;
70
+ options;
71
+ pendingIceCandidates = [];
72
+ frameSource;
73
+ stopping = false;
74
+ /**
75
+ * @param options - Session configuration options
76
+ *
77
+ * Use {@link create} factory method
78
+ *
79
+ * @internal
80
+ */
81
+ constructor(options) {
82
+ this.options = {
83
+ onIceCandidate: options.onIceCandidate ?? (() => { }),
84
+ onClose: options.onClose ?? (() => { }),
85
+ iceServers: options.iceServers ?? [],
86
+ ...options,
87
+ };
88
+ }
89
+ /**
90
+ * Create a WebRTC session from a media source.
91
+ *
92
+ * Opens the input media, creates internal streaming components, and prepares
93
+ * for WebRTC peer connection negotiation. Does not start streaming yet.
94
+ * Call {@link setOffer} to negotiate SDP and {@link start} to begin streaming.
95
+ *
96
+ * @param input - Media source URL (RTSP, file path, HTTP, etc.) or a pre-opened {@link Demuxer}
97
+ *
98
+ * @param options - Session configuration options
99
+ *
100
+ * @returns Configured WebRTC session instance
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * const session = WebRTCStream.create('rtsp://camera.local/stream', {
105
+ * mtu: 1200,
106
+ * hardware: 'auto',
107
+ * iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
108
+ * });
109
+ * ```
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // Session from a pre-opened Demuxer (e.g. screen capture)
114
+ * const demuxer = await Device.openScreen({ frameRate: 30 });
115
+ * const session = WebRTCStream.create(demuxer, {
116
+ * hardware: 'auto'
117
+ * });
118
+ * ```
119
+ */
120
+ static create(input, options = {}) {
121
+ const session = new WebRTCStream(options);
122
+ // Remember a frame source so negotiation can advertise the encoder's target
123
+ // codecs (there's no input stream to read a codec from).
124
+ if (isMediaFrameSource(input)) {
125
+ session.frameSource = input;
126
+ }
127
+ // Create stream with WebRTC-specific codec support
128
+ session.stream = RTPStream.create(input, {
129
+ video: options.video,
130
+ audio: options.audio,
131
+ hardware: options.hardware,
132
+ inputOptions: options.inputOptions,
133
+ supportedVideoCodecs: [AV_CODEC_ID_H264, AV_CODEC_ID_HEVC, AV_CODEC_ID_VP8, AV_CODEC_ID_VP9, AV_CODEC_ID_AV1],
134
+ supportedAudioCodecs: [AV_CODEC_ID_OPUS, AV_CODEC_ID_PCM_ALAW, AV_CODEC_ID_PCM_MULAW],
135
+ onVideoPacket: (rtp) => {
136
+ session.videoTrack?.writeRtp(rtp);
137
+ },
138
+ onAudioPacket: (rtp) => {
139
+ session.audioTrack?.writeRtp(rtp);
140
+ },
141
+ onClose: (error) => {
142
+ session.options.onClose?.(error);
143
+ },
144
+ });
145
+ return session;
146
+ }
147
+ /**
148
+ * Start streaming media to the WebRTC peer connection.
149
+ *
150
+ * Begins the media processing pipeline, reading packets from input,
151
+ * transcoding if necessary, and sending RTP packets to the media tracks.
152
+ * {@link setOffer} calls this automatically after negotiating, so calling it
153
+ * explicitly is optional. It is idempotent - a useful pattern for demuxer
154
+ * inputs is calling `start()` *before* `setOffer()` so the input is open and
155
+ * its actual codecs are advertised in the answer.
156
+ *
157
+ * @returns Promise that resolves once streaming has started (runs in the background)
158
+ *
159
+ * @throws {FFmpegError} If transcoding or muxing fails
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const session = WebRTCStream.create('rtsp://camera.local/stream');
164
+ *
165
+ * await session.start(); // open input so getCodecs() sees the real codecs
166
+ * const answer = await session.setOffer(remoteOffer);
167
+ * sendToRemote(answer);
168
+ * ```
169
+ *
170
+ * @see {@link setOffer} Which starts the stream automatically after negotiation
171
+ */
172
+ async start() {
173
+ await this.stream.start();
174
+ }
175
+ /**
176
+ * Stop streaming gracefully and clean up all resources.
177
+ *
178
+ * Stops the stream, closes peer connection, and releases all resources.
179
+ * Safe to call multiple times. After stopping, you can call start() again
180
+ * to restart the session.
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const session = await WebRTCStream.create('input.mp4');
185
+ * await session.start();
186
+ *
187
+ * // Stop after 10 seconds
188
+ * setTimeout(async () => await session.stop(), 10000);
189
+ * ```
190
+ */
191
+ async stop() {
192
+ if (this.stopping) {
193
+ return;
194
+ }
195
+ this.stopping = true;
196
+ try {
197
+ await this.stream.stop();
198
+ try {
199
+ await this.pc?.close();
200
+ }
201
+ catch {
202
+ // Peer connection may already be closed.
203
+ }
204
+ this.videoTrack = null;
205
+ this.audioTrack = null;
206
+ this.pc = null;
207
+ this.pendingIceCandidates = [];
208
+ }
209
+ finally {
210
+ this.stopping = false;
211
+ }
212
+ }
213
+ /**
214
+ * Get detected codec information.
215
+ *
216
+ * Returns RTP codec parameters and FFmpeg codec IDs for video and audio.
217
+ * Useful for inspecting what codecs will be used in the WebRTC session.
218
+ * The input is automatically opened during {@link create}, so codecs can be
219
+ * detected immediately after session creation.
220
+ *
221
+ * @returns Codec configuration for video and audio streams
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * const session = await WebRTCStream.create('input.mp4');
226
+ * const codecs = session.getCodecs();
227
+ *
228
+ * console.log('Video:', codecs.video.mimeType);
229
+ * console.log('Audio:', codecs.audio?.mimeType);
230
+ * ```
231
+ */
232
+ getCodecs() {
233
+ // Frame source: no input stream - advertise the encoder's target codecs
234
+ // (RTPStream's frame path encodes video to H264 and audio to OPUS), gated on
235
+ // which frame streams are present.
236
+ if (this.frameSource) {
237
+ return {
238
+ video: this.frameSource.video ? this.getVideoCodecConfig(AV_CODEC_ID_H264) : undefined,
239
+ audio: this.frameSource.audio ? this.getAudioCodecConfig(AV_CODEC_ID_OPUS) : undefined,
240
+ };
241
+ }
242
+ const input = this.stream.getInput();
243
+ if (!input) {
244
+ return {
245
+ video: undefined,
246
+ audio: undefined,
247
+ };
248
+ }
249
+ const videoStream = input.video();
250
+ const audioStream = input.audio();
251
+ // Try the input codec first; if unsupported (e.g. rawvideo from device capture),
252
+ // fall back to the first supported video codec (the transcode target)
253
+ let videoConfig = this.getVideoCodecConfig(videoStream?.codecpar.codecId);
254
+ if (!videoConfig && videoStream) {
255
+ const supportedVideoCodecs = [AV_CODEC_ID_H264, AV_CODEC_ID_HEVC, AV_CODEC_ID_VP8, AV_CODEC_ID_VP9, AV_CODEC_ID_AV1];
256
+ for (const codecId of supportedVideoCodecs) {
257
+ videoConfig = this.getVideoCodecConfig(codecId);
258
+ if (videoConfig)
259
+ break;
260
+ }
261
+ }
262
+ return {
263
+ video: videoConfig,
264
+ audio: this.getAudioCodecConfig(audioStream?.codecpar.codecId),
265
+ };
266
+ }
267
+ /**
268
+ * Process SDP offer from remote peer and generate SDP answer.
269
+ *
270
+ * Creates RTCPeerConnection with detected codecs, sets up media tracks,
271
+ * processes the remote SDP offer, and generates a local SDP answer.
272
+ * Also configures ICE candidate handling via `onIceCandidate` callback in options.
273
+ * Must be called before {@link start}.
274
+ * Calling it again renegotiates: the previous peer connection is closed and
275
+ * replaced by a new one built from the new offer, while streaming continues.
276
+ *
277
+ * @param offerSdp - SDP offer string from remote WebRTC peer
278
+ *
279
+ * @returns SDP answer string to send back to remote peer
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * const session = await WebRTCStream.create('input.mp4');
284
+ *
285
+ * // Setup ICE candidate handler first
286
+ * session.onIceCandidate = (candidate) => {
287
+ * sendToRemote({ type: 'candidate', value: candidate });
288
+ * };
289
+ *
290
+ * // Process offer and send answer
291
+ * const answer = await session.setOffer(remoteOffer);
292
+ * sendToRemote({ type: 'answer', value: answer });
293
+ *
294
+ * // Start streaming
295
+ * await session.start();
296
+ * ```
297
+ */
298
+ async setOffer(offerSdp) {
299
+ // Renegotiation: dispose any previous peer connection first. Left alive, its
300
+ // connectionstatechange handler would later report 'failed'/'closed' and tear
301
+ // down the new session via stop(). Buffered candidates belong to the old ICE
302
+ // session, so drop them too.
303
+ if (this.pc) {
304
+ const oldPc = this.pc;
305
+ this.pc = null;
306
+ this.videoTrack = null;
307
+ this.audioTrack = null;
308
+ this.pendingIceCandidates = [];
309
+ try {
310
+ await oldPc.close();
311
+ }
312
+ catch {
313
+ // Old connection may already be gone - proceed with the new one.
314
+ }
315
+ }
316
+ const codecs = this.getCodecs();
317
+ const videoConfig = codecs.video ?? {
318
+ mimeType: 'video/H264',
319
+ clockRate: 90000,
320
+ payloadType: 96,
321
+ };
322
+ delete videoConfig.codecId;
323
+ const audioConfig = codecs.audio ?? {
324
+ mimeType: 'audio/opus',
325
+ clockRate: 48000,
326
+ channels: 2,
327
+ payloadType: 111,
328
+ };
329
+ delete audioConfig.codecId;
330
+ // Create PeerConnection with detected codecs
331
+ const codecParams = {
332
+ video: [
333
+ new RTCRtpCodecParameters({
334
+ ...videoConfig,
335
+ }),
336
+ ],
337
+ audio: [
338
+ new RTCRtpCodecParameters({
339
+ ...audioConfig,
340
+ }),
341
+ ],
342
+ };
343
+ const pc = new RTCPeerConnection({
344
+ codecs: codecParams,
345
+ iceServers: this.options.iceServers,
346
+ });
347
+ this.pc = pc;
348
+ // Tear down when the peer goes away. werift verifies ICE consent (RFC 7675)
349
+ // and reports 'failed' once the browser disconnects (tab closed/reloaded) -
350
+ // without this, the pipeline would keep encoding into the void forever.
351
+ pc.connectionStateChange.subscribe((state) => {
352
+ // Ignore stale events from a connection that was replaced by a newer
353
+ // setOffer() - they must not tear down the current session.
354
+ if (this.pc !== pc) {
355
+ return;
356
+ }
357
+ if ((state === 'failed' || state === 'closed') && !this.stopping) {
358
+ this.stop().catch(() => {
359
+ // Best-effort teardown - errors already surface via onClose(error).
360
+ });
361
+ }
362
+ });
363
+ // Setup ICE candidate handling
364
+ pc.onIceCandidate.subscribe((candidate) => {
365
+ if (candidate?.candidate && this.options.onIceCandidate) {
366
+ this.options.onIceCandidate(candidate.candidate);
367
+ }
368
+ });
369
+ // Setup tracks
370
+ pc.onRemoteTransceiverAdded.subscribe(async (transceiver) => {
371
+ if (transceiver.kind === 'video') {
372
+ this.videoTrack = new MediaStreamTrack({ kind: 'video' });
373
+ transceiver.sender.replaceTrack(this.videoTrack);
374
+ transceiver.setDirection('sendonly');
375
+ // Answer PLI feedback with a fresh keyframe - a receiver that connected
376
+ // after the stream started (or lost packets) can't decode until the next
377
+ // IDR, and it asks for one via RTCP PLI.
378
+ transceiver.sender.onPictureLossIndication.subscribe(() => {
379
+ this.stream.requestVideoKeyframe();
380
+ });
381
+ }
382
+ else if (transceiver.kind === 'audio' && this.audioTrack === null) {
383
+ this.audioTrack = new MediaStreamTrack({ kind: 'audio' });
384
+ transceiver.sender.replaceTrack(this.audioTrack);
385
+ transceiver.setDirection('sendonly');
386
+ }
387
+ else if (transceiver.kind === 'audio') {
388
+ // Backchannel
389
+ const [track] = await transceiver.onTrack.asPromise();
390
+ const input = this.stream.getInput();
391
+ const ctx = input?.getFormatContext();
392
+ const streams = ctx?.getRTSPStreamInfo();
393
+ const backchannel = streams?.find((s) => s.direction === 'sendonly' && s.mediaType === 'audio');
394
+ track.onReceiveRtp.subscribe(async (rtp) => {
395
+ if (backchannel && this.stream.isStreamActive) {
396
+ try {
397
+ await ctx?.sendRTSPPacket(backchannel.streamIndex, rtp.serialize());
398
+ }
399
+ catch {
400
+ // Ignore send errors
401
+ }
402
+ }
403
+ });
404
+ }
405
+ });
406
+ // Set remote description and create answer
407
+ await pc.setRemoteDescription(new RTCSessionDescription(offerSdp, 'offer'));
408
+ // The sender transmits with the FIRST negotiated codec, and browsers offer
409
+ // several H264 variants (packetization-mode=1 and =0). FFmpeg's RTP payloader
410
+ // fragments large NALs (FU-A), which is invalid under packetization-mode=0 -
411
+ // if that entry happened to be first, the receiver would silently discard
412
+ // every fragmented (key)frame. Prefer a packetization-mode=1 H264 entry.
413
+ for (const transceiver of pc.getTransceivers()) {
414
+ if (transceiver.kind !== 'video') {
415
+ continue;
416
+ }
417
+ transceiver.codecs = [...transceiver.codecs].sort((a, b) => {
418
+ const score = (codec) => codec.mimeType.toLowerCase() === 'video/h264' && !(codec.parameters ?? '').includes('packetization-mode=1') ? 1 : 0;
419
+ return score(a) - score(b);
420
+ });
421
+ }
422
+ const answer = await pc.createAnswer();
423
+ // Must be awaited: localDescription is only complete afterwards, and an
424
+ // un-awaited rejection would otherwise be unhandled.
425
+ await pc.setLocalDescription(answer);
426
+ // Apply any buffered ICE candidates now that remote description is set
427
+ if (this.pendingIceCandidates.length > 0) {
428
+ for (const candidate of this.pendingIceCandidates) {
429
+ pc.addIceCandidate(new RTCIceCandidate({ candidate }));
430
+ }
431
+ this.pendingIceCandidates = [];
432
+ }
433
+ // Start streaming - negotiation is done and the tracks exist, so the caller
434
+ // doesn't have to sequence start() themselves. Idempotent: calling start()
435
+ // before setOffer() (e.g. to have the input open for codec detection) is fine.
436
+ await this.start();
437
+ return pc.localDescription?.sdp ?? '';
438
+ }
439
+ /**
440
+ * Add ICE candidate from remote peer.
441
+ *
442
+ * Processes ICE candidates received from the remote peer via signaling channel.
443
+ * Should be called whenever a new candidate message arrives from remote peer.
444
+ * Can be called multiple times as candidates are discovered.
445
+ *
446
+ * Supports ICE trickling: If called before {@link setOffer}, candidates are buffered
447
+ * and applied automatically once the remote description is set.
448
+ *
449
+ * @param candidate - ICE candidate string from remote peer
450
+ *
451
+ * @example
452
+ * ```typescript
453
+ * // In signaling message handler
454
+ * if (msg.type === 'candidate') {
455
+ * session.addIceCandidate(msg.value);
456
+ * }
457
+ * ```
458
+ */
459
+ addIceCandidate(candidate) {
460
+ // Buffer candidates if peer connection not ready yet (ICE trickling)
461
+ if (!this.pc?.remoteDescription) {
462
+ this.pendingIceCandidates.push(candidate);
463
+ return;
464
+ }
465
+ // Apply candidate immediately if peer connection is ready
466
+ this.pc.addIceCandidate(new RTCIceCandidate({ candidate }));
467
+ }
468
+ /**
469
+ * Get video codec configuration from input stream.
470
+ *
471
+ * @param codecId - FFmpeg codec ID
472
+ *
473
+ * @returns RTP codec parameters with codec ID or undefined if unsupported
474
+ *
475
+ * @internal
476
+ */
477
+ getVideoCodecConfig(codecId) {
478
+ let mimeType;
479
+ const clockRate = 90000;
480
+ let payloadType;
481
+ switch (codecId) {
482
+ case AV_CODEC_ID_H264:
483
+ mimeType = 'video/H264';
484
+ payloadType = 96;
485
+ break;
486
+ case AV_CODEC_ID_HEVC:
487
+ mimeType = 'video/H265';
488
+ payloadType = 96;
489
+ break;
490
+ case AV_CODEC_ID_VP8:
491
+ mimeType = 'video/VP8';
492
+ payloadType = 96;
493
+ break;
494
+ case AV_CODEC_ID_VP9:
495
+ mimeType = 'video/VP9';
496
+ payloadType = 98;
497
+ break;
498
+ case AV_CODEC_ID_AV1:
499
+ mimeType = 'video/AV1';
500
+ payloadType = 98;
501
+ break;
502
+ default:
503
+ return undefined;
504
+ }
505
+ return { mimeType, clockRate, payloadType, codecId };
506
+ }
507
+ /**
508
+ * Get audio codec configuration from input stream.
509
+ *
510
+ * @param codecId - FFmpeg codec ID
511
+ *
512
+ * @returns RTP codec parameters with codec ID or undefined if unsupported
513
+ *
514
+ * @internal
515
+ */
516
+ getAudioCodecConfig(codecId) {
517
+ let mimeType;
518
+ let clockRate;
519
+ let channels;
520
+ let payloadType;
521
+ switch (codecId) {
522
+ case AV_CODEC_ID_OPUS:
523
+ mimeType = 'audio/opus';
524
+ clockRate = 48000;
525
+ channels = 2;
526
+ payloadType = 111;
527
+ break;
528
+ case AV_CODEC_ID_PCM_ALAW:
529
+ mimeType = 'audio/PCMA';
530
+ clockRate = 8000;
531
+ channels = 1;
532
+ payloadType = 8;
533
+ break;
534
+ case AV_CODEC_ID_PCM_MULAW:
535
+ mimeType = 'audio/PCMU';
536
+ clockRate = 8000;
537
+ channels = 1;
538
+ payloadType = 0;
539
+ break;
540
+ default:
541
+ return undefined;
542
+ }
543
+ return { mimeType, clockRate, channels, payloadType, codecId };
544
+ }
545
+ }
546
+ //# 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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"}