node-av 1.1.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 (166) hide show
  1. package/README.md +51 -59
  2. package/dist/api/bitstream-filter.d.ts +183 -123
  3. package/dist/api/bitstream-filter.js +185 -127
  4. package/dist/api/bitstream-filter.js.map +1 -1
  5. package/dist/api/decoder.d.ts +282 -130
  6. package/dist/api/decoder.js +290 -142
  7. package/dist/api/decoder.js.map +1 -1
  8. package/dist/api/encoder.d.ts +249 -160
  9. package/dist/api/encoder.js +276 -207
  10. package/dist/api/encoder.js.map +1 -1
  11. package/dist/api/filter-presets.d.ts +1944 -96
  12. package/dist/api/filter-presets.js +2059 -105
  13. package/dist/api/filter-presets.js.map +1 -1
  14. package/dist/api/filter.d.ts +264 -200
  15. package/dist/api/filter.js +269 -231
  16. package/dist/api/filter.js.map +1 -1
  17. package/dist/api/hardware.d.ts +246 -117
  18. package/dist/api/hardware.js +440 -217
  19. package/dist/api/hardware.js.map +1 -1
  20. package/dist/api/index.d.ts +3 -3
  21. package/dist/api/index.js +1 -1
  22. package/dist/api/index.js.map +1 -1
  23. package/dist/api/io-stream.d.ts +65 -55
  24. package/dist/api/io-stream.js +43 -40
  25. package/dist/api/io-stream.js.map +1 -1
  26. package/dist/api/media-input.d.ts +242 -139
  27. package/dist/api/media-input.js +205 -103
  28. package/dist/api/media-input.js.map +1 -1
  29. package/dist/api/media-output.d.ts +208 -126
  30. package/dist/api/media-output.js +212 -126
  31. package/dist/api/media-output.js.map +1 -1
  32. package/dist/api/pipeline.d.ts +361 -38
  33. package/dist/api/pipeline.js +255 -14
  34. package/dist/api/pipeline.js.map +1 -1
  35. package/dist/api/types.d.ts +26 -187
  36. package/dist/api/utilities/audio-sample.d.ts +0 -8
  37. package/dist/api/utilities/audio-sample.js +0 -8
  38. package/dist/api/utilities/audio-sample.js.map +1 -1
  39. package/dist/api/utilities/channel-layout.d.ts +0 -8
  40. package/dist/api/utilities/channel-layout.js +0 -8
  41. package/dist/api/utilities/channel-layout.js.map +1 -1
  42. package/dist/api/utilities/image.d.ts +0 -8
  43. package/dist/api/utilities/image.js +0 -8
  44. package/dist/api/utilities/image.js.map +1 -1
  45. package/dist/api/utilities/index.d.ts +3 -3
  46. package/dist/api/utilities/index.js +3 -3
  47. package/dist/api/utilities/index.js.map +1 -1
  48. package/dist/api/utilities/media-type.d.ts +1 -9
  49. package/dist/api/utilities/media-type.js +1 -9
  50. package/dist/api/utilities/media-type.js.map +1 -1
  51. package/dist/api/utilities/pixel-format.d.ts +1 -9
  52. package/dist/api/utilities/pixel-format.js +1 -9
  53. package/dist/api/utilities/pixel-format.js.map +1 -1
  54. package/dist/api/utilities/sample-format.d.ts +1 -9
  55. package/dist/api/utilities/sample-format.js +1 -9
  56. package/dist/api/utilities/sample-format.js.map +1 -1
  57. package/dist/api/utilities/streaming.d.ts +0 -8
  58. package/dist/api/utilities/streaming.js +0 -8
  59. package/dist/api/utilities/streaming.js.map +1 -1
  60. package/dist/api/utilities/timestamp.d.ts +0 -8
  61. package/dist/api/utilities/timestamp.js +0 -8
  62. package/dist/api/utilities/timestamp.js.map +1 -1
  63. package/dist/api/utils.d.ts +1 -2
  64. package/dist/api/utils.js +11 -0
  65. package/dist/api/utils.js.map +1 -1
  66. package/dist/constants/constants.d.ts +1 -1
  67. package/dist/constants/constants.js +2 -0
  68. package/dist/constants/constants.js.map +1 -1
  69. package/dist/lib/audio-fifo.d.ts +127 -170
  70. package/dist/lib/audio-fifo.js +130 -173
  71. package/dist/lib/audio-fifo.js.map +1 -1
  72. package/dist/lib/binding.d.ts +1 -0
  73. package/dist/lib/binding.js +7 -0
  74. package/dist/lib/binding.js.map +1 -1
  75. package/dist/lib/bitstream-filter-context.d.ts +139 -184
  76. package/dist/lib/bitstream-filter-context.js +139 -188
  77. package/dist/lib/bitstream-filter-context.js.map +1 -1
  78. package/dist/lib/bitstream-filter.d.ts +68 -54
  79. package/dist/lib/bitstream-filter.js +68 -54
  80. package/dist/lib/bitstream-filter.js.map +1 -1
  81. package/dist/lib/codec-context.d.ts +316 -380
  82. package/dist/lib/codec-context.js +316 -381
  83. package/dist/lib/codec-context.js.map +1 -1
  84. package/dist/lib/codec-parameters.d.ts +160 -170
  85. package/dist/lib/codec-parameters.js +162 -172
  86. package/dist/lib/codec-parameters.js.map +1 -1
  87. package/dist/lib/codec-parser.d.ts +91 -104
  88. package/dist/lib/codec-parser.js +92 -103
  89. package/dist/lib/codec-parser.js.map +1 -1
  90. package/dist/lib/codec.d.ts +266 -283
  91. package/dist/lib/codec.js +270 -287
  92. package/dist/lib/codec.js.map +1 -1
  93. package/dist/lib/dictionary.d.ts +149 -203
  94. package/dist/lib/dictionary.js +158 -212
  95. package/dist/lib/dictionary.js.map +1 -1
  96. package/dist/lib/error.d.ts +96 -130
  97. package/dist/lib/error.js +98 -128
  98. package/dist/lib/error.js.map +1 -1
  99. package/dist/lib/filter-context.d.ts +284 -218
  100. package/dist/lib/filter-context.js +290 -227
  101. package/dist/lib/filter-context.js.map +1 -1
  102. package/dist/lib/filter-graph.d.ts +251 -292
  103. package/dist/lib/filter-graph.js +253 -294
  104. package/dist/lib/filter-graph.js.map +1 -1
  105. package/dist/lib/filter-inout.d.ts +87 -95
  106. package/dist/lib/filter-inout.js +87 -95
  107. package/dist/lib/filter-inout.js.map +1 -1
  108. package/dist/lib/filter.d.ts +93 -111
  109. package/dist/lib/filter.js +93 -111
  110. package/dist/lib/filter.js.map +1 -1
  111. package/dist/lib/format-context.d.ts +320 -428
  112. package/dist/lib/format-context.js +313 -385
  113. package/dist/lib/format-context.js.map +1 -1
  114. package/dist/lib/frame.d.ts +262 -405
  115. package/dist/lib/frame.js +263 -408
  116. package/dist/lib/frame.js.map +1 -1
  117. package/dist/lib/hardware-device-context.d.ts +149 -203
  118. package/dist/lib/hardware-device-context.js +149 -203
  119. package/dist/lib/hardware-device-context.js.map +1 -1
  120. package/dist/lib/hardware-frames-context.d.ts +170 -180
  121. package/dist/lib/hardware-frames-context.js +171 -181
  122. package/dist/lib/hardware-frames-context.js.map +1 -1
  123. package/dist/lib/index.d.ts +3 -2
  124. package/dist/lib/index.js +3 -3
  125. package/dist/lib/index.js.map +1 -1
  126. package/dist/lib/input-format.d.ts +89 -117
  127. package/dist/lib/input-format.js +89 -117
  128. package/dist/lib/input-format.js.map +1 -1
  129. package/dist/lib/io-context.d.ts +209 -241
  130. package/dist/lib/io-context.js +220 -252
  131. package/dist/lib/io-context.js.map +1 -1
  132. package/dist/lib/log.d.ts +85 -119
  133. package/dist/lib/log.js +85 -122
  134. package/dist/lib/log.js.map +1 -1
  135. package/dist/lib/native-types.d.ts +118 -106
  136. package/dist/lib/native-types.js +0 -7
  137. package/dist/lib/native-types.js.map +1 -1
  138. package/dist/lib/option.d.ts +437 -218
  139. package/dist/lib/option.js +462 -226
  140. package/dist/lib/option.js.map +1 -1
  141. package/dist/lib/output-format.d.ts +77 -101
  142. package/dist/lib/output-format.js +77 -101
  143. package/dist/lib/output-format.js.map +1 -1
  144. package/dist/lib/packet.d.ts +172 -240
  145. package/dist/lib/packet.js +172 -241
  146. package/dist/lib/packet.js.map +1 -1
  147. package/dist/lib/rational.d.ts +0 -2
  148. package/dist/lib/rational.js +0 -2
  149. package/dist/lib/rational.js.map +1 -1
  150. package/dist/lib/software-resample-context.d.ts +241 -325
  151. package/dist/lib/software-resample-context.js +242 -326
  152. package/dist/lib/software-resample-context.js.map +1 -1
  153. package/dist/lib/software-scale-context.d.ts +129 -173
  154. package/dist/lib/software-scale-context.js +131 -175
  155. package/dist/lib/software-scale-context.js.map +1 -1
  156. package/dist/lib/stream.d.ts +87 -197
  157. package/dist/lib/stream.js +87 -197
  158. package/dist/lib/stream.js.map +1 -1
  159. package/dist/lib/utilities.d.ts +435 -181
  160. package/dist/lib/utilities.js +438 -182
  161. package/dist/lib/utilities.js.map +1 -1
  162. package/install/check.js +0 -1
  163. package/install/ffmpeg.js +0 -11
  164. package/package.json +25 -18
  165. package/release_notes.md +24 -59
  166. package/CHANGELOG.md +0 -8
