node-av 0.0.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 (175) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE.md +22 -0
  3. package/README.md +377 -0
  4. package/binding.gyp +78 -0
  5. package/dist/api/bitstream-filter.d.ts +246 -0
  6. package/dist/api/bitstream-filter.js +369 -0
  7. package/dist/api/bitstream-filter.js.map +1 -0
  8. package/dist/api/decoder.d.ts +257 -0
  9. package/dist/api/decoder.js +424 -0
  10. package/dist/api/decoder.js.map +1 -0
  11. package/dist/api/encoder.d.ts +298 -0
  12. package/dist/api/encoder.js +574 -0
  13. package/dist/api/encoder.js.map +1 -0
  14. package/dist/api/filter.d.ts +457 -0
  15. package/dist/api/filter.js +876 -0
  16. package/dist/api/filter.js.map +1 -0
  17. package/dist/api/hardware.d.ts +318 -0
  18. package/dist/api/hardware.js +558 -0
  19. package/dist/api/hardware.js.map +1 -0
  20. package/dist/api/index.d.ts +12 -0
  21. package/dist/api/index.js +20 -0
  22. package/dist/api/index.js.map +1 -0
  23. package/dist/api/io-stream.d.ts +109 -0
  24. package/dist/api/io-stream.js +124 -0
  25. package/dist/api/io-stream.js.map +1 -0
  26. package/dist/api/media-input.d.ts +295 -0
  27. package/dist/api/media-input.js +456 -0
  28. package/dist/api/media-input.js.map +1 -0
  29. package/dist/api/media-output.d.ts +274 -0
  30. package/dist/api/media-output.js +486 -0
  31. package/dist/api/media-output.js.map +1 -0
  32. package/dist/api/pipeline.d.ts +117 -0
  33. package/dist/api/pipeline.js +836 -0
  34. package/dist/api/pipeline.js.map +1 -0
  35. package/dist/api/types.d.ts +440 -0
  36. package/dist/api/types.js +2 -0
  37. package/dist/api/types.js.map +1 -0
  38. package/dist/api/utilities/audio-sample.d.ts +115 -0
  39. package/dist/api/utilities/audio-sample.js +110 -0
  40. package/dist/api/utilities/audio-sample.js.map +1 -0
  41. package/dist/api/utilities/channel-layout.d.ts +83 -0
  42. package/dist/api/utilities/channel-layout.js +87 -0
  43. package/dist/api/utilities/channel-layout.js.map +1 -0
  44. package/dist/api/utilities/image.d.ts +177 -0
  45. package/dist/api/utilities/image.js +183 -0
  46. package/dist/api/utilities/image.js.map +1 -0
  47. package/dist/api/utilities/index.d.ts +8 -0
  48. package/dist/api/utilities/index.js +17 -0
  49. package/dist/api/utilities/index.js.map +1 -0
  50. package/dist/api/utilities/media-type.d.ts +56 -0
  51. package/dist/api/utilities/media-type.js +60 -0
  52. package/dist/api/utilities/media-type.js.map +1 -0
  53. package/dist/api/utilities/pixel-format.d.ts +94 -0
  54. package/dist/api/utilities/pixel-format.js +102 -0
  55. package/dist/api/utilities/pixel-format.js.map +1 -0
  56. package/dist/api/utilities/sample-format.d.ts +132 -0
  57. package/dist/api/utilities/sample-format.js +144 -0
  58. package/dist/api/utilities/sample-format.js.map +1 -0
  59. package/dist/api/utilities/streaming.d.ts +104 -0
  60. package/dist/api/utilities/streaming.js +137 -0
  61. package/dist/api/utilities/streaming.js.map +1 -0
  62. package/dist/api/utilities/timestamp.d.ts +187 -0
  63. package/dist/api/utilities/timestamp.js +200 -0
  64. package/dist/api/utilities/timestamp.js.map +1 -0
  65. package/dist/api/utils.d.ts +61 -0
  66. package/dist/api/utils.js +330 -0
  67. package/dist/api/utils.js.map +1 -0
  68. package/dist/index.d.ts +2 -0
  69. package/dist/index.js +5 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/lib/audio-fifo.d.ts +339 -0
  72. package/dist/lib/audio-fifo.js +365 -0
  73. package/dist/lib/audio-fifo.js.map +1 -0
  74. package/dist/lib/binding.d.ts +192 -0
  75. package/dist/lib/binding.js +70 -0
  76. package/dist/lib/binding.js.map +1 -0
  77. package/dist/lib/bitstream-filter-context.d.ts +345 -0
  78. package/dist/lib/bitstream-filter-context.js +407 -0
  79. package/dist/lib/bitstream-filter-context.js.map +1 -0
  80. package/dist/lib/bitstream-filter.d.ts +124 -0
  81. package/dist/lib/bitstream-filter.js +138 -0
  82. package/dist/lib/bitstream-filter.js.map +1 -0
  83. package/dist/lib/channel-layouts.d.ts +51 -0
  84. package/dist/lib/channel-layouts.js +55 -0
  85. package/dist/lib/channel-layouts.js.map +1 -0
  86. package/dist/lib/codec-context.d.ts +763 -0
  87. package/dist/lib/codec-context.js +974 -0
  88. package/dist/lib/codec-context.js.map +1 -0
  89. package/dist/lib/codec-parameters.d.ts +362 -0
  90. package/dist/lib/codec-parameters.js +460 -0
  91. package/dist/lib/codec-parameters.js.map +1 -0
  92. package/dist/lib/codec-parser.d.ts +185 -0
  93. package/dist/lib/codec-parser.js +193 -0
  94. package/dist/lib/codec-parser.js.map +1 -0
  95. package/dist/lib/codec.d.ts +432 -0
  96. package/dist/lib/codec.js +492 -0
  97. package/dist/lib/codec.js.map +1 -0
  98. package/dist/lib/constants.d.ts +2037 -0
  99. package/dist/lib/constants.js +1659 -0
  100. package/dist/lib/constants.js.map +1 -0
  101. package/dist/lib/dictionary.d.ts +371 -0
  102. package/dist/lib/dictionary.js +406 -0
  103. package/dist/lib/dictionary.js.map +1 -0
  104. package/dist/lib/error.d.ts +216 -0
  105. package/dist/lib/error.js +254 -0
  106. package/dist/lib/error.js.map +1 -0
  107. package/dist/lib/filter-context.d.ts +445 -0
  108. package/dist/lib/filter-context.js +505 -0
  109. package/dist/lib/filter-context.js.map +1 -0
  110. package/dist/lib/filter-graph.d.ts +556 -0
  111. package/dist/lib/filter-graph.js +608 -0
  112. package/dist/lib/filter-graph.js.map +1 -0
  113. package/dist/lib/filter-inout.d.ts +205 -0
  114. package/dist/lib/filter-inout.js +264 -0
  115. package/dist/lib/filter-inout.js.map +1 -0
  116. package/dist/lib/filter.d.ts +231 -0
  117. package/dist/lib/filter.js +260 -0
  118. package/dist/lib/filter.js.map +1 -0
  119. package/dist/lib/format-context.d.ts +798 -0
  120. package/dist/lib/format-context.js +845 -0
  121. package/dist/lib/format-context.js.map +1 -0
  122. package/dist/lib/frame.d.ts +784 -0
  123. package/dist/lib/frame.js +933 -0
  124. package/dist/lib/frame.js.map +1 -0
  125. package/dist/lib/hardware-device-context.d.ts +407 -0
  126. package/dist/lib/hardware-device-context.js +429 -0
  127. package/dist/lib/hardware-device-context.js.map +1 -0
  128. package/dist/lib/hardware-frames-context.d.ts +374 -0
  129. package/dist/lib/hardware-frames-context.js +430 -0
  130. package/dist/lib/hardware-frames-context.js.map +1 -0
  131. package/dist/lib/index.d.ts +31 -0
  132. package/dist/lib/index.js +54 -0
  133. package/dist/lib/index.js.map +1 -0
  134. package/dist/lib/input-format.d.ts +216 -0
  135. package/dist/lib/input-format.js +246 -0
  136. package/dist/lib/input-format.js.map +1 -0
  137. package/dist/lib/io-context.d.ts +495 -0
  138. package/dist/lib/io-context.js +550 -0
  139. package/dist/lib/io-context.js.map +1 -0
  140. package/dist/lib/log.d.ts +201 -0
  141. package/dist/lib/log.js +219 -0
  142. package/dist/lib/log.js.map +1 -0
  143. package/dist/lib/native-types.d.ts +719 -0
  144. package/dist/lib/native-types.js +2 -0
  145. package/dist/lib/native-types.js.map +1 -0
  146. package/dist/lib/option.d.ts +589 -0
  147. package/dist/lib/option.js +853 -0
  148. package/dist/lib/option.js.map +1 -0
  149. package/dist/lib/output-format.d.ts +179 -0
  150. package/dist/lib/output-format.js +205 -0
  151. package/dist/lib/output-format.js.map +1 -0
  152. package/dist/lib/packet.d.ts +487 -0
  153. package/dist/lib/packet.js +558 -0
  154. package/dist/lib/packet.js.map +1 -0
  155. package/dist/lib/rational.d.ts +210 -0
  156. package/dist/lib/rational.js +233 -0
  157. package/dist/lib/rational.js.map +1 -0
  158. package/dist/lib/software-resample-context.d.ts +572 -0
  159. package/dist/lib/software-resample-context.js +610 -0
  160. package/dist/lib/software-resample-context.js.map +1 -0
  161. package/dist/lib/software-scale-context.d.ts +290 -0
  162. package/dist/lib/software-scale-context.js +308 -0
  163. package/dist/lib/software-scale-context.js.map +1 -0
  164. package/dist/lib/stream.d.ts +322 -0
  165. package/dist/lib/stream.js +408 -0
  166. package/dist/lib/stream.js.map +1 -0
  167. package/dist/lib/types.d.ts +59 -0
  168. package/dist/lib/types.js +8 -0
  169. package/dist/lib/types.js.map +1 -0
  170. package/dist/lib/utilities.d.ts +346 -0
  171. package/dist/lib/utilities.js +424 -0
  172. package/dist/lib/utilities.js.map +1 -0
  173. package/install/check.js +113 -0
  174. package/install/ffmpeg.js +163 -0
  175. package/package.json +107 -0
