@revizly/node-av 5.2.2-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 (254) hide show
  1. package/BUILD_LINUX.md +61 -0
  2. package/LICENSE.md +22 -0
  3. package/README.md +662 -0
  4. package/build_mac_local.sh +69 -0
  5. package/dist/api/audio-frame-buffer.d.ts +205 -0
  6. package/dist/api/audio-frame-buffer.js +287 -0
  7. package/dist/api/audio-frame-buffer.js.map +1 -0
  8. package/dist/api/bitstream-filter.d.ts +820 -0
  9. package/dist/api/bitstream-filter.js +1242 -0
  10. package/dist/api/bitstream-filter.js.map +1 -0
  11. package/dist/api/constants.d.ts +44 -0
  12. package/dist/api/constants.js +45 -0
  13. package/dist/api/constants.js.map +1 -0
  14. package/dist/api/data/test_av1.ivf +0 -0
  15. package/dist/api/data/test_h264.h264 +0 -0
  16. package/dist/api/data/test_hevc.h265 +0 -0
  17. package/dist/api/data/test_mjpeg.mjpeg +0 -0
  18. package/dist/api/data/test_vp8.ivf +0 -0
  19. package/dist/api/data/test_vp9.ivf +0 -0
  20. package/dist/api/decoder.d.ts +1088 -0
  21. package/dist/api/decoder.js +1775 -0
  22. package/dist/api/decoder.js.map +1 -0
  23. package/dist/api/demuxer.d.ts +1219 -0
  24. package/dist/api/demuxer.js +2081 -0
  25. package/dist/api/demuxer.js.map +1 -0
  26. package/dist/api/device.d.ts +586 -0
  27. package/dist/api/device.js +961 -0
  28. package/dist/api/device.js.map +1 -0
  29. package/dist/api/encoder.d.ts +1132 -0
  30. package/dist/api/encoder.js +1988 -0
  31. package/dist/api/encoder.js.map +1 -0
  32. package/dist/api/filter-complex.d.ts +821 -0
  33. package/dist/api/filter-complex.js +1604 -0
  34. package/dist/api/filter-complex.js.map +1 -0
  35. package/dist/api/filter-presets.d.ts +1286 -0
  36. package/dist/api/filter-presets.js +2152 -0
  37. package/dist/api/filter-presets.js.map +1 -0
  38. package/dist/api/filter.d.ts +1234 -0
  39. package/dist/api/filter.js +1976 -0
  40. package/dist/api/filter.js.map +1 -0
  41. package/dist/api/fmp4-stream.d.ts +426 -0
  42. package/dist/api/fmp4-stream.js +739 -0
  43. package/dist/api/fmp4-stream.js.map +1 -0
  44. package/dist/api/hardware.d.ts +651 -0
  45. package/dist/api/hardware.js +1260 -0
  46. package/dist/api/hardware.js.map +1 -0
  47. package/dist/api/index.d.ts +17 -0
  48. package/dist/api/index.js +32 -0
  49. package/dist/api/index.js.map +1 -0
  50. package/dist/api/io-stream.d.ts +307 -0
  51. package/dist/api/io-stream.js +282 -0
  52. package/dist/api/io-stream.js.map +1 -0
  53. package/dist/api/muxer.d.ts +957 -0
  54. package/dist/api/muxer.js +2002 -0
  55. package/dist/api/muxer.js.map +1 -0
  56. package/dist/api/pipeline.d.ts +607 -0
  57. package/dist/api/pipeline.js +1145 -0
  58. package/dist/api/pipeline.js.map +1 -0
  59. package/dist/api/utilities/async-queue.d.ts +120 -0
  60. package/dist/api/utilities/async-queue.js +211 -0
  61. package/dist/api/utilities/async-queue.js.map +1 -0
  62. package/dist/api/utilities/audio-sample.d.ts +117 -0
  63. package/dist/api/utilities/audio-sample.js +112 -0
  64. package/dist/api/utilities/audio-sample.js.map +1 -0
  65. package/dist/api/utilities/channel-layout.d.ts +76 -0
  66. package/dist/api/utilities/channel-layout.js +80 -0
  67. package/dist/api/utilities/channel-layout.js.map +1 -0
  68. package/dist/api/utilities/electron-shared-texture.d.ts +328 -0
  69. package/dist/api/utilities/electron-shared-texture.js +503 -0
  70. package/dist/api/utilities/electron-shared-texture.js.map +1 -0
  71. package/dist/api/utilities/image.d.ts +207 -0
  72. package/dist/api/utilities/image.js +213 -0
  73. package/dist/api/utilities/image.js.map +1 -0
  74. package/dist/api/utilities/index.d.ts +12 -0
  75. package/dist/api/utilities/index.js +25 -0
  76. package/dist/api/utilities/index.js.map +1 -0
  77. package/dist/api/utilities/media-type.d.ts +49 -0
  78. package/dist/api/utilities/media-type.js +53 -0
  79. package/dist/api/utilities/media-type.js.map +1 -0
  80. package/dist/api/utilities/pixel-format.d.ts +89 -0
  81. package/dist/api/utilities/pixel-format.js +97 -0
  82. package/dist/api/utilities/pixel-format.js.map +1 -0
  83. package/dist/api/utilities/sample-format.d.ts +129 -0
  84. package/dist/api/utilities/sample-format.js +141 -0
  85. package/dist/api/utilities/sample-format.js.map +1 -0
  86. package/dist/api/utilities/scheduler.d.ts +138 -0
  87. package/dist/api/utilities/scheduler.js +98 -0
  88. package/dist/api/utilities/scheduler.js.map +1 -0
  89. package/dist/api/utilities/streaming.d.ts +186 -0
  90. package/dist/api/utilities/streaming.js +309 -0
  91. package/dist/api/utilities/streaming.js.map +1 -0
  92. package/dist/api/utilities/timestamp.d.ts +193 -0
  93. package/dist/api/utilities/timestamp.js +206 -0
  94. package/dist/api/utilities/timestamp.js.map +1 -0
  95. package/dist/api/utilities/whisper-model.d.ts +310 -0
  96. package/dist/api/utilities/whisper-model.js +528 -0
  97. package/dist/api/utilities/whisper-model.js.map +1 -0
  98. package/dist/api/utils.d.ts +19 -0
  99. package/dist/api/utils.js +39 -0
  100. package/dist/api/utils.js.map +1 -0
  101. package/dist/api/whisper.d.ts +324 -0
  102. package/dist/api/whisper.js +362 -0
  103. package/dist/api/whisper.js.map +1 -0
  104. package/dist/constants/channel-layouts.d.ts +53 -0
  105. package/dist/constants/channel-layouts.js +57 -0
  106. package/dist/constants/channel-layouts.js.map +1 -0
  107. package/dist/constants/constants.d.ts +2325 -0
  108. package/dist/constants/constants.js +1887 -0
  109. package/dist/constants/constants.js.map +1 -0
  110. package/dist/constants/decoders.d.ts +633 -0
  111. package/dist/constants/decoders.js +641 -0
  112. package/dist/constants/decoders.js.map +1 -0
  113. package/dist/constants/encoders.d.ts +295 -0
  114. package/dist/constants/encoders.js +308 -0
  115. package/dist/constants/encoders.js.map +1 -0
  116. package/dist/constants/hardware.d.ts +26 -0
  117. package/dist/constants/hardware.js +27 -0
  118. package/dist/constants/hardware.js.map +1 -0
  119. package/dist/constants/index.d.ts +5 -0
  120. package/dist/constants/index.js +6 -0
  121. package/dist/constants/index.js.map +1 -0
  122. package/dist/ffmpeg/index.d.ts +99 -0
  123. package/dist/ffmpeg/index.js +115 -0
  124. package/dist/ffmpeg/index.js.map +1 -0
  125. package/dist/ffmpeg/utils.d.ts +31 -0
  126. package/dist/ffmpeg/utils.js +68 -0
  127. package/dist/ffmpeg/utils.js.map +1 -0
  128. package/dist/ffmpeg/version.d.ts +6 -0
  129. package/dist/ffmpeg/version.js +7 -0
  130. package/dist/ffmpeg/version.js.map +1 -0
  131. package/dist/index.d.ts +4 -0
  132. package/dist/index.js +9 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/lib/audio-fifo.d.ts +399 -0
  135. package/dist/lib/audio-fifo.js +431 -0
  136. package/dist/lib/audio-fifo.js.map +1 -0
  137. package/dist/lib/binding.d.ts +228 -0
  138. package/dist/lib/binding.js +60 -0
  139. package/dist/lib/binding.js.map +1 -0
  140. package/dist/lib/bitstream-filter-context.d.ts +379 -0
  141. package/dist/lib/bitstream-filter-context.js +441 -0
  142. package/dist/lib/bitstream-filter-context.js.map +1 -0
  143. package/dist/lib/bitstream-filter.d.ts +140 -0
  144. package/dist/lib/bitstream-filter.js +154 -0
  145. package/dist/lib/bitstream-filter.js.map +1 -0
  146. package/dist/lib/codec-context.d.ts +1071 -0
  147. package/dist/lib/codec-context.js +1354 -0
  148. package/dist/lib/codec-context.js.map +1 -0
  149. package/dist/lib/codec-parameters.d.ts +616 -0
  150. package/dist/lib/codec-parameters.js +761 -0
  151. package/dist/lib/codec-parameters.js.map +1 -0
  152. package/dist/lib/codec-parser.d.ts +201 -0
  153. package/dist/lib/codec-parser.js +213 -0
  154. package/dist/lib/codec-parser.js.map +1 -0
  155. package/dist/lib/codec.d.ts +586 -0
  156. package/dist/lib/codec.js +713 -0
  157. package/dist/lib/codec.js.map +1 -0
  158. package/dist/lib/device.d.ts +291 -0
  159. package/dist/lib/device.js +324 -0
  160. package/dist/lib/device.js.map +1 -0
  161. package/dist/lib/dictionary.d.ts +333 -0
  162. package/dist/lib/dictionary.js +372 -0
  163. package/dist/lib/dictionary.js.map +1 -0
  164. package/dist/lib/error.d.ts +242 -0
  165. package/dist/lib/error.js +303 -0
  166. package/dist/lib/error.js.map +1 -0
  167. package/dist/lib/fifo.d.ts +416 -0
  168. package/dist/lib/fifo.js +453 -0
  169. package/dist/lib/fifo.js.map +1 -0
  170. package/dist/lib/filter-context.d.ts +712 -0
  171. package/dist/lib/filter-context.js +789 -0
  172. package/dist/lib/filter-context.js.map +1 -0
  173. package/dist/lib/filter-graph-segment.d.ts +160 -0
  174. package/dist/lib/filter-graph-segment.js +171 -0
  175. package/dist/lib/filter-graph-segment.js.map +1 -0
  176. package/dist/lib/filter-graph.d.ts +641 -0
  177. package/dist/lib/filter-graph.js +704 -0
  178. package/dist/lib/filter-graph.js.map +1 -0
  179. package/dist/lib/filter-inout.d.ts +198 -0
  180. package/dist/lib/filter-inout.js +257 -0
  181. package/dist/lib/filter-inout.js.map +1 -0
  182. package/dist/lib/filter.d.ts +243 -0
  183. package/dist/lib/filter.js +272 -0
  184. package/dist/lib/filter.js.map +1 -0
  185. package/dist/lib/format-context.d.ts +1254 -0
  186. package/dist/lib/format-context.js +1379 -0
  187. package/dist/lib/format-context.js.map +1 -0
  188. package/dist/lib/frame-utils.d.ts +116 -0
  189. package/dist/lib/frame-utils.js +98 -0
  190. package/dist/lib/frame-utils.js.map +1 -0
  191. package/dist/lib/frame.d.ts +1222 -0
  192. package/dist/lib/frame.js +1435 -0
  193. package/dist/lib/frame.js.map +1 -0
  194. package/dist/lib/hardware-device-context.d.ts +362 -0
  195. package/dist/lib/hardware-device-context.js +383 -0
  196. package/dist/lib/hardware-device-context.js.map +1 -0
  197. package/dist/lib/hardware-frames-context.d.ts +419 -0
  198. package/dist/lib/hardware-frames-context.js +477 -0
  199. package/dist/lib/hardware-frames-context.js.map +1 -0
  200. package/dist/lib/index.d.ts +35 -0
  201. package/dist/lib/index.js +60 -0
  202. package/dist/lib/index.js.map +1 -0
  203. package/dist/lib/input-format.d.ts +249 -0
  204. package/dist/lib/input-format.js +306 -0
  205. package/dist/lib/input-format.js.map +1 -0
  206. package/dist/lib/io-context.d.ts +696 -0
  207. package/dist/lib/io-context.js +769 -0
  208. package/dist/lib/io-context.js.map +1 -0
  209. package/dist/lib/log.d.ts +174 -0
  210. package/dist/lib/log.js +184 -0
  211. package/dist/lib/log.js.map +1 -0
  212. package/dist/lib/native-types.d.ts +946 -0
  213. package/dist/lib/native-types.js +2 -0
  214. package/dist/lib/native-types.js.map +1 -0
  215. package/dist/lib/option.d.ts +927 -0
  216. package/dist/lib/option.js +1583 -0
  217. package/dist/lib/option.js.map +1 -0
  218. package/dist/lib/output-format.d.ts +180 -0
  219. package/dist/lib/output-format.js +213 -0
  220. package/dist/lib/output-format.js.map +1 -0
  221. package/dist/lib/packet.d.ts +501 -0
  222. package/dist/lib/packet.js +590 -0
  223. package/dist/lib/packet.js.map +1 -0
  224. package/dist/lib/rational.d.ts +251 -0
  225. package/dist/lib/rational.js +278 -0
  226. package/dist/lib/rational.js.map +1 -0
  227. package/dist/lib/software-resample-context.d.ts +552 -0
  228. package/dist/lib/software-resample-context.js +592 -0
  229. package/dist/lib/software-resample-context.js.map +1 -0
  230. package/dist/lib/software-scale-context.d.ts +344 -0
  231. package/dist/lib/software-scale-context.js +366 -0
  232. package/dist/lib/software-scale-context.js.map +1 -0
  233. package/dist/lib/stream.d.ts +379 -0
  234. package/dist/lib/stream.js +526 -0
  235. package/dist/lib/stream.js.map +1 -0
  236. package/dist/lib/sync-queue.d.ts +179 -0
  237. package/dist/lib/sync-queue.js +197 -0
  238. package/dist/lib/sync-queue.js.map +1 -0
  239. package/dist/lib/types.d.ts +34 -0
  240. package/dist/lib/types.js +2 -0
  241. package/dist/lib/types.js.map +1 -0
  242. package/dist/lib/utilities.d.ts +1127 -0
  243. package/dist/lib/utilities.js +1225 -0
  244. package/dist/lib/utilities.js.map +1 -0
  245. package/dist/utils/electron.d.ts +49 -0
  246. package/dist/utils/electron.js +63 -0
  247. package/dist/utils/electron.js.map +1 -0
  248. package/dist/utils/index.d.ts +4 -0
  249. package/dist/utils/index.js +5 -0
  250. package/dist/utils/index.js.map +1 -0
  251. package/install/check.js +121 -0
  252. package/install/ffmpeg.js +66 -0
  253. package/jellyfin-ffmpeg.patch +181 -0
  254. package/package.json +129 -0