@@ -1,25 +1,41 @@
1
- /**
2
- * FilterPresets - Pre-defined filter configurations
3
- *
4
- * Provides convenient filter string builders for common operations.
5
- * Includes both software and hardware-accelerated filter presets.
6
- *
7
- * Simplifies filter creation with type-safe parameter handling.
8
- * Supports platform-specific hardware acceleration capabilities.
9
- *
10
- * @module api/filter-presets
11
- */
12
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';
13
2
  import { Filter } from '../lib/filter.js';
3
+ import { HardwareDeviceContext } from '../lib/hardware-device-context.js';
14
4
  import { avGetPixFmtName, avGetSampleFmtName } from '../lib/utilities.js';
15
5
  /**
16
6
  * Base class for filter preset implementations.
17
- * Provides common filter building methods that can be overridden.
7
+ * Provides common filter building methods that can be overridden by hardware-specific implementations.
8
+ *
9
+ * This class defines the standard filter operations available in FFmpeg,
10
+ * with each method returning a filter string that can be used in a filter graph.
11
+ * Hardware-specific implementations may override these methods to use optimized
12
+ * hardware filters instead of software implementations.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * class CustomPresets extends FilterPresetBase {
17
+ * override scale(width: number, height: number): string | null {
18
+ * return `custom_scale=${width}:${height}`;
19
+ * }
20
+ * }
21
+ * ```
18
22
  */