@@ -0,0 +1,456 @@
1
+ /**
2
+ * MediaInput - Unified Input Handler for FFmpeg
3
+ *
4
+ * Provides a high-level interface for opening and reading media from various sources.
5
+ * Supports files, URLs, and Buffers with automatic format detection.
6
+ *
7
+ * Central entry point for all media input operations.
8
+ * Manages FormatContext lifecycle and provides stream information.
9
+ *
10
+ * @module api/media-input
11
+ */
12
+ import { open } from 'fs/promises';
13
+ import { AVFLAG_NONE, avGetPixFmtName, avGetSampleFmtName, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_VIDEO, Dictionary, FFmpegError, FormatContext, InputFormat, Packet, Rational, } from '../lib/index.js';
14
+ import { IOStream } from './io-stream.js';
15
+ /**
16
+ * MediaInput - High-level media input handler.
17
+ *
18
+ * Opens and provides access to media streams from various sources.
19
+ * Automatically detects format and finds stream information.
20
+ *
21
+ * Manages the FormatContext and provides convenient methods for
22
+ * accessing streams, metadata, and packets.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { MediaInput } from 'node-av/api';
27
+ *
28
+ * // Open from file
29
+ * const media = await MediaInput.open('video.mp4');
30
+ * console.log(`Found ${media.streams.length} streams`);
31
+ * console.log(`Duration: ${media.duration} seconds`);
32
+ *
33
+ * // Open from buffer
34
+ * const buffer = await fs.readFile('video.mp4');
35
+ * const media = await MediaInput.open(buffer);
36
+ *
37
+ * // Iterate packets
38
+ * for await (const packet of media.packets()) {
39
+ * console.log(`Packet from stream ${packet.streamIndex}`);
40
+ * }
41
+ * ```
42
+ */
43
+ export class MediaInput {
44
+ formatContext;
45
+ _streams = [];
46
+ ioContext; // Store IOContext for cleanup
47
+ /**
48
+ * Create a new MediaInput instance.
49
+ *
50
+ * Private constructor - use MediaInput.open() to create instances.
51
+ *
52
+ * Parses stream information immediately after construction.
53
+ *
54
+ * @param formatContext - Opened FormatContext
55
+ */
56
+ constructor(formatContext) {
57
+ this.formatContext = formatContext;
58
+ // Streams will be set after findStreamInfo in the static factory
59
+ }
60
+ /**
61
+ * Probe the format of media without fully opening it.
62
+ *
63
+ * Detects the container format and basic information without
64
+ * parsing all stream information. Useful for quick format validation.
65
+ *
66
+ * @param input - File path or Buffer to probe
67
+ *
68
+ * @returns Format information or null if unrecognized
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * // Probe a file
73
+ * const info = await MediaInput.probeFormat('video.mp4');
74
+ * if (info) {
75
+ * console.log(`Format: ${info.format}`);
76
+ * console.log(`Confidence: ${info.confidence}%`);
77
+ * }
78
+ *
79
+ * // Probe a buffer
80
+ * const buffer = await fs.readFile('video.mp4');
81
+ * const info = await MediaInput.probeFormat(buffer);
82
+ * ```
83
+ */
84
+ static async probeFormat(input) {
85
+ try {
86
+ if (Buffer.isBuffer(input)) {
87
+ // Probe from buffer
88
+ const format = InputFormat.probe(input);
89
+ if (!format) {
90
+ return null;
91
+ }
92
+ return {
93
+ format: format.name ?? 'unknown',
94
+ longName: format.longName ?? undefined,
95
+ extensions: format.extensions ?? undefined,
96
+ mimeType: format.mimeType ?? undefined,
97
+ confidence: 100, // Direct probe always has high confidence
98
+ };
99
+ }
100
+ else {
101
+ // For files, read first part and probe
102
+ let fileHandle;
103
+ try {
104
+ fileHandle = await open(input, 'r');
105
+ // Read first 64KB for probing
106
+ const buffer = Buffer.alloc(65536);
107
+ const { bytesRead } = await fileHandle.read(buffer, 0, 65536, 0);
108
+ const probeBuffer = buffer.subarray(0, bytesRead);
109
+ const format = InputFormat.probe(probeBuffer, input);
110
+ if (!format) {
111
+ return null;
112
+ }
113
+ return {
114
+ format: format.name ?? 'unknown',
115
+ longName: format.longName ?? undefined,
116
+ extensions: format.extensions ?? undefined,
117
+ mimeType: format.mimeType ?? undefined,
118
+ confidence: 90, // File-based probe with filename hint
119
+ };
120
+ }
121
+ catch {
122
+ // If file reading fails, return null
123
+ return null;
124
+ }
125
+ finally {
126
+ await fileHandle?.close();
127
+ }
128
+ }
129
+ }
130
+ catch {
131
+ return null;
132
+ }
133
+ }
134
+ static async open(input, options = {}) {
135
+ // Check if input is raw data
136
+ if (typeof input === 'object' && 'type' in input && ('width' in input || 'sampleRate' in input)) {
137
+ // Build options for raw data
138
+ const rawOptions = {
139
+ bufferSize: options.bufferSize,
140
+ format: options.format ?? (input.type === 'video' ? 'rawvideo' : 's16le'),
141
+ options: {
142
+ ...options.options,
143
+ },
144
+ };
145
+ if (input.type === 'video') {
146
+ rawOptions.options = {
147
+ ...rawOptions.options,
148
+ video_size: `${input.width}x${input.height}`,
149
+ pixel_format: avGetPixFmtName(input.pixelFormat) ?? 'yuv420p',
150
+ framerate: new Rational(input.frameRate.num, input.frameRate.den).toString(),
151
+ };
152
+ }
153
+ else {
154
+ rawOptions.options = {
155
+ ...rawOptions.options,
156
+ sample_rate: input.sampleRate,
157
+ channels: input.channels,
158
+ sample_fmt: avGetSampleFmtName(input.sampleFormat) ?? 's16le',
159
+ };
160
+ }
161
+ // Open with the raw data source
162
+ return MediaInput.open(input.input, rawOptions);
163
+ }
164
+ // Original implementation for non-raw data
165
+ const formatContext = new FormatContext();
166
+ let ioContext;
167
+ let optionsDict = null;
168
+ let inputFormat = null;
169
+ try {
170
+ // Create options dictionary if options are provided
171
+ if (options.options && Object.keys(options.options).length > 0) {
172
+ // Convert all values to strings for FFmpeg
173
+ const stringOptions = {};
174
+ for (const [key, value] of Object.entries(options.options)) {
175
+ stringOptions[key] = String(value);
176
+ }
177
+ optionsDict = Dictionary.fromObject(stringOptions);
178
+ }
179
+ // Find input format if specified
180
+ if (options.format) {
181
+ inputFormat = InputFormat.findInputFormat(options.format);
182
+ if (!inputFormat) {
183
+ throw new Error(`Input format '${options.format}' not found`);
184
+ }
185
+ }
186
+ if (typeof input === 'string') {
187
+ // File path or URL
188
+ const ret = await formatContext.openInput(input, inputFormat, optionsDict);
189
+ FFmpegError.throwIfError(ret, 'Failed to open input');
190
+ }
191
+ else if (Buffer.isBuffer(input)) {
192
+ // Validate buffer is not empty
193
+ if (input.length === 0) {
194
+ throw new Error('Cannot open media from empty buffer');
195
+ }
196
+ // From buffer - allocate context first for custom I/O
197
+ formatContext.allocContext();
198
+ ioContext = IOStream.create(input, { bufferSize: options.bufferSize });
199
+ formatContext.pb = ioContext;
200
+ const ret = await formatContext.openInput('', inputFormat, optionsDict);
201
+ FFmpegError.throwIfError(ret, 'Failed to open input from buffer');
202
+ }
203
+ else {
204
+ throw new TypeError('Invalid input type. Expected file path, URL, or Buffer');
205
+ }
206
+ // Find stream information
207
+ const ret = await formatContext.findStreamInfo(null);
208
+ FFmpegError.throwIfError(ret, 'Failed to find stream info');
209
+ const mediaInput = new MediaInput(formatContext);
210
+ mediaInput.ioContext = ioContext;
211
+ // After successful creation, streams should be available
212
+ mediaInput._streams = formatContext.streams ?? [];
213
+ return mediaInput;
214
+ }
215
+ catch (error) {
216
+ // Clean up only on error
217
+ if (ioContext) {
218
+ // Clear the pb reference first
219
+ formatContext.pb = null;
220
+ // Free the IOContext
221
+ ioContext.freeContext();
222
+ }
223
+ // Clean up FormatContext
224
+ await formatContext.closeInput();
225
+ throw error;
226
+ }
227
+ finally {
228
+ // Clean up options dictionary
229
+ if (optionsDict) {
230
+ optionsDict.free();
231
+ }
232
+ }
233
+ }
234
+ /**
235
+ * Get all streams in the container.
236
+ *
237
+ * @returns Array of stream information
238
+ */
239
+ get streams() {
240
+ return this._streams;
241
+ }
242
+ /**
243
+ * Get media duration in seconds.
244
+ *
245
+ * Returns 0 if duration is not available.
246
+ *
247
+ * @returns Duration in seconds
248
+ */
249
+ get duration() {
250
+ const duration = this.formatContext.duration;
251
+ if (!duration || duration <= 0)
252
+ return 0;
253
+ // Convert from AV_TIME_BASE (microseconds) to seconds
254
+ return Number(duration) / 1000000;
255
+ }
256
+ /**
257
+ * Get container metadata.
258
+ *
259
+ * @returns Metadata key-value pairs
260
+ */
261
+ get metadata() {
262
+ return this.formatContext.metadata?.getAll() ?? {};
263
+ }
264
+ /**
265
+ * Get container format name.
266
+ *
267
+ * @returns Format name (e.g., 'mov,mp4,m4a,3gp,3g2,mj2')
268
+ */
269
+ get formatName() {
270
+ return this.formatContext.iformat?.name ?? 'unknown';
271
+ }
272
+ /**
273
+ * Get container format long name.
274
+ *
275
+ * @returns Format long name (e.g., 'QuickTime / MOV')
276
+ */
277
+ get formatLongName() {
278
+ return this.formatContext.iformat?.longName ?? 'Unknown Format';
279
+ }
280
+ /**
281
+ * Get the first video stream.
282
+ *
283
+ * @param index - Video stream index (0 for first, 1 for second, etc.)
284
+ *
285
+ * @returns Stream info or undefined if not found
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * const videoStream = media.video();
290
+ * if (videoStream) {
291
+ * console.log(`Video: ${videoStream.width}x${videoStream.height}`);
292
+ * }
293
+ * ```
294
+ */
295
+ video(index = 0) {
296
+ const streams = this._streams.filter((s) => s.codecpar.codecType === AVMEDIA_TYPE_VIDEO);
297
+ return streams[index];
298
+ }
299
+ /**
300
+ * Get the first audio stream.
301
+ *
302
+ * @param index - Audio stream index (0 for first, 1 for second, etc.)
303
+ *
304
+ * @returns Stream info or undefined if not found
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * const audioStream = media.audio();
309
+ * if (audioStream) {
310
+ * console.log(`Audio: ${audioStream.sampleRate}Hz, ${audioStream.channels}ch`);
311
+ * }
312
+ * ```
313
+ */
314
+ audio(index = 0) {
315
+ const streams = this._streams.filter((s) => s.codecpar.codecType === AVMEDIA_TYPE_AUDIO);
316
+ return streams[index];
317
+ }
318
+ /**
319
+ * Find the best stream of a given type.
320
+ *
321
+ * Uses FFmpeg's stream selection logic to find the most suitable stream.
322
+ *
323
+ * Uses av_find_best_stream() internally for optimal stream selection.
324
+ *
325
+ * @param type - Media type to search for
326
+ *
327
+ * @returns Stream info or undefined if not found
328
+ */
329
+ findBestStream(type) {
330
+ const bestStreamIndex = this.formatContext.findBestStream(type);
331
+ return this._streams.find((s) => s.index === bestStreamIndex);
332
+ }
333
+ /**
334
+ * Iterate over all packets in the container.
335
+ *
336
+ * Allocates a single packet and reuses it for efficiency.
337
+ * Automatically unreferences the packet between iterations.
338
+ *
339
+ * Uses av_read_frame() internally.
340
+ *
341
+ * @yields Packet from the container
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * for await (const packet of media.packets()) {
346
+ * if (packet.streamIndex === videoStream.index) {
347
+ * // Process video packet
348
+ * await decoder.decode(packet);
349
+ * }
350
+ * }
351
+ * ```
352
+ */
353
+ async *packets(index) {
354
+ const packet = new Packet();
355
+ packet.alloc();
356
+ try {
357
+ while (true) {
358
+ const ret = await this.formatContext.readFrame(packet);
359
+ if (ret < 0) {
360
+ // End of file or error
361
+ break;
362
+ }
363
+ if (index === undefined || packet.streamIndex === index) {
364
+ // Clone the packet for the user
365
+ // This creates a new Packet object that shares the same data buffer
366
+ // through reference counting. The data won't be freed until both
367
+ // the original and the clone are unreferenced.
368
+ const cloned = packet.clone();
369
+ if (!cloned) {
370
+ throw new Error('Failed to clone packet (out of memory)');
371
+ }
372
+ yield cloned;
373
+ }
374
+ // Unreference the original packet's data buffer
375
+ // This allows us to reuse the packet object for the next readFrame()
376
+ // The data itself is still alive because the clone has a reference
377
+ packet.unref();
378
+ }
379
+ }
380
+ finally {
381
+ packet.free();
382
+ }
383
+ }
384
+ /**
385
+ * Seek to a specific timestamp.
386
+ *
387
+ * Uses av_seek_frame() internally.
388
+ *
389
+ * Converts seconds to microseconds for FFmpeg's AV_TIME_BASE.
390
+ *
391
+ * @param timestamp - Target timestamp in seconds
392
+ * @param streamIndex - Stream to seek in (-1 for default)
393
+ * @param flags - Seek flags (0 for default)
394
+ *
395
+ * @returns 0 on success, negative error code on failure
396
+ */
397
+ async seek(timestamp, streamIndex = -1, flags = AVFLAG_NONE) {
398
+ // Convert seconds to AV_TIME_BASE
399
+ const ts = BigInt(Math.floor(timestamp * 1000000));
400
+ return this.formatContext.seekFrame(streamIndex, ts, flags);
401
+ }
402
+ /**
403
+ * Close the input and free resources.
404
+ *
405
+ * Uses avformat_close_input() internally.
406
+ *
407
+ * Properly cleans up IOContext references before closing to prevent
408
+ * use-after-free errors.
409
+ */
410
+ async close() {
411
+ // IMPORTANT: Clear pb reference FIRST to prevent use-after-free
412
+ if (this.ioContext) {
413
+ this.formatContext.pb = null;
414
+ }
415
+ // Close FormatContext
416
+ await this.formatContext.closeInput();
417
+ // NOW we can safely free the IOContext
418
+ if (this.ioContext) {
419
+ this.ioContext.freeContext();
420
+ this.ioContext = undefined;
421
+ }
422
+ }
423
+ /**
424
+ * Get the low-level FormatContext.
425
+ *
426
+ * Internal method for advanced use cases.
427
+ *
428
+ * Provides direct access to the underlying AVFormatContext.
429
+ *
430
+ * @returns FFmpeg FormatContext
431
+ *
432
+ * @internal
433
+ */
434
+ getFormatContext() {
435
+ return this.formatContext;
436
+ }
437
+ /**
438
+ * Async cleanup when using 'await using' statement.
439
+ *
440
+ * Implements the AsyncDisposable interface for automatic cleanup.
441
+ *
442
+ * Calls close() to free all resources.
443
+ *
444
+ * @example
445
+ * ```typescript
446
+ * {
447
+ * await using media = await MediaInput.open('video.mp4');
448
+ * // Use media...
449
+ * } // Automatically closed
450
+ * ```
451
+ */
452
+ async [Symbol.asyncDispose]() {
453
+ await this.close();
454
+ }
455
+ }
456
+ //# sourceMappingURL=media-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-input.js","sourceRoot":"","sources":["../../src/api/media-input.ts"],"names":[],"mappings":"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"}