@@ -0,0 +1,957 @@
1
+ import { Writable } from 'node:stream';
2
+ import { FormatContext } from '../lib/format-context.js';
3
+ import { Packet } from '../lib/packet.js';
4
+ import { Encoder } from './encoder.js';
5
+ import type { OutputFormat, Stream } from '../lib/index.js';
6
+ import type { Demuxer, RTPDemuxer } from './demuxer.js';
7
+ import type { IOOutputCallbacks } from './io-stream.js';
8
+ /**
9
+ * Options for Muxer creation.
10
+ */
11
+ export interface MuxerOptions {
12
+ /**
13
+ * Input media for automatic metadata and property copying.
14
+ *
15
+ * When provided, Muxer will automatically copy:
16
+ * - Container-level metadata (title, artist, etc.)
17
+ * - Stream-level metadata
18
+ * - Disposition flags (DEFAULT, FORCED, etc.)
19
+ * - Duration hints for encoding
20
+ *
21
+ * This matches FFmpeg CLI behavior which copies metadata by default.
22
+ */
23
+ input?: Demuxer | RTPDemuxer;
24
+ /**
25
+ * Preferred output format.
26
+ *
27
+ * If not specified, format is guessed from file extension.
28
+ * Use this to override automatic format detection.
29
+ *
30
+ * Matches FFmpeg CLI's -f option.
31
+ */
32
+ format?: string;
33
+ /**
34
+ * Buffer size for I/O operations.
35
+ *
36
+ * This option controls the size of the internal buffer used for
37
+ * reading and writing data.
38
+ *
39
+ * @default 32768 (32 KB, matches FFmpeg CLI default)
40
+ */
41
+ bufferSize?: number;
42
+ /**
43
+ * Maximum packet size for I/O operations.
44
+ *
45
+ * This option controls the maximum size of individual packets
46
+ * for protocols that require specific packet sizes (e.g., RTP with MTU constraints).
47
+ *
48
+ * Matches FFmpeg's max_packet_size in AVIOContext.
49
+ *
50
+ * @default 1200
51
+ */
52
+ maxPacketSize?: number;
53
+ /**
54
+ * Exit immediately on first write error.
55
+ *
56
+ * When enabled, the muxer will terminate on the first write error.
57
+ * When disabled, errors are logged but processing continues.
58
+ *
59
+ * @default true
60
+ */
61
+ exitOnError?: boolean;
62
+ /**
63
+ * Maximum number of packets to buffer per stream in the sync queue.
64
+ *
65
+ * Matches FFmpeg CLI's -max_muxing_queue_size option.
66
+ * Limits memory usage when encoders are still initializing.
67
+ * Takes effect after muxingQueueDataThreshold is reached.
68
+ * If exceeded, an error is thrown.
69
+ *
70
+ * @default 128 (same as FFmpeg CLI)
71
+ */
72
+ maxMuxingQueueSize?: number;
73
+ /**
74
+ * Threshold in bytes after which maxMuxingQueueSize takes effect.
75
+ *
76
+ * Matches FFmpeg CLI's -muxing_queue_data_threshold option.
77
+ * Once this threshold is reached, maxMuxingQueueSize limit applies.
78
+ * This is an intelligent system: small streams (audio) can buffer many packets,
79
+ * large streams (video) are limited by packet count.
80
+ *
81
+ * @default 52428800 (50 MB, same as FFmpeg CLI)
82
+ */
83
+ muxingQueueDataThreshold?: number;
84
+ /**
85
+ * Maximum buffering duration in seconds for sync queue interleaving.
86
+ *
87
+ * Matches FFmpeg CLI's -shortest_buf_duration option.
88
+ * Controls how much buffering is allowed in the native sync queue
89
+ * for packet interleaving across multiple streams.
90
+ *
91
+ * @default 10 (same as FFmpeg CLI)
92
+ */
93
+ syncQueueBufferDuration?: number;
94
+ /**
95
+ * Start time offset in seconds for output timestamps.
96
+ *
97
+ * Matches FFmpeg CLI's -ss (output) option.
98
+ * Subtracts this offset from all packet timestamps.
99
+ * Use for trimming from start of stream.
100
+ *
101
+ * @default AV_NOPTS_VALUE (no offset)
102
+ */
103
+ startTime?: number;
104
+ /**
105
+ * Whether to copy initial non-keyframe packets in streamcopy mode.
106
+ *
107
+ * Matches FFmpeg CLI's -copyinkf option.
108
+ * If false (default), packets before first keyframe are skipped.
109
+ * If true, all packets from start are copied.
110
+ *
111
+ * @default false
112
+ */
113
+ copyInitialNonkeyframes?: boolean;
114
+ /**
115
+ * Copy or discard frames before start time.
116
+ *
117
+ * Matches FFmpeg CLI's -copypriorss option.
118
+ * Controls whether packets before the start time are copied:
119
+ * - -1 (default): Use FFmpeg's internal ts_copy_start calculation
120
+ * - 0: Discard packets before start time
121
+ * - 1: Copy all packets regardless of start time
122
+ *
123
+ * @default -1
124
+ */
125
+ copyPriorStart?: number;
126
+ /**
127
+ * Use synchronous packet queue for interleaving.
128
+ *
129
+ * When true and there are stream copy streams present, enables FFmpeg's
130
+ * sync queue for proper interleaving of packets based on timestamps.
131
+ *
132
+ * The sync queue is only activated when both conditions are met:
133
+ * - `useSyncQueue` is `true`
134
+ * - Output contains at least one stream copy stream
135
+ *
136
+ * This includes scenarios with:
137
+ * - Only stream copy streams (e.g., 1 streamcopy stream)
138
+ * - Mixed streams (e.g., 1 streamcopy + 1 encoded stream)
139
+ *
140
+ * For outputs with only encoded streams, the sync queue is not used.
141
+ *
142
+ * @default true
143
+ */
144
+ useSyncQueue?: boolean;
145
+ /**
146
+ * Use asynchronous write queue to prevent race conditions.
147
+ *
148
+ * When true and there are multiple streams (> 1), all write operations
149
+ * are serialized through an async queue, preventing concurrent access
150
+ * to AVFormatContext which can cause "Packet duration out of range"
151
+ * errors with parallel encoding.
152
+ *
153
+ * The async queue is only activated when both conditions are met:
154
+ * - `useAsyncWrite` is `true`
155
+ * - Output has more than one stream
156
+ *
157
+ * For single-stream outputs, writes are performed directly without
158
+ * queuing, regardless of this setting.
159
+ *
160
+ * @default true
161
+ */
162
+ useAsyncWrite?: boolean;
163
+ /**
164
+ * FFmpeg format options passed directly to the output.
165
+ *
166
+ * Key-value pairs of FFmpeg AVFormatContext options.
167
+ * These are passed directly to avformat_write_header().
168
+ */
169
+ options?: Record<string, string | number | boolean | bigint | undefined | null>;
170
+ /**
171
+ * AbortSignal for cancellation.
172
+ *
173
+ * When aborted, async methods throw AbortError.
174
+ */
175
+ signal?: AbortSignal;
176
+ }
177
+ /**
178
+ * High-level muxer for writing and muxing media files.
179
+ *
180
+ * Provides simplified access to media muxing and file writing operations.
181
+ * Automatically manages header and trailer writing - header is written on first packet,
182
+ * trailer is written on close. Supports lazy initialization for both encoders and streams.
183
+ * Handles stream configuration, packet writing, and format management.
184
+ * Supports files, URLs, and custom I/O with automatic cleanup.
185
+ * Essential component for media encoding pipelines and transcoding.
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * import { Muxer } from 'node-av/api';
190
+ *
191
+ * // Create output file
192
+ * await using output = await Muxer.open('output.mp4');
193
+ *
194
+ * // Add streams from encoders
195
+ * const videoIdx = output.addStream(videoEncoder);
196
+ * const audioIdx = output.addStream(audioEncoder);
197
+ *
198
+ * // Write packets - header written automatically on first packet
199
+ * await output.writePacket(packet, videoIdx);
200
+ *
201
+ * // Close - trailer written automatically
202
+ * // (automatic with await using)
203
+ * ```
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * // Stream copy
208
+ * await using input = await Demuxer.open('input.mp4');
209
+ * await using output = await Muxer.open('output.mp4');
210
+ *
211
+ * // Copy stream configuration
212
+ * const videoIdx = output.addStream(input.video());
213
+ *
214
+ * // Process packets - header/trailer handled automatically
215
+ * for await (const packet of input.packets()) {
216
+ * await output.writePacket(packet, videoIdx);
217
+ * packet.free();
218
+ * }
219
+ * ```
220
+ *
221
+ * @see {@link Demuxer} For reading media files
222
+ * @see {@link Encoder} For encoding frames to packets
223
+ * @see {@link FormatContext} For low-level API
224
+ */
225
+ export declare class Muxer implements AsyncDisposable, Disposable {
226
+ private formatContext;
227
+ private options;
228
+ private _streams;
229
+ private ioContext?;
230
+ private headerWritten;
231
+ private headerWritePromise?;
232
+ private trailerWritten;
233
+ private isClosed;
234
+ private syncQueue?;
235
+ private sqPacket?;
236
+ private containerMetadataCopied;
237
+ private writeQueue?;
238
+ private writeWorkerPromise?;
239
+ private signal?;
240
+ /**
241
+ * @param options - Media output options
242
+ *
243
+ * @internal
244
+ */
245
+ private constructor();
246
+ /**
247
+ * Open muxer for writing.
248
+ *
249
+ * Creates and configures output context for muxing.
250
+ * Automatically creates directories for file output.
251
+ * Supports files, URLs, and custom I/O callbacks.
252
+ *
253
+ * Direct mapping to avformat_alloc_output_context2() and avio_open2().
254
+ *
255
+ * @param target - File path, URL, or I/O callbacks
256
+ *
257
+ * @param options - Output configuration options
258
+ *
259
+ * @returns Opened muxer instance
260
+ *
261
+ * @throws {Error} If format required for custom I/O
262
+ *
263
+ * @throws {FFmpegError} If allocation or opening fails
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * // Create file output
268
+ * await using output = await Muxer.open('output.mp4');
269
+ * ```
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * // Create output with specific format
274
+ * await using output = await Muxer.open('output.ts', {
275
+ * format: 'mpegts'
276
+ * });
277
+ * ```
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * // Custom I/O callbacks - async streaming to web destination
282
+ * const callbacks = {
283
+ * write: async (buffer: Buffer) => {
284
+ * await streamWriter.write(buffer);
285
+ * return buffer.length;
286
+ * }
287
+ * };
288
+ *
289
+ * await using output = await Muxer.open(callbacks, {
290
+ * format: 'mp4',
291
+ * bufferSize: 8192
292
+ * });
293
+ * ```
294
+ *
295
+ * @example
296
+ * ```typescript
297
+ * // Custom I/O callbacks - synchronous buffering
298
+ * const chunks: Buffer[] = [];
299
+ * const callbacks = {
300
+ * write: (buffer: Buffer) => {
301
+ * chunks.push(Buffer.from(buffer));
302
+ * return buffer.length;
303
+ * }
304
+ * };
305
+ *
306
+ * await using output = await Muxer.open(callbacks, { format: 'mp4' });
307
+ * ```
308
+ *
309
+ * @see {@link MuxerOptions} For configuration options
310
+ * @see {@link IOOutputCallbacks} For custom I/O interface
311
+ */
312
+ static open(target: string, options?: MuxerOptions): Promise<Muxer>;
313
+ static open(target: IOOutputCallbacks, options: MuxerOptions & {
314
+ format: string;
315
+ }): Promise<Muxer>;
316
+ static open(target: Writable, options: MuxerOptions & {
317
+ format: string;
318
+ }): Promise<Muxer>;
319
+ /**
320
+ * Open muxer for writing synchronously.
321
+ * Synchronous version of open.
322
+ *
323
+ * Creates and configures output context for muxing.
324
+ * Automatically creates directories for file output.
325
+ * Supports files, URLs, and custom I/O callbacks.
326
+ *
327
+ * Direct mapping to avformat_alloc_output_context2() and avio_open2().
328
+ *
329
+ * @param target - File path, URL, or I/O callbacks
330
+ *
331
+ * @param options - Output configuration options
332
+ *
333
+ * @returns Opened muxer instance
334
+ *
335
+ * @throws {Error} If format required for custom I/O
336
+ *
337
+ * @throws {FFmpegError} If allocation or opening fails
338
+ *
339
+ * @example
340
+ * ```typescript
341
+ * // Create file output
342
+ * using output = Muxer.openSync('output.mp4');
343
+ * ```
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * // Create output with specific format
348
+ * using output = Muxer.openSync('output.ts', {
349
+ * format: 'mpegts'
350
+ * });
351
+ * ```
352
+ *
353
+ * @see {@link open} For async version
354
+ */
355
+ static openSync(target: string, options?: MuxerOptions): Muxer;
356
+ static openSync(target: IOOutputCallbacks, options: MuxerOptions & {
357
+ format: string;
358
+ }): Muxer;
359
+ static openSync(target: Writable, options: MuxerOptions & {
360
+ format: string;
361
+ }): Muxer;
362
+ /**
363
+ * Check if output is open.
364
+ *
365
+ * @example
366
+ * ```typescript
367
+ * if (!output.isOutputOpen) {
368
+ * console.log('Output is not open');
369
+ * }
370
+ * ```
371
+ */
372
+ get isOpen(): boolean;
373
+ /**
374
+ * Check if output is initialized.
375
+ *
376
+ * All streams have been initialized.
377
+ * This occurs after the first packet has been written to each stream.
378
+ *
379
+ * @example
380
+ * ```typescript
381
+ * if (!output.isOutputInitialized) {
382
+ * console.log('Output is not initialized');
383
+ * }
384
+ * ```
385
+ */
386
+ get streamsInitialized(): boolean;
387
+ /**
388
+ * Get all streams in the media.
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * for (const stream of output.streams) {
393
+ * console.log(`Stream ${stream.index}: ${stream.codecpar.codecType}`);
394
+ * }
395
+ * ```
396
+ */
397
+ get streams(): Stream[];
398
+ /**
399
+ * Get format name.
400
+ *
401
+ * Returns 'unknown' if output is closed or format is not available.
402
+ *
403
+ * @example
404
+ * ```typescript
405
+ * console.log(`Format: ${output.formatName}`); // "mov,mp4,m4a,3gp,3g2,mj2"
406
+ * ```
407
+ */
408
+ get formatName(): string;
409
+ /**
410
+ * Get format long name.
411
+ *
412
+ * Returns 'Unknown Format' if output is closed or format is not available.
413
+ *
414
+ * @example
415
+ * ```typescript
416
+ * console.log(`Format: ${output.formatLongName}`); // "QuickTime / MOV"
417
+ * ```
418
+ */
419
+ get formatLongName(): string;
420
+ /**
421
+ * Get MIME type of the output format.
422
+ *
423
+ * Returns format's native MIME type.
424
+ * Returns null if output is closed or format is not available.
425
+ *
426
+ * @example
427
+ * ```typescript
428
+ * console.log(mp4Output.mimeType); // "video/mp4"
429
+ * ```
430
+ */
431
+ get mimeType(): string | null;
432
+ /**
433
+ * Add a stream to the output (encoder-only mode).
434
+ *
435
+ * Configures output stream from encoder. Stream is initialized lazily from first encoded frame.
436
+ * Use this when generating frames programmatically without an input stream.
437
+ *
438
+ * @param encoder - Encoder for encoding frames to packets
439
+ *
440
+ * @param options - Stream configuration options
441
+ *
442
+ * @param options.inputStream - Optional input stream for metadata/properties
443
+ *
444
+ * @returns Stream index for packet writing
445
+ *
446
+ * @throws {Error} If called after packets have been written or output closed
447
+ *
448
+ * @example
449
+ * ```typescript
450
+ * // Encoder-only (e.g., frame generator)
451
+ * const encoder = await Encoder.create(FF_ENCODER_LIBX264);
452
+ * const streamIdx = output.addStream(encoder);
453
+ * ```
454
+ *
455
+ * @example
456
+ * ```typescript
457
+ * // Encoder with input stream for metadata
458
+ * const streamIdx = output.addStream(encoder, {
459
+ * inputStream: input.video()
460
+ * });
461
+ * ```
462
+ */
463
+ addStream(encoder: Encoder, options?: {
464
+ inputStream?: Stream;
465
+ }): number;
466
+ /**
467
+ * Add a stream to the output (stream copy or transcoding mode).
468
+ *
469
+ * Configures output stream from input stream and optional encoder.
470
+ * Must be called before writing any packets.
471
+ * Returns stream index for packet writing.
472
+ *
473
+ * Automatically copies from input stream:
474
+ * - Codec parameters (stream copy mode)
475
+ * - Metadata
476
+ * - Disposition flags
477
+ * - Frame rates and aspect ratios
478
+ * - Duration hints
479
+ * - HDR/Dolby Vision side data (coded_side_data)
480
+ *
481
+ * When encoder is provided:
482
+ * - Stream is initialized lazily from first encoded frame
483
+ * - Metadata and disposition copied from input stream
484
+ * - Duration hint used for muxer
485
+ *
486
+ * Direct mapping to avformat_new_stream().
487
+ *
488
+ * @param stream - Input stream (source for properties/metadata)
489
+ *
490
+ * @param options - Stream configuration options
491
+ *
492
+ * @param options.encoder - Optional encoder for transcoding
493
+ *
494
+ * @returns Stream index for packet writing
495
+ *
496
+ * @throws {Error} If called after packets have been written or output closed
497
+ *
498
+ * @example
499
+ * ```typescript
500
+ * // Stream copy
501
+ * const videoIdx = output.addStream(input.video());
502
+ * const audioIdx = output.addStream(input.audio());
503
+ * ```
504
+ *
505
+ * @example
506
+ * ```typescript
507
+ * // With encoding
508
+ * const videoIdx = output.addStream(input.video(), {
509
+ * encoder: videoEncoder
510
+ * });
511
+ * ```
512
+ *
513
+ * @see {@link writePacket} For writing packets to streams
514
+ * @see {@link Encoder} For transcoding source
515
+ */
516
+ addStream(stream: Stream, options?: {
517
+ encoder?: Encoder;
518
+ }): number;
519
+ /**
520
+ * Get output stream by index.
521
+ *
522
+ * Returns the stream at the specified index.
523
+ * Use the stream index returned by addStream().
524
+ *
525
+ * @param index - Stream index (returned by addStream)
526
+ *
527
+ * @returns Stream or undefined if index is invalid
528
+ *
529
+ * @example
530
+ * ```typescript
531
+ * const output = await Muxer.open('output.mp4');
532
+ * const videoIdx = output.addStream(encoder);
533
+ *
534
+ * // Get the output stream to inspect codec parameters
535
+ * const stream = output.getStream(videoIdx);
536
+ * if (stream) {
537
+ * console.log(`Output codec: ${stream.codecpar.codecId}`);
538
+ * }
539
+ * ```
540
+ *
541
+ * @see {@link addStream} For adding streams
542
+ * @see {@link video} For getting video streams
543
+ * @see {@link audio} For getting audio streams
544
+ */
545
+ getStream(index: number): Stream | undefined;
546
+ /**
547
+ * Get video stream by index.
548
+ *
549
+ * Returns the nth video stream (0-based index).
550
+ * Returns undefined if stream doesn't exist.
551
+ *
552
+ * @param index - Video stream index (default: 0)
553
+ *
554
+ * @returns Video stream or undefined
555
+ *
556
+ * @example
557
+ * ```typescript
558
+ * const output = await Muxer.open('output.mp4');
559
+ * output.addStream(videoEncoder);
560
+ *
561
+ * // Get first video stream
562
+ * const videoStream = output.video();
563
+ * if (videoStream) {
564
+ * console.log(`Video output: ${videoStream.codecpar.width}x${videoStream.codecpar.height}`);
565
+ * }
566
+ * ```
567
+ *
568
+ * @see {@link audio} For audio streams
569
+ * @see {@link getStream} For direct stream access
570
+ */
571
+ video(index?: number): Stream | undefined;
572
+ /**
573
+ * Get audio stream by index.
574
+ *
575
+ * Returns the nth audio stream (0-based index).
576
+ * Returns undefined if stream doesn't exist.
577
+ *
578
+ * @param index - Audio stream index (default: 0)
579
+ *
580
+ * @returns Audio stream or undefined
581
+ *
582
+ * @example
583
+ * ```typescript
584
+ * const output = await Muxer.open('output.mp4');
585
+ * output.addStream(audioEncoder);
586
+ *
587
+ * // Get first audio stream
588
+ * const audioStream = output.audio();
589
+ * if (audioStream) {
590
+ * console.log(`Audio output: ${audioStream.codecpar.sampleRate}Hz`);
591
+ * }
592
+ * ```
593
+ *
594
+ * @see {@link video} For video streams
595
+ * @see {@link getStream} For direct stream access
596
+ */
597
+ audio(index?: number): Stream | undefined;
598
+ /**
599
+ * Get output format.
600
+ *
601
+ * Returns the output format used for muxing.
602
+ * May be null if format context not initialized.
603
+ *
604
+ * @returns Output format or null
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * const output = await Muxer.open('output.mp4');
609
+ * const format = output.outputFormat();
610
+ * if (format) {
611
+ * console.log(`Output format: ${format.name}`);
612
+ * }
613
+ * ```
614
+ *
615
+ * @see {@link OutputFormat} For format details
616
+ */
617
+ outputFormat(): OutputFormat | null;
618
+ /**
619
+ * Write a packet to the output.
620
+ *
621
+ * Writes muxed packet to the specified stream.
622
+ * Automatically handles:
623
+ * - Stream initialization on first packet (lazy initialization)
624
+ * - Codec parameter configuration from encoder or input stream
625
+ * - Header writing on first packet
626
+ * - Timestamp rescaling between source and output timebases
627
+ * - Sync queue for proper interleaving
628
+ *
629
+ * For encoder sources, the encoder must have processed at least one frame
630
+ * before packets can be written (encoder must be initialized).
631
+ *
632
+ * Uses FFmpeg CLI's sync queue pattern: buffers packets per stream and writes
633
+ * them in DTS order using av_compare_ts for timebase-aware comparison.
634
+ *
635
+ * To signal EOF for a stream, pass null as the packet.
636
+ * This tells the muxer that no more packets will be sent for this stream.
637
+ * The trailer is written only when close() is called.
638
+ *
639
+ * Direct mapping to avformat_write_header() (on first packet) and av_interleaved_write_frame().
640
+ *
641
+ * @param packet - Packet to write (or null to signal EOF for the stream)
642
+ *
643
+ * @param streamIndex - Target stream index
644
+ *
645
+ * @throws {Error} If stream invalid or encoder not initialized
646
+ *
647
+ * @throws {FFmpegError} If write fails
648
+ *
649
+ * @example
650
+ * ```typescript
651
+ * // Write encoded packet - header written automatically on first packet
652
+ * const packet = await encoder.encode(frame);
653
+ * if (packet) {
654
+ * await output.writePacket(packet, videoIdx);
655
+ * packet.free();
656
+ * }
657
+ * ```
658
+ *
659
+ * @example
660
+ * ```typescript
661
+ * // Stream copy with packet processing
662
+ * for await (const packet of input.packets()) {
663
+ * if (packet.streamIndex === inputVideoIdx) {
664
+ * await output.writePacket(packet, outputVideoIdx);
665
+ * }
666
+ * packet.free();
667
+ * }
668
+ * ```
669
+ *
670
+ * @see {@link addStream} For adding streams
671
+ */
672
+ writePacket(packet: Packet | null | undefined, streamIndex: number): Promise<void>;
673
+ /**
674
+ * Write a packet to the output synchronously.
675
+ * Synchronous version of writePacket.
676
+ *
677
+ * Writes muxed packet to the specified stream.
678
+ * Automatically handles:
679
+ * - Stream initialization on first packet (lazy initialization)
680
+ * - Codec parameter configuration from encoder or input stream
681
+ * - Header writing on first packet
682
+ * - Timestamp rescaling between source and output timebases
683
+ * - Sync queue for proper interleaving
684
+ *
685
+ * For encoder sources, the encoder must have processed at least one frame
686
+ * before packets can be written (encoder must be initialized).
687
+ *
688
+ * Uses FFmpeg CLI's sync queue pattern: buffers packets per stream and writes
689
+ * them in DTS order using av_compare_ts for timebase-aware comparison.
690
+ *
691
+ * To signal EOF for a stream, pass null as the packet.
692
+ * This tells the muxer that no more packets will be sent for this stream.
693
+ * The trailer is written only when close() is called.
694
+ *
695
+ * Direct mapping to avformat_write_header() (on first packet) and av_interleaved_write_frame().
696
+ *
697
+ * @param packet - Packet to write (or null/undefined to signal EOF)
698
+ *
699
+ * @param streamIndex - Target stream index
700
+ *
701
+ * @throws {Error} If stream invalid or encoder not initialized
702
+ *
703
+ * @throws {FFmpegError} If write fails
704
+ *
705
+ * @example
706
+ * ```typescript
707
+ * // Write encoded packet - header written automatically on first packet
708
+ * const packet = encoder.encodeSync(frame);
709
+ * if (packet) {
710
+ * output.writePacketSync(packet, videoIdx);
711
+ * packet.free();
712
+ * }
713
+ * ```
714
+ *
715
+ * @example
716
+ * ```typescript
717
+ * // Stream copy with packet processing
718
+ * for (const packet of input.packetsSync()) {
719
+ * if (packet.streamIndex === inputVideoIdx) {
720
+ * output.writePacketSync(packet, outputVideoIdx);
721
+ * }
722
+ * packet.free();
723
+ * }
724
+ * ```
725
+ *
726
+ * @see {@link writePacket} For async version
727
+ */
728
+ writePacketSync(packet: Packet | null | undefined, streamIndex: number): void;
729
+ /**
730
+ * Close muxer and free resources.
731
+ *
732
+ * Automatically writes trailer if header was written.
733
+ * Closes the output file and releases all resources.
734
+ * Safe to call multiple times.
735
+ * Automatically called by Symbol.asyncDispose.
736
+ *
737
+ * @example
738
+ * ```typescript
739
+ * const output = await Muxer.open('output.mp4');
740
+ * try {
741
+ * // Use output - trailer written automatically on close
742
+ * } finally {
743
+ * await output.close();
744
+ * }
745
+ * ```
746
+ *
747
+ * @see {@link Symbol.asyncDispose} For automatic cleanup
748
+ */
749
+ close(): Promise<void>;
750
+ /**
751
+ * Close muxer and free resources synchronously.
752
+ * Synchronous version of close.
753
+ *
754
+ * Automatically writes trailer if header was written.
755
+ * Closes the output file and releases all resources.
756
+ * Safe to call multiple times.
757
+ * Automatically called by Symbol.dispose.
758
+ *
759
+ * @example
760
+ * ```typescript
761
+ * const output = Muxer.openSync('output.mp4');
762
+ * try {
763
+ * // Use output - trailer written automatically on close
764
+ * } finally {
765
+ * output.closeSync();
766
+ * }
767
+ * ```
768
+ *
769
+ * @see {@link close} For async version
770
+ */
771
+ closeSync(): void;
772
+ /**
773
+ * Get underlying format context.
774
+ *
775
+ * Returns the internal format context for advanced operations.
776
+ *
777
+ * @returns Format context
778
+ *
779
+ * @internal
780
+ */
781
+ getFormatContext(): FormatContext;
782
+ /**
783
+ * Setup sync queues based on stream configuration.
784
+ *
785
+ * Called before writing header.
786
+ * Muxing sync queue is created only if nb_interleaved > nb_av_enc
787
+ * (i.e., when there are streamcopy streams).
788
+ *
789
+ * All streams are added as non-limiting (FFmpeg default without -shortest),
790
+ * which means no timestamp-based synchronization - frames are output immediately.
791
+ *
792
+ * @internal
793
+ */
794
+ private setupSyncQueues;
795
+ /**
796
+ * Flush all PreMuxQueues in DTS-sorted order.
797
+ *
798
+ * Implements FFmpeg's PreMuxQueue flush algorithm from mux_task_start().
799
+ * Repeatedly finds the stream with the earliest DTS packet and sends it:
800
+ * - WITH SyncQueue: Sends to SyncQueue for interleaving
801
+ * - WITHOUT SyncQueue: Writes directly to muxer
802
+ * NULL packets (EOF markers) and packets with AV_NOPTS_VALUE have priority (sent first).
803
+ *
804
+ * @internal
805
+ */
806
+ private flushPreMuxQueues;
807
+ /**
808
+ * Flush all PreMuxQueues in DTS-sorted order (synchronous version).
809
+ *
810
+ * Implements FFmpeg's PreMuxQueue flush algorithm from mux_task_start().
811
+ * Repeatedly finds the stream with the earliest DTS packet and sends it:
812
+ * - WITH SyncQueue: Sends to SyncQueue for interleaving
813
+ * - WITHOUT SyncQueue: Writes directly to muxer
814
+ * NULL packets (EOF markers) and packets with AV_NOPTS_VALUE have priority (sent first).
815
+ *
816
+ * @internal
817
+ */
818
+ private flushPreMuxQueuesSync;
819
+ /**
820
+ * Write a packet to the output.
821
+ *
822
+ * @param pkt - Packet to write
823
+ *
824
+ * @param streamInfo - Stream description
825
+ *
826
+ * @param streamIndex - Stream index
827
+ *
828
+ * @internal
829
+ */
830
+ private write;
831
+ /**
832
+ * Internal write implementation.
833
+ * Called either directly or through the write worker.
834
+ *
835
+ * @param pkt - Packet to write
836
+ *
837
+ * @param streamInfo - Stream description
838
+ *
839
+ * @param streamIndex - Stream index
840
+ *
841
+ * @internal
842
+ */
843
+ private writeInternal;
844
+ /**
845
+ * Start background worker for async write queue.
846
+ * Processes write jobs sequentially to prevent race conditions.
847
+ *
848
+ * @internal
849
+ */
850
+ private startWriteWorker;
851
+ /**
852
+ * Write a packet to the output synchronously.
853
+ * Synchronous version of write.
854
+ *
855
+ * @param pkt - Packet to write
856
+ *
857
+ * @param streamInfo - Stream description
858
+ *
859
+ * @param streamIndex - Stream index
860
+ *
861
+ * @internal
862
+ */
863
+ private writeSync;
864
+ /**
865
+ * Streamcopy packet filtering and timestamp offset.
866
+ *
867
+ * Applies streamcopy-specific logic before muxing:
868
+ * 1. Recording time limit check
869
+ * 2. Skip non-keyframe packets at start (unless copyInitialNonkeyframes)
870
+ * 3. Skip packets before ts_copy_start (unless copyPriorStart)
871
+ * 4. Skip packets before startTime
872
+ * 5. Apply start_time timestamp offset
873
+ *
874
+ * @param pkt - Packet to process
875
+ *
876
+ * @param streamInfo - Stream description
877
+ *
878
+ * @param streamIndex - Stream index
879
+ *
880
+ * @returns true if packet should be written, false if packet should be skipped
881
+ *
882
+ * @throws {Error} If recording time limit reached
883
+ *
884
+ * @internal
885
+ */
886
+ private ofStreamcopy;
887
+ /**
888
+ * Fix packet timestamps before muxing.
889
+ *
890
+ * Performs timestamp corrections:
891
+ * 1. Rescales timestamps to output timebase (av_rescale_delta for audio streamcopy)
892
+ * 2. Sets pkt.timeBase to output stream timebase
893
+ * 3. Fixes invalid DTS > PTS relationships
894
+ * 4. Enforces monotonic DTS (never decreasing)
895
+ *
896
+ * @param pkt - Packet to fix
897
+ *
898
+ * @param streamInfo - Stream description
899
+ *
900
+ * @param streamIndex - Stream index
901
+ *
902
+ * @internal
903
+ */
904
+ private muxFixupTs;
905
+ /**
906
+ * Copy container metadata from input to output.
907
+ *
908
+ * Automatically copies global metadata from input Demuxer to output format context.
909
+ * Only copies once (on first call). Removes duration/creation_time metadata.
910
+ *
911
+ * @internal
912
+ */
913
+ private copyContainerMetadata;
914
+ /**
915
+ * Auto-set DEFAULT disposition for first stream of each type.
916
+ *
917
+ * FFmpeg automatically sets DEFAULT flag for the first stream of each type
918
+ * if no stream of that type has DEFAULT set yet.
919
+ *
920
+ * @internal
921
+ */
922
+ private updateDefaultDisposition;
923
+ /**
924
+ * Dispose of muxer.
925
+ *
926
+ * Implements AsyncDisposable interface for automatic cleanup.
927
+ * Equivalent to calling close().
928
+ *
929
+ * @example
930
+ * ```typescript
931
+ * {
932
+ * await using output = await Muxer.open('output.mp4');
933
+ * // Use output...
934
+ * } // Automatically closed
935
+ * ```
936
+ *
937
+ * @see {@link close} For manual cleanup
938
+ */
939
+ [Symbol.asyncDispose](): Promise<void>;
940
+ /**
941
+ * Dispose of muxer synchronously.
942
+ *
943
+ * Implements Disposable interface for automatic cleanup.
944
+ * Equivalent to calling closeSync().
945
+ *
946
+ * @example
947
+ * ```typescript
948
+ * {
949
+ * using output = Muxer.openSync('output.mp4');
950
+ * // Use output...
951
+ * } // Automatically closed
952
+ * ```
953
+ *
954
+ * @see {@link closeSync} For manual cleanup
955
+ */
956
+ [Symbol.dispose](): void;
957
+ }