node-av 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +0 -21
  2. package/dist/api/bitstream-filter.d.ts +3 -0
  3. package/dist/api/bitstream-filter.js +5 -2
  4. package/dist/api/bitstream-filter.js.map +1 -1
  5. package/dist/api/decoder.d.ts +5 -0
  6. package/dist/api/decoder.js +7 -2
  7. package/dist/api/decoder.js.map +1 -1
  8. package/dist/api/encoder.d.ts +11 -6
  9. package/dist/api/encoder.js +13 -8
  10. package/dist/api/encoder.js.map +1 -1
  11. package/dist/api/filter-presets.d.ts +1267 -15
  12. package/dist/api/filter-presets.js +1387 -17
  13. package/dist/api/filter-presets.js.map +1 -1
  14. package/dist/api/filter.d.ts +28 -0
  15. package/dist/api/filter.js +30 -2
  16. package/dist/api/filter.js.map +1 -1
  17. package/dist/api/hardware.d.ts +24 -2
  18. package/dist/api/hardware.js +65 -8
  19. package/dist/api/hardware.js.map +1 -1
  20. package/dist/api/io-stream.d.ts +6 -0
  21. package/dist/api/io-stream.js +6 -0
  22. package/dist/api/io-stream.js.map +1 -1
  23. package/dist/api/media-input.d.ts +1 -0
  24. package/dist/api/media-input.js.map +1 -1
  25. package/dist/api/media-output.d.ts +4 -0
  26. package/dist/api/media-output.js +4 -0
  27. package/dist/api/media-output.js.map +1 -1
  28. package/dist/api/pipeline.d.ts +193 -0
  29. package/dist/api/pipeline.js +17 -0
  30. package/dist/api/pipeline.js.map +1 -1
  31. package/dist/api/types.d.ts +5 -0
  32. package/dist/api/utilities/audio-sample.d.ts +0 -8
  33. package/dist/api/utilities/audio-sample.js +0 -8
  34. package/dist/api/utilities/audio-sample.js.map +1 -1
  35. package/dist/api/utilities/channel-layout.d.ts +0 -8
  36. package/dist/api/utilities/channel-layout.js +0 -8
  37. package/dist/api/utilities/channel-layout.js.map +1 -1
  38. package/dist/api/utilities/image.d.ts +0 -8
  39. package/dist/api/utilities/image.js +0 -8
  40. package/dist/api/utilities/image.js.map +1 -1
  41. package/dist/api/utilities/index.d.ts +3 -3
  42. package/dist/api/utilities/index.js +3 -3
  43. package/dist/api/utilities/index.js.map +1 -1
  44. package/dist/api/utilities/media-type.d.ts +1 -9
  45. package/dist/api/utilities/media-type.js +1 -9
  46. package/dist/api/utilities/media-type.js.map +1 -1
  47. package/dist/api/utilities/pixel-format.d.ts +1 -9
  48. package/dist/api/utilities/pixel-format.js +1 -9
  49. package/dist/api/utilities/pixel-format.js.map +1 -1
  50. package/dist/api/utilities/sample-format.d.ts +1 -9
  51. package/dist/api/utilities/sample-format.js +1 -9
  52. package/dist/api/utilities/sample-format.js.map +1 -1
  53. package/dist/api/utilities/streaming.d.ts +0 -8
  54. package/dist/api/utilities/streaming.js +0 -8
  55. package/dist/api/utilities/streaming.js.map +1 -1
  56. package/dist/api/utilities/timestamp.d.ts +0 -8
  57. package/dist/api/utilities/timestamp.js +0 -8
  58. package/dist/api/utilities/timestamp.js.map +1 -1
  59. package/dist/api/utils.js +2 -0
  60. package/dist/api/utils.js.map +1 -1
  61. package/dist/constants/constants.d.ts +1 -1
  62. package/dist/constants/constants.js +2 -0
  63. package/dist/constants/constants.js.map +1 -1
  64. package/dist/lib/binding.d.ts +1 -0
  65. package/dist/lib/binding.js +2 -0
  66. package/dist/lib/binding.js.map +1 -1
  67. package/dist/lib/codec.d.ts +4 -4
  68. package/dist/lib/codec.js +4 -4
  69. package/dist/lib/error.d.ts +1 -1
  70. package/dist/lib/error.js +1 -1
  71. package/dist/lib/index.d.ts +1 -1
  72. package/dist/lib/index.js +1 -1
  73. package/dist/lib/index.js.map +1 -1
  74. package/dist/lib/native-types.d.ts +1 -0
  75. package/dist/lib/option.d.ts +176 -0
  76. package/dist/lib/option.js +176 -0
  77. package/dist/lib/option.js.map +1 -1
  78. package/dist/lib/utilities.d.ts +64 -1
  79. package/dist/lib/utilities.js +65 -0
  80. package/dist/lib/utilities.js.map +1 -1
  81. package/install/ffmpeg.js +0 -11
  82. package/package.json +12 -14
  83. package/release_notes.md +24 -43
@@ -1,5 +1,6 @@
1
1
  import { AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_D3D11VA, AV_HWDEVICE_TYPE_D3D12VA, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_DXVA2, AV_HWDEVICE_TYPE_MEDIACODEC, AV_HWDEVICE_TYPE_OPENCL, AV_HWDEVICE_TYPE_QSV, AV_HWDEVICE_TYPE_RKMPP, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_VDPAU, AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_VULKAN, AVFILTER_FLAG_HWDEVICE, } from '../constants/constants.js';
2
2
  import { Filter } from '../lib/filter.js';
3
+ import { HardwareDeviceContext } from '../lib/hardware-device-context.js';
3
4
  import { avGetPixFmtName, avGetSampleFmtName } from '../lib/utilities.js';
4
5
  /**
5
6
  * Base class for filter preset implementations.
@@ -28,6 +29,12 @@ export class FilterPresetBase {
28
29
  * @param options - Additional scaling options (e.g., flags for algorithm)
29
30
  * @returns Filter string or null if not supported
30
31
  *
32
+ * @example
33
+ * ```typescript
34
+ * presets.scale(1920, 1080) // Scale to Full HD
35
+ * presets.scale(640, 480, { flags: 'lanczos' }) // With specific algorithm
36
+ * ```
37
+ *
31
38
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#scale | FFmpeg scale filter}
32
39
  */