19
23
  export class FilterPresetBase {
20
24
  /**
21
- * Scale video to specified dimensions.
25
+ * Creates a scale filter string.
26
+ *
27
+ * @param width - Target width in pixels
28
+ * @param height - Target height in pixels
29
+ * @param options - Additional scaling options (e.g., flags for algorithm)
22
30
  * @returns Filter string or null if not supported
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
+ *
38
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#scale | FFmpeg scale filter}
23
39
  */
24
40
  scale(width, height, options) {
25
41
  const flags = options?.flags;
@@ -27,21 +43,59 @@ export class FilterPresetBase {
27
43
  return flags ? `${base}:flags=${flags}` : base;
28
44
  }
29
45
  /**
30
- * Crop video to specified dimensions.
46
+ * Creates a crop filter string.
47
+ *
48
+ * @param width - Width of the cropped area
49
+ * @param height - Height of the cropped area
50
+ * @param x - X coordinate of top-left corner (default: 0)
51
+ * @param y - Y coordinate of top-left corner (default: 0)
52
+ * @returns Filter string or null if not supported
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
+ *
60
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#crop | FFmpeg crop filter}
31
61
  */
32
62
  crop(width, height, x = 0, y = 0) {
33
63
  return `crop=${width}:${height}:${x}:${y}`;
34
64
  }
35
65
  /**
36
- * Change frame rate.
66
+ * Creates an FPS filter string to change frame rate.
67
+ *
68
+ * @param fps - Target frames per second
69
+ * @returns Filter string or null if not supported
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * presets.fps(30) // Convert to 30 FPS
74
+ * presets.fps(23.976) // Film frame rate
75
+ * ```
76
+ *
77
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#fps | FFmpeg fps filter}
37
78
  */
38
79
  fps(fps) {
39
80
  return `fps=${fps}`;
40
81
  }
41
82
  /**
42
- * Convert pixel format.
43
- * Can accept a single format or an array of formats for fallback.
44
- * Multiple formats will create a chain: format=fmt1,format=fmt2,...
83
+ * Creates a format filter string to convert pixel format.
84
+ *
85
+ * @param pixelFormat - Target pixel format(s) - can be string, AVPixelFormat enum, or array
86
+ * @returns Filter string or null if not supported
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * // Single format
91
+ * presets.format('yuv420p');
92
+ * presets.format(AV_PIX_FMT_YUV420P);
93
+ *
94
+ * // Multiple formats (creates a chain)
95
+ * presets.format(['yuv420p', 'rgb24']);
96
+ * ```
97
+ *
98
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#format | FFmpeg format filter}
45
99
  */
46
100
  format(pixelFormat) {
47
101
  if (Array.isArray(pixelFormat)) {
@@ -56,31 +110,89 @@ export class FilterPresetBase {
56
110
  return `format=${formatName}`;
57
111
  }
58
112
  /**
59
- * Rotate video by angle.
113
+ * Creates a rotate filter string.
114
+ *
115
+ * @param angle - Rotation angle in degrees
116
+ * @returns Filter string or null if not supported
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * presets.rotate(90) // Rotate 90 degrees clockwise
121
+ * presets.rotate(-45) // Rotate 45 degrees counter-clockwise
122
+ * ```
123
+ *
124
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#rotate | FFmpeg rotate filter}
60
125
  */
61
126
  rotate(angle) {
62
127
  return `rotate=${angle}*PI/180`;
63
128
  }
64
129
  /**
65
- * Flip video horizontally.
130
+ * Creates a horizontal flip filter string.
131
+ *
132
+ * @returns Filter string or null if not supported
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * presets.hflip() // Mirror horizontally
137
+ * ```
138
+ *
139
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hflip | FFmpeg hflip filter}
66
140
  */
67
141
  hflip() {
68
142
  return 'hflip';
69
143
  }
70
144
  /**
71
- * Flip video vertically.
145
+ * Creates a vertical flip filter string.
146
+ *
147
+ * @returns Filter string or null if not supported
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * presets.vflip() // Flip upside down
152
+ * ```
153
+ *
154
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#vflip | FFmpeg vflip filter}
72
155
  */
73
156
  vflip() {
74
157
  return 'vflip';
75
158
  }
76
159
  /**
77
- * Apply fade effect.
160
+ * Creates a fade filter string for video.
161
+ *
162
+ * @param type - Fade type ('in' or 'out')
163
+ * @param start - Start time in seconds
164
+ * @param duration - Fade duration in seconds
165
+ * @returns Filter string or null if not supported
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
+ *
173
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#fade | FFmpeg fade filter}
78
174
  */
79
175
  fade(type, start, duration) {
80
176
  return `fade=t=${type}:st=${start}:d=${duration}`;
81
177
  }
82
178
  /**
83
- * Overlay one video on another.
179
+ * Creates an overlay filter string to composite two video streams.
180
+ *
181
+ * @param x - X position for overlay (default: 0)
182
+ * @param y - Y position for overlay (default: 0)
183
+ * @param options - Additional overlay options
184
+ * @returns Filter string or null if not supported
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * // Basic overlay at position
189
+ * presets.overlay(100, 50);
190
+ *
191
+ * // With additional options
192
+ * presets.overlay(0, 0, { format: 'yuv420' });
193
+ * ```
194
+ *
195
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#overlay | FFmpeg overlay filter}
84
196
  */
85
197
  overlay(x = 0, y = 0, options) {
86
198
  let filter = `overlay=${x}:${y}`;
@@ -92,13 +204,43 @@ export class FilterPresetBase {
92
204
  return filter;
93
205
  }
94
206
  /**
95
- * Adjust audio volume.
207
+ * Creates a volume filter string for audio.
208
+ *
209
+ * @param factor - Volume multiplication factor (1.0 = unchanged, 2.0 = double)
210
+ * @returns Filter string or null if not supported
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
+ *
218
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#volume | FFmpeg volume filter}
96
219
  */
97
220
  volume(factor) {
98
221
  return `volume=${factor}`;
99
222
  }
100
223
  /**
101
- * Convert audio sample format.
224
+ * Creates an audio format filter string.
225
+ *
226
+ * @param sampleFormat - Target sample format (e.g., 's16', 'fltp')
227
+ * @param sampleRate - Target sample rate in Hz (optional)
228
+ * @param channelLayout - Target channel layout (optional)
229
+ * @returns Filter string or null if not supported
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * // Change sample format only
234
+ * presets.aformat('s16');
235
+ *
236
+ * // Change format and sample rate
237
+ * presets.aformat('fltp', 48000);
238
+ *
239
+ * // Full conversion
240
+ * presets.aformat('s16', 44100, 'stereo');
241
+ * ```
242
+ *
243
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#aformat | FFmpeg aformat filter}
102
244
  */
103
245
  aformat(sampleFormat, sampleRate, channelLayout) {
104
246
  const formatName = typeof sampleFormat === 'string' ? sampleFormat : (avGetSampleFmtName(sampleFormat) ?? 's16');
@@ -110,33 +252,453 @@ export class FilterPresetBase {
110
252
  return filter;
111
253
  }
112
254
  /**
113
- * Change audio tempo without changing pitch.
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
+ }
277
+ /**
278
+ * Creates an atempo filter string to change audio playback speed.
279
+ * Factor must be between 0.5 and 2.0. For larger changes, chain multiple atempo filters.
280
+ *
281
+ * @param factor - Tempo factor (0.5 = half speed, 2.0 = double speed)
282
+ * @returns Filter string or null if not supported
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
+ *
290
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#atempo | FFmpeg atempo filter}
114
291
  */
115
292
  atempo(factor) {
116
293
  return `atempo=${factor}`;
117
294
  }
118
295
  /**
119
- * Apply audio fade.
296
+ * Creates an audio fade filter string.
297
+ *
298
+ * @param type - Fade type ('in' or 'out')
299
+ * @param start - Start time in seconds
300
+ * @param duration - Fade duration in seconds
301
+ * @returns Filter string or null if not supported
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
+ *
309
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#afade | FFmpeg afade filter}
120
310
  */
121
311
  afade(type, start, duration) {
122
312
  return `afade=t=${type}:st=${start}:d=${duration}`;
123
313
  }
124
314
  /**
125
- * Mix multiple audio streams.
315
+ * Creates an amix filter string to mix multiple audio streams.
316
+ *
317
+ * @param inputs - Number of input streams to mix (default: 2)
318
+ * @param duration - How to determine output duration (default: 'longest')
319
+ * @returns Filter string or null if not supported
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
+ *
327
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#amix | FFmpeg amix filter}
126
328
  */
127
329
  amix(inputs = 2, duration = 'longest') {
128
330
  return `amix=inputs=${inputs}:duration=${duration}`;
129
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
+ }
130
675
  }
131
676
  /**
132
677
  * Filter chain builder for composing multiple filters.
133
- * Allows fluent API for building complex filter graphs.
678
+ * Allows fluent API for building complex filter graphs by chaining filter operations.
679
+ *
680
+ * @example
681
+ * ```typescript
682
+ * const chain = new FilterChain()
683
+ * .add('scale=1920:1080')
684
+ * .add('fps=30')
685
+ * .custom('rotate=45*PI/180')
686
+ * .build();
687
+ * // Result: "scale=1920:1080,fps=30,rotate=45*PI/180"
688
+ * ```
134
689
  */
135
690
  export class FilterChain {
136
691
  filters = [];
137
692
  /**
138
- * Add a filter to the chain.
139
- * @param filter - Filter string or null/undefined (will be skipped)
693
+ * Adds a filter to the chain.
694
+ *
695
+ * @param filter - Filter string to add (ignored if null/undefined)
696
+ * @returns This instance for chaining
697
+ *
698
+ * @example
699
+ * ```typescript
700
+ * chain.add('scale=1920:1080')
701
+ * ```
140
702
  */
141
703
  add(filter) {
142
704
  if (filter) {
@@ -145,20 +707,42 @@ export class FilterChain {
145
707
  return this;
146
708
  }
147
709
  /**
148
- * Add a custom filter string.
710
+ * Adds a custom filter string to the chain.
711
+ *
712
+ * @param filter - Custom filter string
713
+ * @returns This instance for chaining
714
+ *
715
+ * @example
716
+ * ```typescript
717
+ * chain.custom('myfilter=param1:param2')
718
+ * ```
149
719
  */
150
720
  custom(filter) {
151
721
  return this.add(filter);
152
722
  }
153
723
  /**
154
- * Build the filter chain string.
724
+ * Builds the final filter string.
725
+ *
155
726
  * @param separator - Separator between filters (default: ',')
727
+ * @returns Combined filter string
728
+ *
729
+ * @example
730
+ * ```typescript
731
+ * const filterString = chain.build() // "scale=1920:1080,fps=30"
732
+ * ```
156
733
  */
157
734
  build(separator = ',') {
158
735
  return this.filters.join(separator);
159
736
  }
160
737
  /**
161
- * Get the filter array.
738
+ * Returns the filters as an array.
739
+ *
740
+ * @returns Array of filter strings
741
+ *
742
+ * @example
743
+ * ```typescript
744
+ * const filters = chain.toArray() // ["scale=1920:1080", "fps=30"]
745
+ * ```
162
746
  */
163
747
  toArray() {
164
748
  return [...this.filters];
@@ -166,75 +750,792 @@ export class FilterChain {
166
750
  }
167
751
  /**
168
752
  * Base chain builder with common filter methods.
753
+ * Provides a fluent API for building filter chains using preset methods.
754
+ *
169
755
  * @template T The preset type this builder uses
756
+ *
757
+ * @example
758
+ * ```typescript
759
+ * const chain = new ChainBuilderBase(presets)
760
+ * .scale(1920, 1080)
761
+ * .fps(30)
762
+ * .fade('in', 0, 2)
763
+ * .build();
764
+ * ```
170
765
  */
171
766
  export class ChainBuilderBase extends FilterChain {
172
767
  presets;
768
+ /**
769
+ * @param presets - The filter presets to use
770
+ * @internal
771
+ */
173
772
  constructor(presets) {
174
773
  super();
175
774
  this.presets = presets;
176
775
  }
776
+ /**
777
+ * Adds a scale filter to the chain.
778
+ *
779
+ * @param width - Target width
780
+ * @param height - Target height
781
+ * @param options - Additional scaling options
782
+ *
783
+ * @returns This instance for chaining
784
+ *
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
+ */
177
801
  scale(width, height, options) {
178
802
  return this.add(this.presets.scale(width, height, options));
179
803
  }
804
+ /**
805
+ * Adds a crop filter to the chain.
806
+ *
807
+ * @param width - Crop width
808
+ * @param height - Crop height
809
+ * @param x - X position (default: 0)
810
+ * @param y - Y position (default: 0)
811
+ *
812
+ * @returns This instance for chaining
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
+ *
828
+ * @see {@link FilterPresetBase.crop}
829
+ */
180
830
  crop(width, height, x = 0, y = 0) {
181
831
  return this.add(this.presets.crop(width, height, x, y));
182
832
  }
833
+ /**
834
+ * Adds an FPS filter to the chain.
835
+ *
836
+ * @param fps - Target frame rate
837
+ *
838
+ * @returns This instance for chaining
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
+ *
854
+ * @see {@link FilterPresetBase.fps}
855
+ */
183
856
  fps(fps) {
184
857
  return this.add(this.presets.fps(fps));
185
858
  }
859
+ /**
860
+ * Adds a format filter to the chain.
861
+ *
862
+ * @param pixelFormat - Target pixel format(s)
863
+ *
864
+ * @returns This instance for chaining
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
+ *
880
+ * @see {@link FilterPresetBase.format}
881
+ */
186
882
  format(pixelFormat) {
187
883
  return this.add(this.presets.format(pixelFormat));
188
884
  }
885
+ /**
886
+ * Adds a rotate filter to the chain.
887
+ *
888
+ * @param angle - Rotation angle in degrees
889
+ *
890
+ * @returns This instance for chaining
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
+ *
906
+ * @see {@link FilterPresetBase.rotate}
907
+ */
189
908
  rotate(angle) {
190
909
  return this.add(this.presets.rotate(angle));
191
910
  }
911
+ /**
912
+ * Adds a horizontal flip filter to the chain.
913
+ *
914
+ * @returns This instance for chaining
915
+ *
916
+ * @example
917
+ * ```typescript
918
+ * const chain = FilterPresets.chain()
919
+ * .hflip()
920
+ * .build();
921
+ * ```
922
+ *
923
+ * @see {@link FilterPresetBase.hflip}
924
+ */
192
925
  hflip() {
193
926
  return this.add(this.presets.hflip());
194
927
  }
928
+ /**
929
+ * Adds a vertical flip filter to the chain.
930
+ *
931
+ * @returns This instance for chaining
932
+ *
933
+ * @example
934
+ * ```typescript
935
+ * const chain = FilterPresets.chain()
936
+ * .vflip()
937
+ * .build();
938
+ * ```
939
+ *
940
+ * @see {@link FilterPresetBase.vflip}
941
+ */
195
942
  vflip() {
196
943
  return this.add(this.presets.vflip());
197
944
  }
945
+ /**
946
+ * Adds a fade filter to the chain.
947
+ *
948
+ * @param type - Fade type ('in' or 'out')
949
+ * @param start - Start time in seconds
950
+ * @param duration - Fade duration in seconds
951
+ *
952
+ * @returns This instance for chaining
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
+ *
968
+ * @see {@link FilterPresetBase.fade}
969
+ */
198
970
  fade(type, start, duration) {
199
971
  return this.add(this.presets.fade(type, start, duration));
200
972
  }
973
+ /**
974
+ * Adds an overlay filter to the chain.
975
+ *
976
+ * @param x - X position (default: 0)
977
+ * @param y - Y position (default: 0)
978
+ * @param options - Additional overlay options
979
+ *
980
+ * @returns This instance for chaining
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
+ *
996
+ * @see {@link FilterPresetBase.overlay}
997
+ */
201
998
  overlay(x = 0, y = 0, options) {
202
999
  return this.add(this.presets.overlay(x, y, options));
203
1000
  }
1001
+ /**
1002
+ * Adds a volume filter to the chain.
1003
+ *
1004
+ * @param factor - Volume factor
1005
+ *
1006
+ * @returns This instance for chaining
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
+ *
1022
+ * @see {@link FilterPresetBase.volume}
1023
+ */
204
1024
  volume(factor) {
205
1025
  return this.add(this.presets.volume(factor));
206
1026
  }
1027
+ /**
1028
+ * Adds an audio format filter to the chain.
1029
+ *
1030
+ * @param sampleFormat - Target sample format
1031
+ * @param sampleRate - Target sample rate (optional)
1032
+ * @param channelLayout - Target channel layout (optional)
1033
+ *
1034
+ * @returns This instance for chaining
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
+ *
1050
+ * @see {@link FilterPresetBase.aformat}
1051
+ */
207
1052
  aformat(sampleFormat, sampleRate, channelLayout) {
208
1053
  return this.add(this.presets.aformat(sampleFormat, sampleRate, channelLayout));
209
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
+ }
1082
+ /**
1083
+ * Adds an atempo filter to the chain.
1084
+ *
1085
+ * @param factor - Tempo factor (0.5 to 2.0)
1086
+ *
1087
+ * @returns This instance for chaining
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
+ *
1103
+ * @see {@link FilterPresetBase.atempo}
1104
+ */
210
1105
  atempo(factor) {
211
1106
  return this.add(this.presets.atempo(factor));
212
1107
  }
1108
+ /**
1109
+ * Adds an audio fade filter to the chain.
1110
+ *
1111
+ * @param type - Fade type ('in' or 'out')
1112
+ * @param start - Start time in seconds
1113
+ * @param duration - Fade duration in seconds
1114
+ *
1115
+ * @returns This instance for chaining
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
+ *
1131
+ * @see {@link FilterPresetBase.afade}
1132
+ */
213
1133
  afade(type, start, duration) {
214
1134
  return this.add(this.presets.afade(type, start, duration));
215
1135
  }
1136
+ /**
1137
+ * Adds an amix filter to the chain.
1138
+ *
1139
+ * @param inputs - Number of inputs (default: 2)
1140
+ * @param duration - Duration mode (default: 'longest')
1141
+ *
1142
+ * @returns This instance for chaining
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
+ *
1158
+ * @see {@link FilterPresetBase.amix}
1159
+ */
216
1160
  amix(inputs = 2, duration = 'longest') {
217
1161
  return this.add(this.presets.amix(inputs, duration));
218
1162
  }
219
- // Hardware-specific methods (only available if presets support them)
220
- transpose(dir = 0) {
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
+ }
1433
+ /**
1434
+ * Adds a transpose filter to the chain (hardware-specific).
1435
+ * Only available for hardware presets that support transpose
1436
+ *
1437
+ * @param mode - Transpose mode (number or string)
1438
+ *
1439
+ * @returns This instance for chaining
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
+ * ```
1454
+ */
1455
+ transpose(mode = 0) {
221
1456
  if ('transpose' in this.presets) {
222
- return this.add(this.presets.transpose(dir));
1457
+ return this.add(this.presets.transpose(mode));
223
1458
  }
224
1459
  return this.add(null);
225
1460
  }
1461
+ /**
1462
+ * Adds a tonemap filter to the chain (hardware-specific).
1463
+ * Only available for hardware presets that support tonemapping
1464
+ *
1465
+ * @param options - Tonemapping options
1466
+ *
1467
+ * @returns This instance for chaining
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
+ * ```
1482
+ */
226
1483
  tonemap(options) {
227
1484
  if ('tonemap' in this.presets) {
228
1485
  return this.add(this.presets.tonemap(options));
229
1486
  }
230
1487
  return this.add(null);
231
1488
  }
1489
+ /**
1490
+ * Adds a deinterlace filter to the chain (hardware-specific).
1491
+ * Only available for hardware presets that support deinterlacing
1492
+ *
1493
+ * @param mode - Deinterlace mode (optional)
1494
+ *
1495
+ * @returns This instance for chaining
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
+ * ```
1510
+ */
232
1511
  deinterlace(mode) {
233
1512
  if ('deinterlace' in this.presets) {
234
1513
  return this.add(this.presets.deinterlace(mode));
235
1514
  }
236
1515
  return this.add(null);
237
1516
  }
1517
+ /**
1518
+ * Adds a flip filter to the chain (hardware-specific).
1519
+ * Falls back to hflip/vflip if hardware flip not available
1520
+ *
1521
+ * @param direction - Flip direction ('h' or 'v')
1522
+ *
1523
+ * @returns This instance for chaining
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
+ * ```
1538
+ */
238
1539
  flip(direction) {
239
1540
  if ('flip' in this.presets) {
240
1541
  return this.add(this.presets.flip(direction));
@@ -242,36 +1543,151 @@ export class ChainBuilderBase extends FilterChain {
242
1543
  // Fallback to hflip/vflip
243
1544
  return direction === 'h' ? this.hflip() : this.vflip();
244
1545
  }
1546
+ /**
1547
+ * Adds a blur filter to the chain (hardware-specific).
1548
+ * Only available for hardware presets that support blur
1549
+ *
1550
+ * @param type - Blur type (default: 'avg')
1551
+ * @param radius - Blur radius (optional)
1552
+ *
1553
+ * @returns This instance for chaining
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
+ * ```
1568
+ */
245
1569
  blur(type = 'avg', radius) {
246
1570
  if ('blur' in this.presets) {
247
1571
  return this.add(this.presets.blur(type, radius));
248
1572
  }
249
1573
  return this.add(null);
250
1574
  }
1575
+ /**
1576
+ * Adds a sharpen filter to the chain (hardware-specific).
1577
+ * Only available for hardware presets that support sharpening
1578
+ *
1579
+ * @param amount - Sharpen amount (optional)
1580
+ *
1581
+ * @returns This instance for chaining
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
+ * ```
1596
+ */
251
1597
  sharpen(amount) {
252
1598
  if ('sharpen' in this.presets) {
253
1599
  return this.add(this.presets.sharpen(amount));
254
1600
  }
255
1601
  return this.add(null);
256
1602
  }
1603
+ /**
1604
+ * Adds a stack filter to the chain (hardware-specific).
1605
+ * Only available for hardware presets that support stacking
1606
+ *
1607
+ * @param type - Stack type ('h' for horizontal, 'v' for vertical, 'x' for grid)
1608
+ * @param inputs - Number of inputs (default: 2)
1609
+ *
1610
+ * @returns This instance for chaining
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
+ * ```
1625
+ */
257
1626
  stack(type, inputs = 2) {
258
1627
  if ('stack' in this.presets) {
259
1628
  return this.add(this.presets.stack(type, inputs));
260
1629
  }
261
1630
  return this.add(null);
262
1631
  }
1632
+ /**
1633
+ * Adds a hwupload filter to upload frames to hardware.
1634
+ *
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
+ * ```
1644
+ */
263
1645
  hwupload() {
264
1646
  if ('hwupload' in this.presets) {
265
1647
  return this.add(this.presets.hwupload());
266
1648
  }
267
1649
  return this.add('hwupload');
268
1650
  }
1651
+ /**
1652
+ * Adds a hwdownload filter to download frames from hardware.
1653
+ *
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
+ * ```
1663
+ */
269
1664
  hwdownload() {
270
1665
  if ('hwdownload' in this.presets) {
271
1666
  return this.add(this.presets.hwdownload());
272
1667
  }
273
1668
  return this.add('hwdownload');
274
1669
  }
1670
+ /**
1671
+ * Adds a hwmap filter to map frames between hardware devices.
1672
+ *
1673
+ * @param derive - Device to derive from (optional)
1674
+ *
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
+ * ```
1690
+ */
275
1691
  hwmap(derive) {
276
1692
  if ('hwmap' in this.presets) {
277
1693
  return this.add(this.presets.hwmap(derive));
@@ -281,91 +1697,368 @@ export class ChainBuilderBase extends FilterChain {
281
1697
  }
282
1698
  /**
283
1699
  * Fluent filter chain builder with preset methods.
1700
+ * Provides a convenient API for building filter chains using standard presets.
1701
+ *
1702
+ * @example
1703
+ * ```typescript
1704
+ * const filter = FilterPresets.chain()
1705
+ * .scale(1920, 1080)
1706
+ * .fps(30)
1707
+ * .fade('in', 0, 2)
1708
+ * .format('yuv420p')
1709
+ * .build();
1710
+ * ```
284
1711
  */
285
1712
  export class FilterChainBuilder extends ChainBuilderBase {
286
1713
  }
287
1714
  /**
288
- * Common filter presets for convenience.
289
- *
290
- * Provides pre-defined filter strings for common operations.
291
- * Can be used with Filter.create() for quick setup.
1715
+ * Standard filter presets for software filtering.
1716
+ * Provides static methods for creating common filter strings and
1717
+ * a chain builder for composing complex filter graphs.
292
1718
  *
293
1719
  * @example
294
1720
  * ```typescript
295
- * const filter = await Filter.create(
296
- * FilterPresets.scale(1280, 720),
297
- * config
298
- * );
1721
+ * // Static methods for individual filters
1722
+ * const scaleFilter = FilterPresets.scale(1920, 1080);
1723
+ * const fpsFilter = FilterPresets.fps(30);
299
1724
  *
300
- * // Using chain builder
1725
+ * // Chain builder for complex graphs
301
1726
  * const chain = FilterPresets.chain()
302
1727
  * .scale(1920, 1080)
303
- * .format('yuv420p')
304
- * .custom('unsharp=5:5:1.0')
1728
+ * .fps(30)
1729
+ * .fade('in', 0, 2)
305
1730
  * .build();
306
1731
  * ```
307
1732
  */
308
1733
  export class FilterPresets extends FilterPresetBase {
309
1734
  static instance = new FilterPresets();
310
1735
  /**
311
- * Create a new filter chain builder.
1736
+ * Creates a new filter chain builder.
1737
+ *
1738
+ * @returns A new FilterChainBuilder instance
1739
+ *
1740
+ * @example
1741
+ * ```typescript
1742
+ * const filter = FilterPresets.chain()
1743
+ * .scale(1280, 720)
1744
+ * .fps(30)
1745
+ * .build();
1746
+ * ```
312
1747
  */
313
1748
  static chain() {
314
1749
  return new FilterChainBuilder(FilterPresets.instance);
315
1750
  }
316
- // Static methods that delegate to instance
1751
+ /**
1752
+ * Creates a scale filter string.
1753
+ *
1754
+ * @param width - Target width
1755
+ * @param height - Target height
1756
+ * @param flags - Scaling algorithm flags (optional)
1757
+ *
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
+ * ```
1769
+ */
317
1770
  static scale(width, height, flags) {
318
1771
  const result = FilterPresets.instance.scale(width, height, { flags });
319
1772
  return result ?? '';
320
1773
  }
1774
+ /**
1775
+ * Creates a crop filter string.
1776
+ *
1777
+ * @param width - Crop width
1778
+ * @param height - Crop height
1779
+ * @param x - X position (default: 0)
1780
+ * @param y - Y position (default: 0)
1781
+ *
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
+ * ```
1793
+ */
321
1794
  static crop(width, height, x = 0, y = 0) {
322
1795
  const result = FilterPresets.instance.crop(width, height, x, y);
323
1796
  return result ?? '';
324
1797
  }
1798
+ /**
1799
+ * Creates an FPS filter string.
1800
+ *
1801
+ * @param fps - Target frame rate
1802
+ *
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
+ * ```
1814
+ */
325
1815
  static fps(fps) {
326
1816
  const result = FilterPresets.instance.fps(fps);
327
1817
  return result ?? '';
328
1818
  }
1819
+ /**
1820
+ * Creates a format filter string.
1821
+ *
1822
+ * @param pixelFormat - Target pixel format(s)
1823
+ *
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
+ * ```
1835
+ */
329
1836
  static format(pixelFormat) {
330
1837
  const result = FilterPresets.instance.format(pixelFormat);
331
1838
  return result ?? '';
332
1839
  }
1840
+ /**
1841
+ * Creates a rotate filter string.
1842
+ *
1843
+ * @param angle - Rotation angle in degrees
1844
+ *
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
+ * ```
1856
+ */
333
1857
  static rotate(angle) {
334
1858
  const result = FilterPresets.instance.rotate(angle);
335
1859
  return result ?? '';
336
1860
  }
1861
+ /**
1862
+ * Creates a horizontal flip filter string.
1863
+ *
1864
+ * @returns Horizontal flip filter string
1865
+ *
1866
+ * @example
1867
+ * ```typescript
1868
+ * const filter = FilterPresets.hflip();
1869
+ * ```
1870
+ */
337
1871
  static hflip() {
338
1872
  const result = FilterPresets.instance.hflip();
339
1873
  return result ?? '';
340
1874
  }
1875
+ /**
1876
+ * Creates a vertical flip filter string.
1877
+ *
1878
+ * @returns Vertical flip filter string
1879
+ *
1880
+ * @example
1881
+ * ```typescript
1882
+ * const filter = FilterPresets.vflip();
1883
+ * ```
1884
+ */
341
1885
  static vflip() {
342
1886
  const result = FilterPresets.instance.vflip();
343
1887
  return result ?? '';
344
1888
  }
1889
+ /**
1890
+ * Creates a fade filter string.
1891
+ *
1892
+ * @param type - Fade type ('in' or 'out')
1893
+ * @param start - Start time in seconds
1894
+ * @param duration - Fade duration in seconds
1895
+ *
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
+ * ```
1907
+ */
345
1908
  static fade(type, start, duration) {
346
1909
  const result = FilterPresets.instance.fade(type, start, duration);
347
1910
  return result ?? '';
348
1911
  }
1912
+ /**
1913
+ * Creates an overlay filter string.
1914
+ *
1915
+ * @param x - X position (default: 0)
1916
+ * @param y - Y position (default: 0)
1917
+ *
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
+ * ```
1929
+ */
349
1930
  static overlay(x = 0, y = 0) {
350
1931
  const result = FilterPresets.instance.overlay(x, y);
351
1932
  return result ?? '';
352
1933
  }
1934
+ /**
1935
+ * Creates a volume filter string.
1936
+ *
1937
+ * @param factor - Volume multiplication factor
1938
+ *
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
+ * ```
1950
+ */
353
1951
  static volume(factor) {
354
1952
  const result = FilterPresets.instance.volume(factor);
355
1953
  return result ?? '';
356
1954
  }
1955
+ /**
1956
+ * Creates an audio format filter string.
1957
+ *
1958
+ * @param sampleFormat - Target sample format
1959
+ * @param sampleRate - Target sample rate (optional)
1960
+ * @param channelLayout - Target channel layout (optional)
1961
+ *
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
+ * ```
1973
+ */
357
1974
  static aformat(sampleFormat, sampleRate, channelLayout) {
358
1975
  const result = FilterPresets.instance.aformat(sampleFormat, sampleRate, channelLayout);
359
1976
  return result ?? '';
360
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
+ }
2000
+ /**
2001
+ * Creates an atempo filter string.
2002
+ *
2003
+ * @param factor - Tempo factor (0.5 to 2.0)
2004
+ *
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
+ * ```
2016
+ */
361
2017
  static atempo(factor) {
362
2018
  const result = FilterPresets.instance.atempo(factor);
363
2019
  return result ?? '';
364
2020
  }
2021
+ /**
2022
+ * Creates an audio fade filter string.
2023
+ *
2024
+ * @param type - Fade type ('in' or 'out')
2025
+ * @param start - Start time in seconds
2026
+ * @param duration - Fade duration in seconds
2027
+ *
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
+ * ```
2039
+ */
365
2040
  static afade(type, start, duration) {
366
2041
  const result = FilterPresets.instance.afade(type, start, duration);
367
2042
  return result ?? '';
368
2043
  }
2044
+ /**
2045
+ * Creates an amix filter string.
2046
+ *
2047
+ * @param inputs - Number of inputs (default: 2)
2048
+ * @param duration - Duration mode (default: 'longest')
2049
+ *
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
+ * ```
2061
+ */
369
2062
  static amix(inputs = 2, duration = 'longest') {
370
2063
  const result = FilterPresets.instance.amix(inputs, duration);
371
2064
  return result ?? '';
@@ -373,47 +2066,54 @@ export class FilterPresets extends FilterPresetBase {
373
2066
  }
374
2067
  /**
375
2068
  * Hardware-accelerated filter presets.
376
- *
377
- * Provides hardware-specific filter strings for accelerated processing.
378
- * Created and managed by HardwareContext for type-safe hardware operations.
2069
+ * Provides optimized filter implementations for specific hardware types,
2070
+ * with automatic fallback when operations aren't supported.
379
2071
  *
380
2072
  * @example
381
2073
  * ```typescript
382
- * const hw = await HardwareContext.auto();
383
- * if (hw) {
384
- * // Get hardware-specific scale filter (returns null if unsupported)
385
- * const scaleFilter = hw.filterPresets.scale(1920, 1080);
2074
+ * // Create hardware presets for CUDA
2075
+ * const hw = new HardwareFilterPresets(AV_HWDEVICE_TYPE_CUDA);
386
2076
  *
387
- * // Build a filter chain (unsupported filters are skipped)
388
- * const chain = hw.filterPresets.chain()
389
- * .hwupload()
390
- * .scale(1920, 1080)
391
- * .tonemap() // Skipped if not supported
392
- * .custom('unsharp=5:5:1.0')
393
- * .hwdownload()
394
- * .build();
2077
+ * // Check capabilities
2078
+ * if (hw.support.scale) {
2079
+ * const scaleFilter = hw.scale(1920, 1080);
395
2080
  * }
2081
+ *
2082
+ * // Use chain builder
2083
+ * const chain = hw.chain()
2084
+ * .hwupload()
2085
+ * .scale(1920, 1080)
2086
+ * .tonemap()
2087
+ * .hwdownload()
2088
+ * .build();
396
2089
  * ```
397
2090
  */
398
2091
  export class HardwareFilterPresets extends FilterPresetBase {
399
2092
  deviceType;
400
- deviceName;
2093
+ deviceTypeName;
401
2094
  support;
402
2095
  /**
403
- * Create hardware filter presets for a specific device type.
404
- * @internal Used by HardwareContext
2096
+ * @param deviceType - Hardware device type enum
2097
+ * @param deviceTypeName - Optional hardware device type name (e.g., 'cuda', 'vaapi')
405
2098
  */
406
- constructor(deviceType, deviceName = null) {
2099
+ constructor(deviceType, deviceTypeName) {
407
2100
  super();
408
2101
  this.deviceType = deviceType;
409
- this.deviceName = deviceName ?? 'unknown';
2102
+ this.deviceTypeName = deviceTypeName ?? HardwareDeviceContext.getTypeName(deviceType);
410
2103
  this.support = this.getSupport();
411
2104
  }
412
2105
  /**
413
- * Check if a filter name is a hardware-accelerated filter.
414
- * Uses FFmpeg's AVFILTER_FLAG_HWDEVICE flag to determine if a filter is hardware-accelerated.
415
- * @param filterName - The filter name to check
416
- * @returns True if it's a hardware filter, false otherwise
2106
+ * Checks if a filter is hardware-accelerated.
2107
+ *
2108
+ * @param filterName - Name of the filter to check
2109
+ * @returns True if the filter uses hardware acceleration
2110
+ *
2111
+ * @example
2112
+ * ```typescript
2113
+ * if (HardwareFilterPresets.isHardwareFilter('scale_cuda')) {
2114
+ * console.log('Hardware accelerated scaling');
2115
+ * }
2116
+ * ```
417
2117
  */
418
2118
  static isHardwareFilter(filterName) {
419
2119
  const filter = Filter.getByName(filterName);
@@ -424,14 +2124,49 @@ export class HardwareFilterPresets extends FilterPresetBase {
424
2124
  return (filter.flags & AVFILTER_FLAG_HWDEVICE) !== 0;
425
2125
  }
426
2126
  /**
427
- * Create a new hardware filter chain builder.
2127
+ * Creates a hardware filter chain builder.
2128
+ *
2129
+ * @returns A new HardwareFilterChainBuilder instance
2130
+ *
2131
+ * @example
2132
+ * ```typescript
2133
+ * const filter = hw.chain()
2134
+ * .hwupload()
2135
+ * .scale(1920, 1080)
2136
+ * .hwdownload()
2137
+ * .build();
2138
+ * ```
428
2139
  */
429
2140
  chain() {
430
2141
  return new HardwareFilterChainBuilder(this);
431
2142
  }
432
2143
  /**
433
- * Hardware-accelerated scale filter.
434
- * @returns Filter string or null if not supported
2144
+ * Creates a hardware-accelerated scale filter.
2145
+ *
2146
+ * Different hardware types use different scale filters:
2147
+ * - CUDA: scale_cuda or scale_npp (with npp option)
2148
+ * - VAAPI: scale_vaapi
2149
+ * - QSV: scale_qsv
2150
+ * - VideoToolbox: scale_vt
2151
+ * - RKMPP: scale_rkrga
2152
+ *
2153
+ * @param width - Target width
2154
+ * @param height - Target height
2155
+ * @param options - Hardware-specific scaling options
2156
+ *
2157
+ * @returns Hardware scale filter string or null if not supported
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
+ * ```
2168
+ *
2169
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#scale_005fcuda | FFmpeg scale_cuda filter}
435
2170
  */
436
2171
  scale(width, height, options) {
437
2172
  if (!this.support.scale) {
@@ -449,7 +2184,7 @@ export class HardwareFilterPresets extends FilterPresetBase {
449
2184
  filterName = 'scale_vt'; // VideoToolbox uses scale_vt
450
2185
  }
451
2186
  else {
452
- filterName = `scale_${this.deviceName}`;
2187
+ filterName = `scale_${this.deviceTypeName}`;
453
2188
  }
454
2189
  let filter = `${filterName}=${width}:${height}`;
455
2190
  if (options) {
@@ -463,15 +2198,32 @@ export class HardwareFilterPresets extends FilterPresetBase {
463
2198
  return filter;
464
2199
  }
465
2200
  /**
466
- * Hardware-accelerated overlay filter.
467
- * @returns Filter string or null if not supported
2201
+ * Creates a hardware-accelerated overlay filter.
2202
+ *
2203
+ * @param x - X position (default: 0)
2204
+ * @param y - Y position (default: 0)
2205
+ * @param options - Hardware-specific overlay options
2206
+ *
2207
+ * @returns Hardware overlay filter string or null if not supported
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
+ *
2219
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#overlay_005fcuda | FFmpeg overlay_cuda filter}
468
2220
  */
469
2221
  overlay(x = 0, y = 0, options) {
470
2222
  if (!this.support.overlay) {
471
2223
  return null;
472
2224
  }
473
2225
  // Special handling for RKMPP which uses RGA
474
- const filterName = this.deviceType === AV_HWDEVICE_TYPE_RKMPP ? 'overlay_rkrga' : `overlay_${this.deviceName}`;
2226
+ const filterName = this.deviceType === AV_HWDEVICE_TYPE_RKMPP ? 'overlay_rkrga' : `overlay_${this.deviceTypeName}`;
475
2227
  let filter = `${filterName}=${x}:${y}`;
476
2228
  if (options) {
477
2229
  for (const [key, value] of Object.entries(options)) {
@@ -481,13 +2233,55 @@ export class HardwareFilterPresets extends FilterPresetBase {
481
2233
  return filter;
482
2234
  }
483
2235
  /**
484
- * Hardware-accelerated transpose filter.
485
- * @returns Filter string or null if not supported
2236
+ * Creates a hardware-accelerated transpose filter.
2237
+ *
2238
+ * Direction values:
2239
+ * - 0: 90 degrees counter-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)
2245
+ *
2246
+ * @returns Hardware transpose filter string or null if not supported
2247
+ *
2248
+ * @example
2249
+ * ```typescript
2250
+ * const filter = hwPresets.transpose('clock');
2251
+ * ```
2252
+ *
2253
+ * @example
2254
+ * ```typescript
2255
+ * const filter = hwPresets.transpose(2);
2256
+ * ```
486
2257
  */
487
- transpose(dir = 0) {
2258
+ transpose(mode) {
488
2259
  if (!this.support.transpose) {
489
2260
  return null;
490
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
+ }
491
2285
  // Special handling for different hardware transpose implementations
492
2286
  let filterName;
493
2287
  if (this.deviceType === AV_HWDEVICE_TYPE_CUDA) {
@@ -497,20 +2291,34 @@ export class HardwareFilterPresets extends FilterPresetBase {
497
2291
  filterName = 'transpose_vt'; // CoreImage-based transpose
498
2292
  }
499
2293
  else {
500
- filterName = `transpose_${this.deviceName}`;
2294
+ filterName = `transpose_${this.deviceTypeName}`;
501
2295
  }
502
2296
  return `${filterName}=dir=${dir}`;
503
2297
  }
504
2298
  /**
505
- * Hardware-accelerated tonemap filter.
506
- * @returns Filter string or null if not supported
2299
+ * Creates a hardware-accelerated tonemap filter.
2300
+ * Used for HDR to SDR conversion with hardware acceleration.
2301
+ *
2302
+ * @param options - Tonemapping options (algorithm, parameters)
2303
+ *
2304
+ * @returns Hardware tonemap filter string or null if not supported
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
+ * ```
507
2315
  */
508
2316
  tonemap(options) {
509
2317
  if (!this.support.tonemap) {
510
2318
  return null;
511
2319
  }
512
2320
  // VideoToolbox uses different filter name
513
- const filterName = this.deviceType === AV_HWDEVICE_TYPE_VIDEOTOOLBOX ? 'tonemap_videotoolbox' : `tonemap_${this.deviceName}`;
2321
+ const filterName = this.deviceType === AV_HWDEVICE_TYPE_VIDEOTOOLBOX ? 'tonemap_videotoolbox' : `tonemap_${this.deviceTypeName}`;
514
2322
  let filter = filterName;
515
2323
  if (options) {
516
2324
  const opts = Object.entries(options)
@@ -521,8 +2329,28 @@ export class HardwareFilterPresets extends FilterPresetBase {
521
2329
  return filter;
522
2330
  }
523
2331
  /**
524
- * Hardware-accelerated deinterlace filter.
525
- * @returns Filter string or null if not supported
2332
+ * Creates a hardware-accelerated deinterlace filter.
2333
+ *
2334
+ * Different hardware types use different deinterlacers:
2335
+ * - CUDA: yadif_cuda
2336
+ * - VAAPI: deinterlace_vaapi
2337
+ * - QSV: deinterlace_qsv
2338
+ * - Vulkan: bwdif_vulkan
2339
+ * - VideoToolbox: yadif_videotoolbox
2340
+ *
2341
+ * @param mode - Deinterlacing mode (optional)
2342
+ *
2343
+ * @returns Hardware deinterlace filter string or null if not supported
2344
+ *
2345
+ * @example
2346
+ * ```typescript
2347
+ * const filter = hwPresets.deinterlace();
2348
+ * ```
2349
+ *
2350
+ * @example
2351
+ * ```typescript
2352
+ * const filter = hwPresets.deinterlace('send_field');
2353
+ * ```
526
2354
  */
527
2355
  deinterlace(mode) {
528
2356
  if (!this.support.deinterlace) {
@@ -544,8 +2372,22 @@ export class HardwareFilterPresets extends FilterPresetBase {
544
2372
  }
545
2373
  }
546
2374
  /**
547
- * Hardware-accelerated flip filter.
548
- * @returns Filter string or null if not supported
2375
+ * Creates a hardware-accelerated flip filter.
2376
+ * Currently only Vulkan supports hardware flip filters.
2377
+ *
2378
+ * @param direction - Flip direction ('h' for horizontal, 'v' for vertical)
2379
+ *
2380
+ * @returns Hardware flip filter string or null if not supported
2381
+ *
2382
+ * @example
2383
+ * ```typescript
2384
+ * const filter = hwPresets.flip('h');
2385
+ * ```
2386
+ *
2387
+ * @example
2388
+ * ```typescript
2389
+ * const filter = hwPresets.flip('v');
2390
+ * ```
549
2391
  */
550
2392
  flip(direction) {
551
2393
  if (!this.support.flip) {
@@ -557,8 +2399,27 @@ export class HardwareFilterPresets extends FilterPresetBase {
557
2399
  return null;
558
2400
  }
559
2401
  /**
560
- * Hardware-accelerated blur filter.
561
- * @returns Filter string or null if not supported
2402
+ * Creates a hardware-accelerated blur filter.
2403
+ *
2404
+ * Different hardware types support different blur filters:
2405
+ * - CUDA: bilateral_cuda
2406
+ * - Vulkan: avgblur_vulkan, gblur_vulkan
2407
+ * - OpenCL: avgblur_opencl, boxblur_opencl
2408
+ *
2409
+ * @param type - Blur type ('avg', 'gaussian', or 'box', default: 'avg')
2410
+ * @param radius - Blur radius (optional)
2411
+ *
2412
+ * @returns Hardware blur filter string or null if not supported
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
+ * ```
562
2423
  */
563
2424
  blur(type = 'avg', radius) {
564
2425
  if (!this.support.blur) {
@@ -576,8 +2437,26 @@ export class HardwareFilterPresets extends FilterPresetBase {
576
2437
  }
577
2438
  }
578
2439
  /**
579
- * Hardware-accelerated sharpen filter.
580
- * @returns Filter string or null if not supported
2440
+ * Creates a hardware-accelerated sharpen filter.
2441
+ *
2442
+ * Hardware sharpening support:
2443
+ * - VAAPI: sharpness_vaapi
2444
+ * - OpenCL: unsharp_opencl
2445
+ * - CUDA: sharpen_npp (NPP-based)
2446
+ *
2447
+ * @param amount - Sharpening amount (optional)
2448
+ *
2449
+ * @returns Hardware sharpen filter string or null if not supported
2450
+ *
2451
+ * @example
2452
+ * ```typescript
2453
+ * const filter = hwPresets.sharpen(1.5);
2454
+ * ```
2455
+ *
2456
+ * @example
2457
+ * ```typescript
2458
+ * const filter = hwPresets.sharpen();
2459
+ * ```
581
2460
  */
582
2461
  sharpen(amount) {
583
2462
  if (!this.support.sharpen) {
@@ -596,20 +2475,45 @@ export class HardwareFilterPresets extends FilterPresetBase {
596
2475
  }
597
2476
  }
598
2477
  /**
599
- * Hardware-accelerated stack filters (hstack, vstack, xstack).
600
- * @returns Filter string or null if not supported
2478
+ * Creates a hardware-accelerated stack filter.
2479
+ * Only VAAPI and QSV support hardware stacking.
2480
+ *
2481
+ * @param type - Stack type ('h' for horizontal, 'v' for vertical, 'x' for grid)
2482
+ * @param inputs - Number of inputs to stack (default: 2)
2483
+ *
2484
+ * @returns Hardware stack filter string or null if not supported
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
+ * ```
601
2495
  */
602
2496
  stack(type, inputs = 2) {
603
2497
  if (!this.support.stack) {
604
2498
  return null;
605
2499
  }
606
2500
  if (this.deviceType === AV_HWDEVICE_TYPE_VAAPI || this.deviceType === AV_HWDEVICE_TYPE_QSV) {
607
- return `${type}stack_${this.deviceName}=inputs=${inputs}`;
2501
+ return `${type}stack_${this.deviceTypeName}=inputs=${inputs}`;
608
2502
  }
609
2503
  return null;
610
2504
  }
611
2505
  /**
612
- * Hardware upload filter to transfer frames to GPU.
2506
+ * Creates a hwupload filter to upload frames to hardware memory.
2507
+ * CUDA uses hwupload_cuda, others use generic hwupload.
2508
+ *
2509
+ * @returns Hardware upload filter string
2510
+ *
2511
+ * @example
2512
+ * ```typescript
2513
+ * const filter = hwPresets.hwupload();
2514
+ * ```
2515
+ *
2516
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwupload | FFmpeg hwupload filter}
613
2517
  */
614
2518
  hwupload() {
615
2519
  if (this.deviceType === AV_HWDEVICE_TYPE_CUDA) {
@@ -618,25 +2522,64 @@ export class HardwareFilterPresets extends FilterPresetBase {
618
2522
  return 'hwupload';
619
2523
  }
620
2524
  /**
621
- * Hardware download filter to transfer frames from GPU.
2525
+ * Creates a hwdownload filter to download frames from hardware memory.
2526
+ *
2527
+ * @returns Hardware download filter string
2528
+ *
2529
+ * @example
2530
+ * ```typescript
2531
+ * const filter = hwPresets.hwdownload();
2532
+ * ```
2533
+ *
2534
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwdownload | FFmpeg hwdownload filter}
622
2535
  */
623
2536
  hwdownload() {
624
2537
  return 'hwdownload';
625
2538
  }
626
2539
  /**
627
- * Format conversion for hardware frames.
2540
+ * Creates a hwmap filter to map frames between hardware devices.
2541
+ *
2542
+ * @param derive - Device to derive from (optional)
2543
+ *
2544
+ * @returns Hardware map filter string
2545
+ *
2546
+ * @example
2547
+ * ```typescript
2548
+ * const filter = hwPresets.hwmap('cuda');
2549
+ * ```
2550
+ *
2551
+ * @example
2552
+ * ```typescript
2553
+ * const filter = hwPresets.hwmap();
2554
+ * ```
2555
+ *
2556
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwmap | FFmpeg hwmap filter}
628
2557
  */
629
2558
  hwmap(derive) {
630
2559
  return derive ? `hwmap=derive_device=${derive}` : 'hwmap';
631
2560
  }
632
2561
  /**
633
- * Get capabilities for this hardware type.
2562
+ * Gets the filter capabilities for this hardware type.
2563
+ *
2564
+ * @returns Object describing which filters are supported
2565
+ *
2566
+ * @example
2567
+ * ```typescript
2568
+ * const caps = hw.getCapabilities();
2569
+ * if (caps.scale && caps.overlay) {
2570
+ * console.log('Hardware supports scaling and overlay');
2571
+ * }
2572
+ * ```
634
2573
  */
635
2574
  getCapabilities() {
636
2575
  return this.support;
637
2576
  }
638
2577
  /**
639
- * Get supported filters for this hardware type.
2578
+ * Determines filter support for the hardware type.
2579
+ *
2580
+ * @returns Hardware filter support configuration
2581
+ *
2582
+ * @internal
640
2583
  */
641
2584
  getSupport() {
642
2585
  switch (this.deviceType) {
@@ -816,7 +2759,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
816
2759
  }
817
2760
  /**
818
2761
  * Hardware filter chain builder with fluent API.
819
- * Automatically skips unsupported filters (returns null).
2762
+ * Automatically skips unsupported filters (returns null) allowing graceful fallback.
2763
+ *
2764
+ * @example
2765
+ * ```typescript
2766
+ * const hw = new HardwareFilterPresets(AV_HWDEVICE_TYPE_CUDA, 'cuda');
2767
+ * const chain = hw.chain()
2768
+ * .hwupload()
2769
+ * .scale(1920, 1080)
2770
+ * .tonemap() // Skipped if not supported
2771
+ * .hwdownload()
2772
+ * .build();
2773
+ * ```
820
2774
  */
821
2775
  export class HardwareFilterChainBuilder extends ChainBuilderBase {
822
2776
  }