33
40
  scale(width, height, options) {
@@ -44,6 +51,12 @@ export class FilterPresetBase {
44
51
  * @param y - Y coordinate of top-left corner (default: 0)
45
52
  * @returns Filter string or null if not supported
46
53
  *
54
+ * @example
55
+ * ```typescript
56
+ * presets.crop(640, 480, 100, 100) // Crop 640x480 area starting at (100,100)
57
+ * presets.crop(1280, 720) // Crop from top-left corner
58
+ * ```
59
+ *
47
60
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#crop | FFmpeg crop filter}
48
61
  */
49
62
  crop(width, height, x = 0, y = 0) {
@@ -55,6 +68,12 @@ export class FilterPresetBase {
55
68
  * @param fps - Target frames per second
56
69
  * @returns Filter string or null if not supported
57
70
  *
71
+ * @example
72
+ * ```typescript
73
+ * presets.fps(30) // Convert to 30 FPS
74
+ * presets.fps(23.976) // Film frame rate
75
+ * ```
76
+ *
58
77
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#fps | FFmpeg fps filter}
59
78
  */
60
79
  fps(fps) {
@@ -96,6 +115,12 @@ export class FilterPresetBase {
96
115
  * @param angle - Rotation angle in degrees
97
116
  * @returns Filter string or null if not supported
98
117
  *
118
+ * @example
119
+ * ```typescript
120
+ * presets.rotate(90) // Rotate 90 degrees clockwise
121
+ * presets.rotate(-45) // Rotate 45 degrees counter-clockwise
122
+ * ```
123
+ *
99
124
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#rotate | FFmpeg rotate filter}
100
125
  */
101
126
  rotate(angle) {
@@ -106,6 +131,11 @@ export class FilterPresetBase {
106
131
  *
107
132
  * @returns Filter string or null if not supported
108
133
  *
134
+ * @example
135
+ * ```typescript
136
+ * presets.hflip() // Mirror horizontally
137
+ * ```
138
+ *
109
139
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hflip | FFmpeg hflip filter}
110
140
  */
111
141
  hflip() {
@@ -116,6 +146,11 @@ export class FilterPresetBase {
116
146
  *
117
147
  * @returns Filter string or null if not supported
118
148
  *
149
+ * @example
150
+ * ```typescript
151
+ * presets.vflip() // Flip upside down
152
+ * ```
153
+ *
119
154
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#vflip | FFmpeg vflip filter}
120
155
  */
121
156
  vflip() {
@@ -129,6 +164,12 @@ export class FilterPresetBase {
129
164
  * @param duration - Fade duration in seconds
130
165
  * @returns Filter string or null if not supported
131
166
  *
167
+ * @example
168
+ * ```typescript
169
+ * presets.fade('in', 0, 2) // 2-second fade in from start
170
+ * presets.fade('out', 10, 1) // 1-second fade out at 10 seconds
171
+ * ```
172
+ *
132
173
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#fade | FFmpeg fade filter}
133
174
  */
134
175
  fade(type, start, duration) {
@@ -168,6 +209,12 @@ export class FilterPresetBase {
168
209
  * @param factor - Volume multiplication factor (1.0 = unchanged, 2.0 = double)
169
210
  * @returns Filter string or null if not supported
170
211
  *
212
+ * @example
213
+ * ```typescript
214
+ * presets.volume(0.5) // Reduce volume by 50%
215
+ * presets.volume(1.5) // Increase volume by 50%
216
+ * ```
217
+ *
171
218
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#volume | FFmpeg volume filter}
172
219
  */
173
220
  volume(factor) {
@@ -204,6 +251,29 @@ export class FilterPresetBase {
204
251
  filter += `:channel_layouts=${channelLayout}`;
205
252
  return filter;
206
253
  }
254
+ /**
255
+ * Creates an asetnsamples filter string to set the number of samples per frame.
256
+ * This is crucial for encoders like Opus that require specific frame sizes.
257
+ *
258
+ * @param samples - Number of samples per frame
259
+ * @param padding - Whether to pad or drop samples (default: true)
260
+ * @returns Filter string or null if not supported
261
+ *
262
+ * @example
263
+ * ```typescript
264
+ * // For Opus encoder (requires 960 samples)
265
+ * presets.asetnsamples(960);
266
+ *
267
+ * // Drop samples instead of padding
268
+ * presets.asetnsamples(1024, false);
269
+ * ```
270
+ *
271
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#asetnsamples | FFmpeg asetnsamples filter}
272
+ */
273
+ asetnsamples(samples, padding = true) {
274
+ const p = padding ? 1 : 0;
275
+ return `asetnsamples=n=${samples}:p=${p}`;
276
+ }
207
277
  /**
208
278
  * Creates an atempo filter string to change audio playback speed.
209
279
  * Factor must be between 0.5 and 2.0. For larger changes, chain multiple atempo filters.
@@ -211,6 +281,12 @@ export class FilterPresetBase {
211
281
  * @param factor - Tempo factor (0.5 = half speed, 2.0 = double speed)
212
282
  * @returns Filter string or null if not supported
213
283
  *
284
+ * @example
285
+ * ```typescript
286
+ * presets.atempo(1.5) // 1.5x speed
287
+ * presets.atempo(0.8) // Slow down to 80% speed
288
+ * ```
289
+ *
214
290
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#atempo | FFmpeg atempo filter}
215
291
  */
216
292
  atempo(factor) {
@@ -224,6 +300,12 @@ export class FilterPresetBase {
224
300
  * @param duration - Fade duration in seconds
225
301
  * @returns Filter string or null if not supported
226
302
  *
303
+ * @example
304
+ * ```typescript
305
+ * presets.afade('in', 0, 3) // 3-second audio fade in
306
+ * presets.afade('out', 20, 2) // 2-second fade out at 20s
307
+ * ```
308
+ *
227
309
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#afade | FFmpeg afade filter}
228
310
  */
229
311
  afade(type, start, duration) {
@@ -236,11 +318,360 @@ export class FilterPresetBase {
236
318
  * @param duration - How to determine output duration (default: 'longest')
237
319
  * @returns Filter string or null if not supported
238
320
  *
321
+ * @example
322
+ * ```typescript
323
+ * presets.amix(3, 'longest') // Mix 3 audio streams
324
+ * presets.amix(2, 'first') // Mix 2 streams, use first's duration
325
+ * ```
326
+ *
239
327
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#amix | FFmpeg amix filter}
240
328
  */
241
329
  amix(inputs = 2, duration = 'longest') {
242
330
  return `amix=inputs=${inputs}:duration=${duration}`;
243
331
  }
332
+ /**
333
+ * Creates a pad filter string to add padding to video.
334
+ * Essential for aspect ratio adjustments and letterboxing.
335
+ *
336
+ * @param width - Output width (can use expressions like 'iw+100')
337
+ * @param height - Output height (can use expressions like 'ih+100')
338
+ * @param x - X position of input video (default: '(ow-iw)/2' for center)
339
+ * @param y - Y position of input video (default: '(oh-ih)/2' for center)
340
+ * @param color - Padding color (default: 'black')
341
+ * @returns Filter string or null if not supported
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * // Add black bars for 16:9 aspect ratio
346
+ * presets.pad('iw', 'iw*9/16');
347
+ *
348
+ * // Add 50px padding on all sides
349
+ * presets.pad('iw+100', 'ih+100');
350
+ * ```
351
+ *
352
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#pad | FFmpeg pad filter}
353
+ */
354
+ pad(width, height, x, y, color = 'black') {
355
+ let filter = `pad=${width}:${height}`;
356
+ if (x !== undefined)
357
+ filter += `:${x}`;
358
+ if (y !== undefined)
359
+ filter += `:${y}`;
360
+ filter += `:${color}`;
361
+ return filter;
362
+ }
363
+ /**
364
+ * Creates a trim filter string to cut a portion of the stream.
365
+ * Crucial for cutting segments from media.
366
+ *
367
+ * @param start - Start time in seconds
368
+ * @param end - End time in seconds (optional)
369
+ * @param duration - Duration in seconds (optional, alternative to end)
370
+ * @returns Filter string or null if not supported
371
+ *
372
+ * @example
373
+ * ```typescript
374
+ * presets.trim(10, 30) // Extract from 10s to 30s
375
+ * presets.trim(5, undefined, 10) // Extract 10s starting at 5s
376
+ * ```
377
+ *
378
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#trim | FFmpeg trim filter}
379
+ */
380
+ trim(start, end, duration) {
381
+ let filter = `trim=start=${start}`;
382
+ if (end !== undefined)
383
+ filter += `:end=${end}`;
384
+ if (duration !== undefined)
385
+ filter += `:duration=${duration}`;
386
+ return filter;
387
+ }
388
+ /**
389
+ * Creates a setpts filter string to change presentation timestamps.
390
+ * Essential for speed changes and timestamp manipulation.
391
+ *
392
+ * @param expression - PTS expression (e.g., 'PTS*2' for half speed, 'PTS/2' for double speed)
393
+ * @returns Filter string or null if not supported
394
+ *
395
+ * @example
396
+ * ```typescript
397
+ * // Double speed
398
+ * presets.setpts('PTS/2');
399
+ *
400
+ * // Half speed
401
+ * presets.setpts('PTS*2');
402
+ *
403
+ * // Reset timestamps
404
+ * presets.setpts('PTS-STARTPTS');
405
+ * ```
406
+ *
407
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#setpts | FFmpeg setpts filter}
408
+ */
409
+ setpts(expression) {
410
+ return `setpts=${expression}`;
411
+ }
412
+ /**
413
+ * Creates an asetpts filter string for audio timestamp manipulation.
414
+ *
415
+ * @param expression - PTS expression
416
+ * @returns Filter string or null if not supported
417
+ *
418
+ * @example
419
+ * ```typescript
420
+ * presets.asetpts('PTS-STARTPTS') // Reset timestamps to start from 0
421
+ * ```
422
+ *
423
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#asetpts | FFmpeg asetpts filter}
424
+ */
425
+ asetpts(expression) {
426
+ return `asetpts=${expression}`;
427
+ }
428
+ /**
429
+ * Creates a transpose filter string for rotation/flipping.
430
+ * More efficient than rotate for 90-degree rotations.
431
+ *
432
+ * @param mode - Transpose mode (0-3, or named constants)
433
+ * @returns Filter string or null if not supported
434
+ *
435
+ * @example
436
+ * ```typescript
437
+ * presets.transpose(1) // Rotate 90 degrees clockwise
438
+ * presets.transpose('cclock') // Rotate 90 degrees counter-clockwise
439
+ * ```
440
+ *
441
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#transpose | FFmpeg transpose filter}
442
+ */
443
+ transpose(mode) {
444
+ return `transpose=${mode}`;
445
+ }
446
+ /**
447
+ * Creates a setsar filter string to set sample aspect ratio.
448
+ * Important for correcting aspect ratio issues.
449
+ *
450
+ * @param ratio - Aspect ratio (e.g., '1:1', '16:9', or number)
451
+ * @returns Filter string or null if not supported
452
+ *
453
+ * @example
454
+ * ```typescript
455
+ * presets.setsar('1:1') // Square pixels
456
+ * presets.setsar(1.333) // 4:3 aspect ratio
457
+ * ```
458
+ *
459
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#setsar | FFmpeg setsar/setdar filter}
460
+ */
461
+ setsar(ratio) {
462
+ return `setsar=${ratio}`;
463
+ }
464
+ /**
465
+ * Creates a setdar filter string to set display aspect ratio.
466
+ *
467
+ * @param ratio - Aspect ratio (e.g., '16:9', '4:3')
468
+ * @returns Filter string or null if not supported
469
+ *
470
+ * @example
471
+ * ```typescript
472
+ * presets.setdar('16:9') // Widescreen
473
+ * presets.setdar('4:3') // Traditional TV aspect
474
+ * ```
475
+ *
476
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#setsar | FFmpeg setsar/setdar filter}
477
+ */
478
+ setdar(ratio) {
479
+ return `setdar=${ratio}`;
480
+ }
481
+ /**
482
+ * Creates an apad filter string to add audio padding.
483
+ * Useful for ensuring minimum audio duration.
484
+ *
485
+ * @param wholeDuration - Minimum duration in seconds (optional)
486
+ * @param padDuration - Amount of padding to add in seconds (optional)
487
+ * @returns Filter string or null if not supported
488
+ *
489
+ * @example
490
+ * ```typescript
491
+ * presets.apad(30) // Ensure at least 30 seconds total
492
+ * presets.apad(undefined, 5) // Add 5 seconds of padding
493
+ * ```
494
+ *
495
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#apad | FFmpeg apad filter}
496
+ */
497
+ apad(wholeDuration, padDuration) {
498
+ if (!wholeDuration && !padDuration)
499
+ return 'apad';
500
+ let filter = 'apad';
501
+ if (wholeDuration)
502
+ filter += `=whole_dur=${wholeDuration}`;
503
+ if (padDuration)
504
+ filter += wholeDuration ? `:pad_dur=${padDuration}` : `=pad_dur=${padDuration}`;
505
+ return filter;
506
+ }
507
+ /**
508
+ * Creates a deinterlace filter string.
509
+ * Essential for processing interlaced content.
510
+ *
511
+ * @param mode - Deinterlace mode (default: 'yadif')
512
+ * @returns Filter string or null if not supported
513
+ *
514
+ * @example
515
+ * ```typescript
516
+ * presets.deinterlace('yadif') // Standard deinterlacing
517
+ * presets.deinterlace('bwdif') // Bob Weaver deinterlacing
518
+ * ```
519
+ *
520
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#yadif | FFmpeg yadif filter}
521
+ */
522
+ deinterlace(mode = 'yadif') {
523
+ return mode;
524
+ }
525
+ /**
526
+ * Creates a select filter string to select specific frames.
527
+ * Powerful for extracting keyframes, specific frame types, etc.
528
+ *
529
+ * @param expression - Selection expression
530
+ * @returns Filter string or null if not supported
531
+ *
532
+ * @example
533
+ * ```typescript
534
+ * presets.select('eq(pict_type,I)') // Select only keyframes
535
+ * presets.select('not(mod(n,10))') // Select every 10th frame
536
+ * ```
537
+ *
538
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#select | FFmpeg select filter}
539
+ */
540
+ select(expression) {
541
+ return `select='${expression}'`;
542
+ }
543
+ /**
544
+ * Creates an aselect filter string for audio selection.
545
+ *
546
+ * @param expression - Selection expression
547
+ * @returns Filter string or null if not supported
548
+ *
549
+ * @example
550
+ * ```typescript
551
+ * presets.aselect('between(t,10,20)') // Select audio between 10-20 seconds
552
+ * ```
553
+ *
554
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#aselect | FFmpeg aselect filter}
555
+ */
556
+ aselect(expression) {
557
+ return `aselect='${expression}'`;
558
+ }
559
+ /**
560
+ * Creates a concat filter string to concatenate multiple inputs.
561
+ * Essential for joining multiple video/audio segments.
562
+ *
563
+ * @param n - Number of input segments
564
+ * @param v - Number of output video streams (0 or 1)
565
+ * @param a - Number of output audio streams (0 or 1)
566
+ * @returns Filter string or null if not supported
567
+ *
568
+ * @example
569
+ * ```typescript
570
+ * presets.concat(3, 1, 1) // Join 3 segments with video and audio
571
+ * presets.concat(2, 1, 0) // Join 2 video-only segments
572
+ * ```
573
+ *
574
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#concat | FFmpeg concat filter}
575
+ */
576
+ concat(n, v = 1, a = 1) {
577
+ return `concat=n=${n}:v=${v}:a=${a}`;
578
+ }
579
+ /**
580
+ * Creates an amerge filter string to merge multiple audio streams into one.
581
+ * Different from amix - this creates multi-channel output.
582
+ *
583
+ * @param inputs - Number of input streams
584
+ * @returns Filter string or null if not supported
585
+ *
586
+ * @example
587
+ * ```typescript
588
+ * presets.amerge(2) // Merge 2 mono streams to stereo
589
+ * presets.amerge(6) // Merge 6 channels for 5.1 surround
590
+ * ```
591
+ *
592
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#amerge | FFmpeg amerge filter}
593
+ */
594
+ amerge(inputs = 2) {
595
+ return `amerge=inputs=${inputs}`;
596
+ }
597
+ /**
598
+ * Creates a channelmap filter string to remap audio channels.
599
+ * Critical for audio channel manipulation.
600
+ *
601
+ * @param map - Channel mapping (e.g., '0-0|1-1' or 'FL-FR|FR-FL' to swap stereo)
602
+ * @returns Filter string or null if not supported
603
+ *
604
+ * @example
605
+ * ```typescript
606
+ * presets.channelmap('FL-FR|FR-FL') // Swap left and right channels
607
+ * presets.channelmap('0-0|0-1') // Duplicate mono to stereo
608
+ * ```
609
+ *
610
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#channelmap | FFmpeg channelmap filter}
611
+ */
612
+ channelmap(map) {
613
+ return `channelmap=${map}`;
614
+ }
615
+ /**
616
+ * Creates a channelsplit filter string to split audio channels.
617
+ *
618
+ * @param channelLayout - Channel layout to split (optional)
619
+ * @returns Filter string or null if not supported
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * presets.channelsplit('stereo') // Split stereo to 2 mono
624
+ * presets.channelsplit('5.1') // Split 5.1 to individual channels
625
+ * ```
626
+ *
627
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#channelsplit | FFmpeg channelsplit filter}
628
+ */
629
+ channelsplit(channelLayout) {
630
+ return channelLayout ? `channelsplit=channel_layout=${channelLayout}` : 'channelsplit';
631
+ }
632
+ /**
633
+ * Creates a loudnorm filter string for loudness normalization.
634
+ * Essential for broadcast compliance and consistent audio levels.
635
+ *
636
+ * @param I - Integrated loudness target (default: -24 LUFS)
637
+ * @param TP - True peak (default: -2 dBTP)
638
+ * @param LRA - Loudness range (default: 7 LU)
639
+ * @returns Filter string or null if not supported
640
+ *
641
+ * @example
642
+ * ```typescript
643
+ * presets.loudnorm(-23, -1, 7) // EBU R128 broadcast standard
644
+ * presets.loudnorm(-16, -1.5, 11) // Streaming platforms standard
645
+ * ```
646
+ *
647
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#loudnorm | FFmpeg loudnorm filter}
648
+ */
649
+ loudnorm(I = -24, TP = -2, LRA = 7) {
650
+ return `loudnorm=I=${I}:TP=${TP}:LRA=${LRA}`;
651
+ }
652
+ /**
653
+ * Creates a compand filter string for audio compression/expansion.
654
+ * Important for dynamic range control.
655
+ *
656
+ * @param attacks - Attack times
657
+ * @param decays - Decay times
658
+ * @param points - Transfer function points
659
+ * @param gain - Output gain
660
+ * @returns Filter string or null if not supported
661
+ *
662
+ * @example
663
+ * ```typescript
664
+ * presets.compand('0.3|0.3', '1|1', '-90/-60|-60/-40|-40/-30|-20/-20', 6)
665
+ * ```
666
+ *
667
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#compand | FFmpeg compand filter}
668
+ */
669
+ compand(attacks, decays, points, gain) {
670
+ let filter = `compand=attacks=${attacks}:decays=${decays}:points=${points}`;
671
+ if (gain !== undefined)
672
+ filter += `:gain=${gain}`;
673
+ return filter;
674
+ }
244
675
  }
245
676
  /**
246
677
  * Filter chain builder for composing multiple filters.
@@ -263,6 +694,11 @@ export class FilterChain {
263
694
  *
264
695
  * @param filter - Filter string to add (ignored if null/undefined)
265
696
  * @returns This instance for chaining
697
+ *
698
+ * @example
699
+ * ```typescript
700
+ * chain.add('scale=1920:1080')
701
+ * ```
266
702
  */
267
703
  add(filter) {
268
704
  if (filter) {
@@ -275,6 +711,11 @@ export class FilterChain {
275
711
  *
276
712
  * @param filter - Custom filter string
277
713
  * @returns This instance for chaining
714
+ *
715
+ * @example
716
+ * ```typescript
717
+ * chain.custom('myfilter=param1:param2')
718
+ * ```
278
719
  */
279
720
  custom(filter) {
280
721
  return this.add(filter);
@@ -284,6 +725,11 @@ export class FilterChain {
284
725
  *
285
726
  * @param separator - Separator between filters (default: ',')
286
727
  * @returns Combined filter string
728
+ *
729
+ * @example
730
+ * ```typescript
731
+ * const filterString = chain.build() // "scale=1920:1080,fps=30"
732
+ * ```
287
733
  */
288
734
  build(separator = ',') {
289
735
  return this.filters.join(separator);
@@ -292,6 +738,11 @@ export class FilterChain {
292
738
  * Returns the filters as an array.
293
739
  *
294
740
  * @returns Array of filter strings
741
+ *
742
+ * @example
743
+ * ```typescript
744
+ * const filters = chain.toArray() // ["scale=1920:1080", "fps=30"]
745
+ * ```
295
746
  */
296
747
  toArray() {
297
748
  return [...this.filters];
@@ -328,22 +779,52 @@ export class ChainBuilderBase extends FilterChain {
328
779
  * @param width - Target width
329
780
  * @param height - Target height
330
781
  * @param options - Additional scaling options
782
+ *
331
783
  * @returns This instance for chaining
332
784
  *
333
- * @see {@link FilterPresetBase.scale}
334
- */
335
- scale(width, height, options) {
336
- return this.add(this.presets.scale(width, height, options));
337
- }
338
- /**
785
+ * @example
786
+ * ```typescript
787
+ * const chain = FilterPresets.chain()
788
+ * .scale(1920, 1080)
789
+ * .build();
790
+ * ```
791
+ *
792
+ * @example
793
+ * ```typescript
794
+ * const chain = FilterPresets.chain()
795
+ * .scale(1280, 720, { flags: 'lanczos' })
796
+ * .build();
797
+ * ```
798
+ *
799
+ * @see {@link FilterPresetBase.scale}
800
+ */
801
+ scale(width, height, options) {
802
+ return this.add(this.presets.scale(width, height, options));
803
+ }
804
+ /**
339
805
  * Adds a crop filter to the chain.
340
806
  *
341
807
  * @param width - Crop width
342
808
  * @param height - Crop height
343
809
  * @param x - X position (default: 0)
344
810
  * @param y - Y position (default: 0)
811
+ *
345
812
  * @returns This instance for chaining
346
813
  *
814
+ * @example
815
+ * ```typescript
816
+ * const chain = FilterPresets.chain()
817
+ * .crop(640, 480)
818
+ * .build();
819
+ * ```
820
+ *
821
+ * @example
822
+ * ```typescript
823
+ * const chain = FilterPresets.chain()
824
+ * .crop(1920, 1080, 100, 50)
825
+ * .build();
826
+ * ```
827
+ *
347
828
  * @see {@link FilterPresetBase.crop}
348
829
  */
349
830
  crop(width, height, x = 0, y = 0) {
@@ -353,8 +834,23 @@ export class ChainBuilderBase extends FilterChain {
353
834
  * Adds an FPS filter to the chain.
354
835
  *
355
836
  * @param fps - Target frame rate
837
+ *
356
838
  * @returns This instance for chaining
357
839
  *
840
+ * @example
841
+ * ```typescript
842
+ * const chain = FilterPresets.chain()
843
+ * .fps(30)
844
+ * .build();
845
+ * ```
846
+ *
847
+ * @example
848
+ * ```typescript
849
+ * const chain = FilterPresets.chain()
850
+ * .fps(23.976)
851
+ * .build();
852
+ * ```
853
+ *
358
854
  * @see {@link FilterPresetBase.fps}
359
855
  */
360
856
  fps(fps) {
@@ -364,8 +860,23 @@ export class ChainBuilderBase extends FilterChain {
364
860
  * Adds a format filter to the chain.
365
861
  *
366
862
  * @param pixelFormat - Target pixel format(s)
863
+ *
367
864
  * @returns This instance for chaining
368
865
  *
866
+ * @example
867
+ * ```typescript
868
+ * const chain = FilterPresets.chain()
869
+ * .format('yuv420p')
870
+ * .build();
871
+ * ```
872
+ *
873
+ * @example
874
+ * ```typescript
875
+ * const chain = FilterPresets.chain()
876
+ * .format(AV_PIX_FMT_RGB24)
877
+ * .build();
878
+ * ```
879
+ *
369
880
  * @see {@link FilterPresetBase.format}
370
881
  */
371
882
  format(pixelFormat) {
@@ -375,8 +886,23 @@ export class ChainBuilderBase extends FilterChain {
375
886
  * Adds a rotate filter to the chain.
376
887
  *
377
888
  * @param angle - Rotation angle in degrees
889
+ *
378
890
  * @returns This instance for chaining
379
891
  *
892
+ * @example
893
+ * ```typescript
894
+ * const chain = FilterPresets.chain()
895
+ * .rotate(45)
896
+ * .build();
897
+ * ```
898
+ *
899
+ * @example
900
+ * ```typescript
901
+ * const chain = FilterPresets.chain()
902
+ * .rotate(-90)
903
+ * .build();
904
+ * ```
905
+ *
380
906
  * @see {@link FilterPresetBase.rotate}
381
907
  */
382
908
  rotate(angle) {
@@ -387,6 +913,13 @@ export class ChainBuilderBase extends FilterChain {
387
913
  *
388
914
  * @returns This instance for chaining
389
915
  *
916
+ * @example
917
+ * ```typescript
918
+ * const chain = FilterPresets.chain()
919
+ * .hflip()
920
+ * .build();
921
+ * ```
922
+ *
390
923
  * @see {@link FilterPresetBase.hflip}
391
924
  */
392
925
  hflip() {
@@ -397,6 +930,13 @@ export class ChainBuilderBase extends FilterChain {
397
930
  *
398
931
  * @returns This instance for chaining
399
932
  *
933
+ * @example
934
+ * ```typescript
935
+ * const chain = FilterPresets.chain()
936
+ * .vflip()
937
+ * .build();
938
+ * ```
939
+ *
400
940
  * @see {@link FilterPresetBase.vflip}
401
941
  */
402
942
  vflip() {
@@ -408,8 +948,23 @@ export class ChainBuilderBase extends FilterChain {
408
948
  * @param type - Fade type ('in' or 'out')
409
949
  * @param start - Start time in seconds
410
950
  * @param duration - Fade duration in seconds
951
+ *
411
952
  * @returns This instance for chaining
412
953
  *
954
+ * @example
955
+ * ```typescript
956
+ * const chain = FilterPresets.chain()
957
+ * .fade('in', 0, 2)
958
+ * .build();
959
+ * ```
960
+ *
961
+ * @example
962
+ * ```typescript
963
+ * const chain = FilterPresets.chain()
964
+ * .fade('out', 10, 1.5)
965
+ * .build();
966
+ * ```
967
+ *
413
968
  * @see {@link FilterPresetBase.fade}
414
969
  */
415
970
  fade(type, start, duration) {
@@ -421,8 +976,23 @@ export class ChainBuilderBase extends FilterChain {
421
976
  * @param x - X position (default: 0)
422
977
  * @param y - Y position (default: 0)
423
978
  * @param options - Additional overlay options
979
+ *
424
980
  * @returns This instance for chaining
425
981
  *
982
+ * @example
983
+ * ```typescript
984
+ * const chain = FilterPresets.chain()
985
+ * .overlay(100, 50)
986
+ * .build();
987
+ * ```
988
+ *
989
+ * @example
990
+ * ```typescript
991
+ * const chain = FilterPresets.chain()
992
+ * .overlay(10, 10, { enable: 'between(t,5,10)' })
993
+ * .build();
994
+ * ```
995
+ *
426
996
  * @see {@link FilterPresetBase.overlay}
427
997
  */
428
998
  overlay(x = 0, y = 0, options) {
@@ -432,8 +1002,23 @@ export class ChainBuilderBase extends FilterChain {
432
1002
  * Adds a volume filter to the chain.
433
1003
  *
434
1004
  * @param factor - Volume factor
1005
+ *
435
1006
  * @returns This instance for chaining
436
1007
  *
1008
+ * @example
1009
+ * ```typescript
1010
+ * const chain = FilterPresets.chain()
1011
+ * .volume(0.5)
1012
+ * .build();
1013
+ * ```
1014
+ *
1015
+ * @example
1016
+ * ```typescript
1017
+ * const chain = FilterPresets.chain()
1018
+ * .volume(2.0)
1019
+ * .build();
1020
+ * ```
1021
+ *
437
1022
  * @see {@link FilterPresetBase.volume}
438
1023
  */
439
1024
  volume(factor) {
@@ -445,19 +1030,76 @@ export class ChainBuilderBase extends FilterChain {
445
1030
  * @param sampleFormat - Target sample format
446
1031
  * @param sampleRate - Target sample rate (optional)
447
1032
  * @param channelLayout - Target channel layout (optional)
1033
+ *
448
1034
  * @returns This instance for chaining
449
1035
  *
1036
+ * @example
1037
+ * ```typescript
1038
+ * const chain = FilterPresets.chain()
1039
+ * .aformat(AV_SAMPLE_FMT_FLT, 48000, 'stereo')
1040
+ * .build();
1041
+ * ```
1042
+ *
1043
+ * @example
1044
+ * ```typescript
1045
+ * const chain = FilterPresets.chain()
1046
+ * .aformat('s16', 44100)
1047
+ * .build();
1048
+ * ```
1049
+ *
450
1050
  * @see {@link FilterPresetBase.aformat}
451
1051
  */
452
1052
  aformat(sampleFormat, sampleRate, channelLayout) {
453
1053
  return this.add(this.presets.aformat(sampleFormat, sampleRate, channelLayout));
454
1054
  }
1055
+ /**
1056
+ * Adds an asetnsamples filter to the chain.
1057
+ *
1058
+ * @param samples - Number of samples per frame
1059
+ * @param padding - Whether to pad or drop samples (default: true)
1060
+ *
1061
+ * @returns This instance for chaining
1062
+ *
1063
+ * @example
1064
+ * ```typescript
1065
+ * const chain = FilterPresets.chain()
1066
+ * .asetnsamples(960)
1067
+ * .build();
1068
+ * ```
1069
+ *
1070
+ * @example
1071
+ * ```typescript
1072
+ * const chain = FilterPresets.chain()
1073
+ * .asetnsamples(1024, false)
1074
+ * .build();
1075
+ * ```
1076
+ *
1077
+ * @see {@link FilterPresetBase.asetnsamples}
1078
+ */
1079
+ asetnsamples(samples, padding = true) {
1080
+ return this.add(this.presets.asetnsamples(samples, padding));
1081
+ }
455
1082
  /**
456
1083
  * Adds an atempo filter to the chain.
457
1084
  *
458
1085
  * @param factor - Tempo factor (0.5 to 2.0)
1086
+ *
459
1087
  * @returns This instance for chaining
460
1088
  *
1089
+ * @example
1090
+ * ```typescript
1091
+ * const chain = FilterPresets.chain()
1092
+ * .atempo(1.5)
1093
+ * .build();
1094
+ * ```
1095
+ *
1096
+ * @example
1097
+ * ```typescript
1098
+ * const chain = FilterPresets.chain()
1099
+ * .atempo(0.8)
1100
+ * .build();
1101
+ * ```
1102
+ *
461
1103
  * @see {@link FilterPresetBase.atempo}
462
1104
  */
463
1105
  atempo(factor) {
@@ -469,8 +1111,23 @@ export class ChainBuilderBase extends FilterChain {
469
1111
  * @param type - Fade type ('in' or 'out')
470
1112
  * @param start - Start time in seconds
471
1113
  * @param duration - Fade duration in seconds
1114
+ *
472
1115
  * @returns This instance for chaining
473
1116
  *
1117
+ * @example
1118
+ * ```typescript
1119
+ * const chain = FilterPresets.chain()
1120
+ * .afade('in', 0, 3)
1121
+ * .build();
1122
+ * ```
1123
+ *
1124
+ * @example
1125
+ * ```typescript
1126
+ * const chain = FilterPresets.chain()
1127
+ * .afade('out', 25, 2)
1128
+ * .build();
1129
+ * ```
1130
+ *
474
1131
  * @see {@link FilterPresetBase.afade}
475
1132
  */
476
1133
  afade(type, start, duration) {
@@ -481,24 +1138,323 @@ export class ChainBuilderBase extends FilterChain {
481
1138
  *
482
1139
  * @param inputs - Number of inputs (default: 2)
483
1140
  * @param duration - Duration mode (default: 'longest')
1141
+ *
484
1142
  * @returns This instance for chaining
485
1143
  *
1144
+ * @example
1145
+ * ```typescript
1146
+ * const chain = FilterPresets.chain()
1147
+ * .amix(3, 'longest')
1148
+ * .build();
1149
+ * ```
1150
+ *
1151
+ * @example
1152
+ * ```typescript
1153
+ * const chain = FilterPresets.chain()
1154
+ * .amix(2, 'first')
1155
+ * .build();
1156
+ * ```
1157
+ *
486
1158
  * @see {@link FilterPresetBase.amix}
487
1159
  */
488
1160
  amix(inputs = 2, duration = 'longest') {
489
1161
  return this.add(this.presets.amix(inputs, duration));
490
1162
  }
1163
+ // ========== New Critical Filter Chain Methods ==========
1164
+ /**
1165
+ * Adds a pad filter to the chain.
1166
+ *
1167
+ * @param width - Target width
1168
+ * @param height - Target height
1169
+ * @param x - X position of input
1170
+ * @param y - Y position of input
1171
+ * @param color - Padding color
1172
+ *
1173
+ * @returns This instance for chaining
1174
+ *
1175
+ * @example
1176
+ * ```typescript
1177
+ * chain.pad('iw*2', 'ih*2') // Double the canvas size
1178
+ * ```
1179
+ *
1180
+ * @see {@link FilterPresetBase.pad}
1181
+ */
1182
+ pad(width, height, x, y, color = 'black') {
1183
+ return this.add(this.presets.pad(width, height, x, y, color));
1184
+ }
1185
+ /**
1186
+ * Adds a trim filter to the chain.
1187
+ *
1188
+ * @param start - Start time in seconds
1189
+ * @param end - End time in seconds
1190
+ * @param duration - Duration in seconds
1191
+ *
1192
+ * @returns This instance for chaining
1193
+ *
1194
+ * @example
1195
+ * ```typescript
1196
+ * chain.trim(10, 20) // Extract 10 seconds from t=10 to t=20
1197
+ * ```
1198
+ *
1199
+ * @see {@link FilterPresetBase.trim}
1200
+ */
1201
+ trim(start, end, duration) {
1202
+ return this.add(this.presets.trim(start, end, duration));
1203
+ }
1204
+ /**
1205
+ * Adds a setpts filter to the chain.
1206
+ *
1207
+ * @param expression - PTS expression
1208
+ *
1209
+ * @returns This instance for chaining
1210
+ *
1211
+ * @example
1212
+ * ```typescript
1213
+ * chain.setpts('PTS/2') // Double playback speed
1214
+ * ```
1215
+ *
1216
+ * @see {@link FilterPresetBase.setpts}
1217
+ */
1218
+ setpts(expression) {
1219
+ return this.add(this.presets.setpts(expression));
1220
+ }
1221
+ /**
1222
+ * Adds an asetpts filter to the chain.
1223
+ *
1224
+ * @param expression - PTS expression
1225
+ *
1226
+ * @returns This instance for chaining
1227
+ *
1228
+ * @example
1229
+ * ```typescript
1230
+ * chain.asetpts('PTS-STARTPTS') // Reset audio timestamps
1231
+ * ```
1232
+ *
1233
+ * @see {@link FilterPresetBase.asetpts}
1234
+ */
1235
+ asetpts(expression) {
1236
+ return this.add(this.presets.asetpts(expression));
1237
+ }
1238
+ /**
1239
+ * Adds a setsar filter to the chain.
1240
+ *
1241
+ * @param ratio - Sample aspect ratio
1242
+ *
1243
+ * @returns This instance for chaining
1244
+ *
1245
+ * @example
1246
+ * ```typescript
1247
+ * chain.setsar('1:1') // Square pixels
1248
+ * ```
1249
+ *
1250
+ * @see {@link FilterPresetBase.setsar}
1251
+ */
1252
+ setsar(ratio) {
1253
+ return this.add(this.presets.setsar(ratio));
1254
+ }
1255
+ /**
1256
+ * Adds a setdar filter to the chain.
1257
+ *
1258
+ * @param ratio - Display aspect ratio
1259
+ *
1260
+ * @returns This instance for chaining
1261
+ *
1262
+ * @example
1263
+ * ```typescript
1264
+ * chain.setdar('16:9') // Set widescreen aspect
1265
+ * ```
1266
+ *
1267
+ * @see {@link FilterPresetBase.setdar}
1268
+ */
1269
+ setdar(ratio) {
1270
+ return this.add(this.presets.setdar(ratio));
1271
+ }
1272
+ /**
1273
+ * Adds an apad filter to the chain.
1274
+ *
1275
+ * @param wholeDuration - Minimum total duration
1276
+ * @param padDuration - Padding duration to add
1277
+ *
1278
+ * @returns This instance for chaining
1279
+ *
1280
+ * @example
1281
+ * ```typescript
1282
+ * chain.apad(10) // Ensure at least 10 seconds of audio
1283
+ * ```
1284
+ *
1285
+ * @see {@link FilterPresetBase.apad}
1286
+ */
1287
+ apad(wholeDuration, padDuration) {
1288
+ return this.add(this.presets.apad(wholeDuration, padDuration));
1289
+ }
1290
+ /**
1291
+ * Adds a select filter to the chain.
1292
+ *
1293
+ * @param expression - Selection expression
1294
+ *
1295
+ * @returns This instance for chaining
1296
+ *
1297
+ * @example
1298
+ * ```typescript
1299
+ * chain.select('eq(pict_type,I)') // Select only I-frames
1300
+ * ```
1301
+ *
1302
+ * @see {@link FilterPresetBase.select}
1303
+ */
1304
+ select(expression) {
1305
+ return this.add(this.presets.select(expression));
1306
+ }
1307
+ /**
1308
+ * Adds an aselect filter to the chain.
1309
+ *
1310
+ * @param expression - Selection expression
1311
+ *
1312
+ * @returns This instance for chaining
1313
+ *
1314
+ * @example
1315
+ * ```typescript
1316
+ * chain.aselect('between(t,10,20)') // Select audio between 10-20s
1317
+ * ```
1318
+ *
1319
+ * @see {@link FilterPresetBase.aselect}
1320
+ */
1321
+ aselect(expression) {
1322
+ return this.add(this.presets.aselect(expression));
1323
+ }
1324
+ /**
1325
+ * Adds a concat filter to the chain.
1326
+ *
1327
+ * @param n - Number of input segments
1328
+ * @param v - Number of video streams
1329
+ * @param a - Number of audio streams
1330
+ *
1331
+ * @returns This instance for chaining
1332
+ *
1333
+ * @example
1334
+ * ```typescript
1335
+ * chain.concat(3, 1, 1) // Concatenate 3 segments with video and audio
1336
+ * ```
1337
+ *
1338
+ * @see {@link FilterPresetBase.concat}
1339
+ */
1340
+ concat(n, v = 1, a = 1) {
1341
+ return this.add(this.presets.concat(n, v, a));
1342
+ }
1343
+ /**
1344
+ * Adds an amerge filter to the chain.
1345
+ *
1346
+ * @param inputs - Number of input streams
1347
+ *
1348
+ * @returns This instance for chaining
1349
+ *
1350
+ * @example
1351
+ * ```typescript
1352
+ * chain.amerge(2) // Merge 2 audio streams
1353
+ * ```
1354
+ *
1355
+ * @see {@link FilterPresetBase.amerge}
1356
+ */
1357
+ amerge(inputs = 2) {
1358
+ return this.add(this.presets.amerge(inputs));
1359
+ }
1360
+ /**
1361
+ * Adds a channelmap filter to the chain.
1362
+ *
1363
+ * @param map - Channel mapping string
1364
+ *
1365
+ * @returns This instance for chaining
1366
+ *
1367
+ * @example
1368
+ * ```typescript
1369
+ * chain.channelmap('FL-FR|FR-FL') // Swap stereo channels
1370
+ * ```
1371
+ *
1372
+ * @see {@link FilterPresetBase.channelmap}
1373
+ */
1374
+ channelmap(map) {
1375
+ return this.add(this.presets.channelmap(map));
1376
+ }
1377
+ /**
1378
+ * Adds a channelsplit filter to the chain.
1379
+ *
1380
+ * @param channelLayout - Channel layout to split
1381
+ *
1382
+ * @returns This instance for chaining
1383
+ *
1384
+ * @example
1385
+ * ```typescript
1386
+ * chain.channelsplit('stereo') // Split stereo into two mono streams
1387
+ * ```
1388
+ *
1389
+ * @see {@link FilterPresetBase.channelsplit}
1390
+ */
1391
+ channelsplit(channelLayout) {
1392
+ return this.add(this.presets.channelsplit(channelLayout));
1393
+ }
1394
+ /**
1395
+ * Adds a loudnorm filter to the chain.
1396
+ *
1397
+ * @param I - Integrated loudness target (LUFS)
1398
+ * @param TP - True peak (dBTP)
1399
+ * @param LRA - Loudness range (LU)
1400
+ *
1401
+ * @returns This instance for chaining
1402
+ *
1403
+ * @example
1404
+ * ```typescript
1405
+ * chain.loudnorm(-16, -1.5, 11) // Streaming loudness standard
1406
+ * ```
1407
+ *
1408
+ * @see {@link FilterPresetBase.loudnorm}
1409
+ */
1410
+ loudnorm(I = -24, TP = -2, LRA = 7) {
1411
+ return this.add(this.presets.loudnorm(I, TP, LRA));
1412
+ }
1413
+ /**
1414
+ * Adds a compand filter to the chain.
1415
+ *
1416
+ * @param attacks - Attack times
1417
+ * @param decays - Decay times
1418
+ * @param points - Transfer function points
1419
+ * @param gain - Output gain
1420
+ *
1421
+ * @returns This instance for chaining
1422
+ *
1423
+ * @example
1424
+ * ```typescript
1425
+ * chain.compand('0.3|0.3', '1|1', '-90/-60|-60/-40|-40/-30|-20/-20', 6)
1426
+ * ```
1427
+ *
1428
+ * @see {@link FilterPresetBase.compand}
1429
+ */
1430
+ compand(attacks, decays, points, gain) {
1431
+ return this.add(this.presets.compand(attacks, decays, points, gain));
1432
+ }
491
1433
  /**
492
1434
  * Adds a transpose filter to the chain (hardware-specific).
493
1435
  * Only available for hardware presets that support transpose
494
1436
  *
495
- * @param dir - Transpose direction (default: 0)
1437
+ * @param mode - Transpose mode (number or string)
1438
+ *
496
1439
  * @returns This instance for chaining
497
1440
  *
1441
+ * @example
1442
+ * ```typescript
1443
+ * const chain = FilterPresets.chain()
1444
+ * .transpose('clock')
1445
+ * .build();
1446
+ * ```
1447
+ *
1448
+ * @example
1449
+ * ```typescript
1450
+ * const chain = FilterPresets.chain()
1451
+ * .transpose('cclock_flip')
1452
+ * .build();
1453
+ * ```
498
1454
  */
499
- transpose(dir = 0) {
1455
+ transpose(mode = 0) {
500
1456
  if ('transpose' in this.presets) {
501
- return this.add(this.presets.transpose(dir));
1457
+ return this.add(this.presets.transpose(mode));
502
1458
  }
503
1459
  return this.add(null);
504
1460
  }
@@ -507,8 +1463,22 @@ export class ChainBuilderBase extends FilterChain {
507
1463
  * Only available for hardware presets that support tonemapping
508
1464
  *
509
1465
  * @param options - Tonemapping options
1466
+ *
510
1467
  * @returns This instance for chaining
511
1468
  *
1469
+ * @example
1470
+ * ```typescript
1471
+ * const chain = FilterPresets.chain()
1472
+ * .tonemap()
1473
+ * .build();
1474
+ * ```
1475
+ *
1476
+ * @example
1477
+ * ```typescript
1478
+ * const chain = FilterPresets.chain()
1479
+ * .tonemap({ tonemap: 'hable', desat: '0' })
1480
+ * .build();
1481
+ * ```
512
1482
  */
513
1483
  tonemap(options) {
514
1484
  if ('tonemap' in this.presets) {
@@ -521,8 +1491,22 @@ export class ChainBuilderBase extends FilterChain {
521
1491
  * Only available for hardware presets that support deinterlacing
522
1492
  *
523
1493
  * @param mode - Deinterlace mode (optional)
1494
+ *
524
1495
  * @returns This instance for chaining
525
1496
  *
1497
+ * @example
1498
+ * ```typescript
1499
+ * const chain = FilterPresets.chain()
1500
+ * .deinterlace()
1501
+ * .build();
1502
+ * ```
1503
+ *
1504
+ * @example
1505
+ * ```typescript
1506
+ * const chain = FilterPresets.chain()
1507
+ * .deinterlace('yadif')
1508
+ * .build();
1509
+ * ```
526
1510
  */
527
1511
  deinterlace(mode) {
528
1512
  if ('deinterlace' in this.presets) {
@@ -535,8 +1519,22 @@ export class ChainBuilderBase extends FilterChain {
535
1519
  * Falls back to hflip/vflip if hardware flip not available
536
1520
  *
537
1521
  * @param direction - Flip direction ('h' or 'v')
1522
+ *
538
1523
  * @returns This instance for chaining
539
1524
  *
1525
+ * @example
1526
+ * ```typescript
1527
+ * const chain = FilterPresets.chain()
1528
+ * .flip('h')
1529
+ * .build();
1530
+ * ```
1531
+ *
1532
+ * @example
1533
+ * ```typescript
1534
+ * const chain = FilterPresets.chain()
1535
+ * .flip('v')
1536
+ * .build();
1537
+ * ```
540
1538
  */
541
1539
  flip(direction) {
542
1540
  if ('flip' in this.presets) {
@@ -551,8 +1549,22 @@ export class ChainBuilderBase extends FilterChain {
551
1549
  *
552
1550
  * @param type - Blur type (default: 'avg')
553
1551
  * @param radius - Blur radius (optional)
1552
+ *
554
1553
  * @returns This instance for chaining
555
1554
  *
1555
+ * @example
1556
+ * ```typescript
1557
+ * const chain = FilterPresets.chain()
1558
+ * .blur('gaussian', 5)
1559
+ * .build();
1560
+ * ```
1561
+ *
1562
+ * @example
1563
+ * ```typescript
1564
+ * const chain = FilterPresets.chain()
1565
+ * .blur('box')
1566
+ * .build();
1567
+ * ```
556
1568
  */
557
1569
  blur(type = 'avg', radius) {
558
1570
  if ('blur' in this.presets) {
@@ -565,8 +1577,22 @@ export class ChainBuilderBase extends FilterChain {
565
1577
  * Only available for hardware presets that support sharpening
566
1578
  *
567
1579
  * @param amount - Sharpen amount (optional)
1580
+ *
568
1581
  * @returns This instance for chaining
569
1582
  *
1583
+ * @example
1584
+ * ```typescript
1585
+ * const chain = FilterPresets.chain()
1586
+ * .sharpen(1.5)
1587
+ * .build();
1588
+ * ```
1589
+ *
1590
+ * @example
1591
+ * ```typescript
1592
+ * const chain = FilterPresets.chain()
1593
+ * .sharpen()
1594
+ * .build();
1595
+ * ```
570
1596
  */
571
1597
  sharpen(amount) {
572
1598
  if ('sharpen' in this.presets) {
@@ -580,8 +1606,22 @@ export class ChainBuilderBase extends FilterChain {
580
1606
  *
581
1607
  * @param type - Stack type ('h' for horizontal, 'v' for vertical, 'x' for grid)
582
1608
  * @param inputs - Number of inputs (default: 2)
1609
+ *
583
1610
  * @returns This instance for chaining
584
1611
  *
1612
+ * @example
1613
+ * ```typescript
1614
+ * const chain = FilterPresets.chain()
1615
+ * .stack('h', 2)
1616
+ * .build();
1617
+ * ```
1618
+ *
1619
+ * @example
1620
+ * ```typescript
1621
+ * const chain = FilterPresets.chain()
1622
+ * .stack('x', 4)
1623
+ * .build();
1624
+ * ```
585
1625
  */
586
1626
  stack(type, inputs = 2) {
587
1627
  if ('stack' in this.presets) {
@@ -593,6 +1633,14 @@ export class ChainBuilderBase extends FilterChain {
593
1633
  * Adds a hwupload filter to upload frames to hardware.
594
1634
  *
595
1635
  * @returns This instance for chaining
1636
+ *
1637
+ * @example
1638
+ * ```typescript
1639
+ * const chain = FilterPresets.chain()
1640
+ * .hwupload()
1641
+ * .scale(1920, 1080)
1642
+ * .build();
1643
+ * ```
596
1644
  */
597
1645
  hwupload() {
598
1646
  if ('hwupload' in this.presets) {
@@ -604,6 +1652,14 @@ export class ChainBuilderBase extends FilterChain {
604
1652
  * Adds a hwdownload filter to download frames from hardware.
605
1653
  *
606
1654
  * @returns This instance for chaining
1655
+ *
1656
+ * @example
1657
+ * ```typescript
1658
+ * const chain = FilterPresets.chain()
1659
+ * .scale(1920, 1080)
1660
+ * .hwdownload()
1661
+ * .build();
1662
+ * ```
607
1663
  */
608
1664
  hwdownload() {
609
1665
  if ('hwdownload' in this.presets) {
@@ -615,7 +1671,22 @@ export class ChainBuilderBase extends FilterChain {
615
1671
  * Adds a hwmap filter to map frames between hardware devices.
616
1672
  *
617
1673
  * @param derive - Device to derive from (optional)
1674
+ *
618
1675
  * @returns This instance for chaining
1676
+ *
1677
+ * @example
1678
+ * ```typescript
1679
+ * const chain = FilterPresets.chain()
1680
+ * .hwmap('cuda')
1681
+ * .build();
1682
+ * ```
1683
+ *
1684
+ * @example
1685
+ * ```typescript
1686
+ * const chain = FilterPresets.chain()
1687
+ * .hwmap()
1688
+ * .build();
1689
+ * ```
619
1690
  */
620
1691
  hwmap(derive) {
621
1692
  if ('hwmap' in this.presets) {
@@ -683,7 +1754,18 @@ export class FilterPresets extends FilterPresetBase {
683
1754
  * @param width - Target width
684
1755
  * @param height - Target height
685
1756
  * @param flags - Scaling algorithm flags (optional)
1757
+ *
686
1758
  * @returns Scale filter string
1759
+ *
1760
+ * @example
1761
+ * ```typescript
1762
+ * const filter = FilterPresets.scale(1920, 1080);
1763
+ * ```
1764
+ *
1765
+ * @example
1766
+ * ```typescript
1767
+ * const filter = FilterPresets.scale(1280, 720, 'lanczos');
1768
+ * ```
687
1769
  */
688
1770
  static scale(width, height, flags) {
689
1771
  const result = FilterPresets.instance.scale(width, height, { flags });
@@ -696,7 +1778,18 @@ export class FilterPresets extends FilterPresetBase {
696
1778
  * @param height - Crop height
697
1779
  * @param x - X position (default: 0)
698
1780
  * @param y - Y position (default: 0)
1781
+ *
699
1782
  * @returns Crop filter string
1783
+ *
1784
+ * @example
1785
+ * ```typescript
1786
+ * const filter = FilterPresets.crop(640, 480);
1787
+ * ```
1788
+ *
1789
+ * @example
1790
+ * ```typescript
1791
+ * const filter = FilterPresets.crop(1920, 1080, 100, 50);
1792
+ * ```
700
1793
  */
701
1794
  static crop(width, height, x = 0, y = 0) {
702
1795
  const result = FilterPresets.instance.crop(width, height, x, y);
@@ -706,7 +1799,18 @@ export class FilterPresets extends FilterPresetBase {
706
1799
  * Creates an FPS filter string.
707
1800
  *
708
1801
  * @param fps - Target frame rate
1802
+ *
709
1803
  * @returns FPS filter string
1804
+ *
1805
+ * @example
1806
+ * ```typescript
1807
+ * const filter = FilterPresets.fps(30);
1808
+ * ```
1809
+ *
1810
+ * @example
1811
+ * ```typescript
1812
+ * const filter = FilterPresets.fps(23.976);
1813
+ * ```
710
1814
  */
711
1815
  static fps(fps) {
712
1816
  const result = FilterPresets.instance.fps(fps);
@@ -716,7 +1820,18 @@ export class FilterPresets extends FilterPresetBase {
716
1820
  * Creates a format filter string.
717
1821
  *
718
1822
  * @param pixelFormat - Target pixel format(s)
1823
+ *
719
1824
  * @returns Format filter string
1825
+ *
1826
+ * @example
1827
+ * ```typescript
1828
+ * const filter = FilterPresets.format('yuv420p');
1829
+ * ```
1830
+ *
1831
+ * @example
1832
+ * ```typescript
1833
+ * const filter = FilterPresets.format(AV_PIX_FMT_RGB24);
1834
+ * ```
720
1835
  */
721
1836
  static format(pixelFormat) {
722
1837
  const result = FilterPresets.instance.format(pixelFormat);
@@ -726,7 +1841,18 @@ export class FilterPresets extends FilterPresetBase {
726
1841
  * Creates a rotate filter string.
727
1842
  *
728
1843
  * @param angle - Rotation angle in degrees
1844
+ *
729
1845
  * @returns Rotate filter string
1846
+ *
1847
+ * @example
1848
+ * ```typescript
1849
+ * const filter = FilterPresets.rotate(45);
1850
+ * ```
1851
+ *
1852
+ * @example
1853
+ * ```typescript
1854
+ * const filter = FilterPresets.rotate(-90);
1855
+ * ```
730
1856
  */
731
1857
  static rotate(angle) {
732
1858
  const result = FilterPresets.instance.rotate(angle);
@@ -736,6 +1862,11 @@ export class FilterPresets extends FilterPresetBase {
736
1862
  * Creates a horizontal flip filter string.
737
1863
  *
738
1864
  * @returns Horizontal flip filter string
1865
+ *
1866
+ * @example
1867
+ * ```typescript
1868
+ * const filter = FilterPresets.hflip();
1869
+ * ```
739
1870
  */
740
1871
  static hflip() {
741
1872
  const result = FilterPresets.instance.hflip();
@@ -745,6 +1876,11 @@ export class FilterPresets extends FilterPresetBase {
745
1876
  * Creates a vertical flip filter string.
746
1877
  *
747
1878
  * @returns Vertical flip filter string
1879
+ *
1880
+ * @example
1881
+ * ```typescript
1882
+ * const filter = FilterPresets.vflip();
1883
+ * ```
748
1884
  */
749
1885
  static vflip() {
750
1886
  const result = FilterPresets.instance.vflip();
@@ -756,7 +1892,18 @@ export class FilterPresets extends FilterPresetBase {
756
1892
  * @param type - Fade type ('in' or 'out')
757
1893
  * @param start - Start time in seconds
758
1894
  * @param duration - Fade duration in seconds
1895
+ *
759
1896
  * @returns Fade filter string
1897
+ *
1898
+ * @example
1899
+ * ```typescript
1900
+ * const filter = FilterPresets.fade('in', 0, 2);
1901
+ * ```
1902
+ *
1903
+ * @example
1904
+ * ```typescript
1905
+ * const filter = FilterPresets.fade('out', 10, 1.5);
1906
+ * ```
760
1907
  */
761
1908
  static fade(type, start, duration) {
762
1909
  const result = FilterPresets.instance.fade(type, start, duration);
@@ -767,7 +1914,18 @@ export class FilterPresets extends FilterPresetBase {
767
1914
  *
768
1915
  * @param x - X position (default: 0)
769
1916
  * @param y - Y position (default: 0)
1917
+ *
770
1918
  * @returns Overlay filter string
1919
+ *
1920
+ * @example
1921
+ * ```typescript
1922
+ * const filter = FilterPresets.overlay(100, 50);
1923
+ * ```
1924
+ *
1925
+ * @example
1926
+ * ```typescript
1927
+ * const filter = FilterPresets.overlay();
1928
+ * ```
771
1929
  */
772
1930
  static overlay(x = 0, y = 0) {
773
1931
  const result = FilterPresets.instance.overlay(x, y);
@@ -777,7 +1935,18 @@ export class FilterPresets extends FilterPresetBase {
777
1935
  * Creates a volume filter string.
778
1936
  *
779
1937
  * @param factor - Volume multiplication factor
1938
+ *
780
1939
  * @returns Volume filter string
1940
+ *
1941
+ * @example
1942
+ * ```typescript
1943
+ * const filter = FilterPresets.volume(0.5);
1944
+ * ```
1945
+ *
1946
+ * @example
1947
+ * ```typescript
1948
+ * const filter = FilterPresets.volume(2.0);
1949
+ * ```
781
1950
  */
782
1951
  static volume(factor) {
783
1952
  const result = FilterPresets.instance.volume(factor);
@@ -789,17 +1958,61 @@ export class FilterPresets extends FilterPresetBase {
789
1958
  * @param sampleFormat - Target sample format
790
1959
  * @param sampleRate - Target sample rate (optional)
791
1960
  * @param channelLayout - Target channel layout (optional)
1961
+ *
792
1962
  * @returns Audio format filter string
1963
+ *
1964
+ * @example
1965
+ * ```typescript
1966
+ * const filter = FilterPresets.aformat(AV_SAMPLE_FMT_FLT, 48000, 'stereo');
1967
+ * ```
1968
+ *
1969
+ * @example
1970
+ * ```typescript
1971
+ * const filter = FilterPresets.aformat('s16', 44100);
1972
+ * ```
793
1973
  */
794
1974
  static aformat(sampleFormat, sampleRate, channelLayout) {
795
1975
  const result = FilterPresets.instance.aformat(sampleFormat, sampleRate, channelLayout);
796
1976
  return result ?? '';
797
1977
  }
1978
+ /**
1979
+ * Creates an asetnsamples filter string.
1980
+ *
1981
+ * @param samples - Number of samples per frame
1982
+ * @param padding - Whether to pad or drop samples (default: true)
1983
+ *
1984
+ * @returns Asetnsamples filter string
1985
+ *
1986
+ * @example
1987
+ * ```typescript
1988
+ * const filter = FilterPresets.asetnsamples(960);
1989
+ * ```
1990
+ *
1991
+ * @example
1992
+ * ```typescript
1993
+ * const filter = FilterPresets.asetnsamples(1024, false);
1994
+ * ```
1995
+ */
1996
+ static asetnsamples(samples, padding = true) {
1997
+ const result = FilterPresets.instance.asetnsamples(samples, padding);
1998
+ return result ?? '';
1999
+ }
798
2000
  /**
799
2001
  * Creates an atempo filter string.
800
2002
  *
801
2003
  * @param factor - Tempo factor (0.5 to 2.0)
2004
+ *
802
2005
  * @returns Atempo filter string
2006
+ *
2007
+ * @example
2008
+ * ```typescript
2009
+ * const filter = FilterPresets.atempo(1.5);
2010
+ * ```
2011
+ *
2012
+ * @example
2013
+ * ```typescript
2014
+ * const filter = FilterPresets.atempo(0.8);
2015
+ * ```
803
2016
  */
804
2017
  static atempo(factor) {
805
2018
  const result = FilterPresets.instance.atempo(factor);
@@ -811,7 +2024,18 @@ export class FilterPresets extends FilterPresetBase {
811
2024
  * @param type - Fade type ('in' or 'out')
812
2025
  * @param start - Start time in seconds
813
2026
  * @param duration - Fade duration in seconds
2027
+ *
814
2028
  * @returns Audio fade filter string
2029
+ *
2030
+ * @example
2031
+ * ```typescript
2032
+ * const filter = FilterPresets.afade('in', 0, 3);
2033
+ * ```
2034
+ *
2035
+ * @example
2036
+ * ```typescript
2037
+ * const filter = FilterPresets.afade('out', 25, 2);
2038
+ * ```
815
2039
  */
816
2040
  static afade(type, start, duration) {
817
2041
  const result = FilterPresets.instance.afade(type, start, duration);
@@ -822,7 +2046,18 @@ export class FilterPresets extends FilterPresetBase {
822
2046
  *
823
2047
  * @param inputs - Number of inputs (default: 2)
824
2048
  * @param duration - Duration mode (default: 'longest')
2049
+ *
825
2050
  * @returns Amix filter string
2051
+ *
2052
+ * @example
2053
+ * ```typescript
2054
+ * const filter = FilterPresets.amix(3, 'longest');
2055
+ * ```
2056
+ *
2057
+ * @example
2058
+ * ```typescript
2059
+ * const filter = FilterPresets.amix(2, 'first');
2060
+ * ```
826
2061
  */
827
2062
  static amix(inputs = 2, duration = 'longest') {
828
2063
  const result = FilterPresets.instance.amix(inputs, duration);
@@ -837,7 +2072,7 @@ export class FilterPresets extends FilterPresetBase {
837
2072
  * @example
838
2073
  * ```typescript
839
2074
  * // Create hardware presets for CUDA
840
- * const hw = new HardwareFilterPresets(AV_HWDEVICE_TYPE_CUDA, 'cuda');
2075
+ * const hw = new HardwareFilterPresets(AV_HWDEVICE_TYPE_CUDA);
841
2076
  *
842
2077
  * // Check capabilities
843
2078
  * if (hw.support.scale) {
@@ -859,12 +2094,12 @@ export class HardwareFilterPresets extends FilterPresetBase {
859
2094
  support;
860
2095
  /**
861
2096
  * @param deviceType - Hardware device type enum
862
- * @param deviceTypeName - Hardware device type name (e.g., 'cuda', 'vaapi')
2097
+ * @param deviceTypeName - Optional hardware device type name (e.g., 'cuda', 'vaapi')
863
2098
  */
864
2099
  constructor(deviceType, deviceTypeName) {
865
2100
  super();
866
2101
  this.deviceType = deviceType;
867
- this.deviceTypeName = deviceTypeName;
2102
+ this.deviceTypeName = deviceTypeName ?? HardwareDeviceContext.getTypeName(deviceType);
868
2103
  this.support = this.getSupport();
869
2104
  }
870
2105
  /**
@@ -918,8 +2153,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
918
2153
  * @param width - Target width
919
2154
  * @param height - Target height
920
2155
  * @param options - Hardware-specific scaling options
2156
+ *
921
2157
  * @returns Hardware scale filter string or null if not supported
922
2158
  *
2159
+ * @example
2160
+ * ```typescript
2161
+ * const filter = hwPresets.scale(1920, 1080);
2162
+ * ```
2163
+ *
2164
+ * @example
2165
+ * ```typescript
2166
+ * const filter = hwPresets.scale(1280, 720, { npp: true });
2167
+ * ```
923
2168
  *
924
2169
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#scale_005fcuda | FFmpeg scale_cuda filter}
925
2170
  */
@@ -958,8 +2203,19 @@ export class HardwareFilterPresets extends FilterPresetBase {
958
2203
  * @param x - X position (default: 0)
959
2204
  * @param y - Y position (default: 0)
960
2205
  * @param options - Hardware-specific overlay options
2206
+ *
961
2207
  * @returns Hardware overlay filter string or null if not supported
962
2208
  *
2209
+ * @example
2210
+ * ```typescript
2211
+ * const filter = hwPresets.overlay(100, 50);
2212
+ * ```
2213
+ *
2214
+ * @example
2215
+ * ```typescript
2216
+ * const filter = hwPresets.overlay(0, 0, { eof_action: 'pass' });
2217
+ * ```
2218
+ *
963
2219
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#overlay_005fcuda | FFmpeg overlay_cuda filter}
964
2220
  */
965
2221
  overlay(x = 0, y = 0, options) {
@@ -981,18 +2237,51 @@ export class HardwareFilterPresets extends FilterPresetBase {
981
2237
  *
982
2238
  * Direction values:
983
2239
  * - 0: 90 degrees counter-clockwise and vertical flip
984
- * - 1: 90 degrees clockwise
985
- * - 2: 90 degrees counter-clockwise
986
- * - 3: 90 degrees clockwise and vertical flip
2240
+ * - 1 / 'clock': 90 degrees clockwise
2241
+ * - 2 / 'cclock': 90 degrees counter-clockwise
2242
+ * - 3 / 'clock_flip': 90 degrees clockwise and vertical flip
2243
+ *
2244
+ * @param mode - Transpose mode (number or string)
987
2245
  *
988
- * @param dir - Transpose direction (default: 0)
989
2246
  * @returns Hardware transpose filter string or null if not supported
990
2247
  *
2248
+ * @example
2249
+ * ```typescript
2250
+ * const filter = hwPresets.transpose('clock');
2251
+ * ```
2252
+ *
2253
+ * @example
2254
+ * ```typescript
2255
+ * const filter = hwPresets.transpose(2);
2256
+ * ```
991
2257
  */
992
- transpose(dir = 0) {
2258
+ transpose(mode) {
993
2259
  if (!this.support.transpose) {
994
2260
  return null;
995
2261
  }
2262
+ // Convert string modes to numbers
2263
+ let dir;
2264
+ if (typeof mode === 'string') {
2265
+ switch (mode) {
2266
+ case 'clock':
2267
+ dir = 1;
2268
+ break;
2269
+ case 'cclock':
2270
+ dir = 2;
2271
+ break;
2272
+ case 'clock_flip':
2273
+ dir = 3;
2274
+ break;
2275
+ case 'cclock_flip':
2276
+ dir = 0;
2277
+ break;
2278
+ default:
2279
+ dir = 0;
2280
+ }
2281
+ }
2282
+ else {
2283
+ dir = mode;
2284
+ }
996
2285
  // Special handling for different hardware transpose implementations
997
2286
  let filterName;
998
2287
  if (this.deviceType === AV_HWDEVICE_TYPE_CUDA) {
@@ -1011,8 +2300,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
1011
2300
  * Used for HDR to SDR conversion with hardware acceleration.
1012
2301
  *
1013
2302
  * @param options - Tonemapping options (algorithm, parameters)
2303
+ *
1014
2304
  * @returns Hardware tonemap filter string or null if not supported
1015
2305
  *
2306
+ * @example
2307
+ * ```typescript
2308
+ * const filter = hwPresets.tonemap();
2309
+ * ```
2310
+ *
2311
+ * @example
2312
+ * ```typescript
2313
+ * const filter = hwPresets.tonemap({ tonemap: 'hable', desat: '0' });
2314
+ * ```
1016
2315
  */
1017
2316
  tonemap(options) {
1018
2317
  if (!this.support.tonemap) {
@@ -1040,8 +2339,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
1040
2339
  * - VideoToolbox: yadif_videotoolbox
1041
2340
  *
1042
2341
  * @param mode - Deinterlacing mode (optional)
2342
+ *
1043
2343
  * @returns Hardware deinterlace filter string or null if not supported
1044
2344
  *
2345
+ * @example
2346
+ * ```typescript
2347
+ * const filter = hwPresets.deinterlace();
2348
+ * ```
2349
+ *
2350
+ * @example
2351
+ * ```typescript
2352
+ * const filter = hwPresets.deinterlace('send_field');
2353
+ * ```
1045
2354
  */
1046
2355
  deinterlace(mode) {
1047
2356
  if (!this.support.deinterlace) {
@@ -1067,8 +2376,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
1067
2376
  * Currently only Vulkan supports hardware flip filters.
1068
2377
  *
1069
2378
  * @param direction - Flip direction ('h' for horizontal, 'v' for vertical)
2379
+ *
1070
2380
  * @returns Hardware flip filter string or null if not supported
1071
2381
  *
2382
+ * @example
2383
+ * ```typescript
2384
+ * const filter = hwPresets.flip('h');
2385
+ * ```
2386
+ *
2387
+ * @example
2388
+ * ```typescript
2389
+ * const filter = hwPresets.flip('v');
2390
+ * ```
1072
2391
  */
1073
2392
  flip(direction) {
1074
2393
  if (!this.support.flip) {
@@ -1089,8 +2408,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
1089
2408
  *
1090
2409
  * @param type - Blur type ('avg', 'gaussian', or 'box', default: 'avg')
1091
2410
  * @param radius - Blur radius (optional)
2411
+ *
1092
2412
  * @returns Hardware blur filter string or null if not supported
1093
2413
  *
2414
+ * @example
2415
+ * ```typescript
2416
+ * const filter = hwPresets.blur('gaussian', 5);
2417
+ * ```
2418
+ *
2419
+ * @example
2420
+ * ```typescript
2421
+ * const filter = hwPresets.blur('avg');
2422
+ * ```
1094
2423
  */
1095
2424
  blur(type = 'avg', radius) {
1096
2425
  if (!this.support.blur) {
@@ -1116,8 +2445,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
1116
2445
  * - CUDA: sharpen_npp (NPP-based)
1117
2446
  *
1118
2447
  * @param amount - Sharpening amount (optional)
2448
+ *
1119
2449
  * @returns Hardware sharpen filter string or null if not supported
1120
2450
  *
2451
+ * @example
2452
+ * ```typescript
2453
+ * const filter = hwPresets.sharpen(1.5);
2454
+ * ```
2455
+ *
2456
+ * @example
2457
+ * ```typescript
2458
+ * const filter = hwPresets.sharpen();
2459
+ * ```
1121
2460
  */
1122
2461
  sharpen(amount) {
1123
2462
  if (!this.support.sharpen) {
@@ -1141,8 +2480,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
1141
2480
  *
1142
2481
  * @param type - Stack type ('h' for horizontal, 'v' for vertical, 'x' for grid)
1143
2482
  * @param inputs - Number of inputs to stack (default: 2)
2483
+ *
1144
2484
  * @returns Hardware stack filter string or null if not supported
1145
2485
  *
2486
+ * @example
2487
+ * ```typescript
2488
+ * const filter = hwPresets.stack('h', 2);
2489
+ * ```
2490
+ *
2491
+ * @example
2492
+ * ```typescript
2493
+ * const filter = hwPresets.stack('x', 4);
2494
+ * ```
1146
2495
  */
1147
2496
  stack(type, inputs = 2) {
1148
2497
  if (!this.support.stack) {
@@ -1159,6 +2508,11 @@ export class HardwareFilterPresets extends FilterPresetBase {
1159
2508
  *
1160
2509
  * @returns Hardware upload filter string
1161
2510
  *
2511
+ * @example
2512
+ * ```typescript
2513
+ * const filter = hwPresets.hwupload();
2514
+ * ```
2515
+ *
1162
2516
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwupload | FFmpeg hwupload filter}
1163
2517
  */
1164
2518
  hwupload() {
@@ -1172,6 +2526,11 @@ export class HardwareFilterPresets extends FilterPresetBase {
1172
2526
  *
1173
2527
  * @returns Hardware download filter string
1174
2528
  *
2529
+ * @example
2530
+ * ```typescript
2531
+ * const filter = hwPresets.hwdownload();
2532
+ * ```
2533
+ *
1175
2534
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwdownload | FFmpeg hwdownload filter}
1176
2535
  */
1177
2536
  hwdownload() {
@@ -1181,8 +2540,19 @@ export class HardwareFilterPresets extends FilterPresetBase {
1181
2540
  * Creates a hwmap filter to map frames between hardware devices.
1182
2541
  *
1183
2542
  * @param derive - Device to derive from (optional)
2543
+ *
1184
2544
  * @returns Hardware map filter string
1185
2545
  *
2546
+ * @example
2547
+ * ```typescript
2548
+ * const filter = hwPresets.hwmap('cuda');
2549
+ * ```
2550
+ *
2551
+ * @example
2552
+ * ```typescript
2553
+ * const filter = hwPresets.hwmap();
2554
+ * ```
2555
+ *
1186
2556
  * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwmap | FFmpeg hwmap filter}
1187
2557
  */
1188
2558
  hwmap(derive) {