node-av 1.0.3 → 1.2.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 (162) hide show
  1. package/README.md +56 -41
  2. package/dist/api/bitstream-filter.d.ts +180 -123
  3. package/dist/api/bitstream-filter.js +182 -126
  4. package/dist/api/bitstream-filter.js.map +1 -1
  5. package/dist/api/decoder.d.ts +286 -130
  6. package/dist/api/decoder.js +321 -159
  7. package/dist/api/decoder.js.map +1 -1
  8. package/dist/api/encoder.d.ts +254 -158
  9. package/dist/api/encoder.js +326 -298
  10. package/dist/api/encoder.js.map +1 -1
  11. package/dist/api/filter-presets.d.ts +912 -0
  12. package/dist/api/filter-presets.js +1407 -0
  13. package/dist/api/filter-presets.js.map +1 -0
  14. package/dist/api/filter.d.ts +280 -284
  15. package/dist/api/filter.js +435 -509
  16. package/dist/api/filter.js.map +1 -1
  17. package/dist/api/hardware.d.ts +226 -159
  18. package/dist/api/hardware.js +405 -287
  19. package/dist/api/hardware.js.map +1 -1
  20. package/dist/api/index.d.ts +3 -2
  21. package/dist/api/index.js +1 -0
  22. package/dist/api/index.js.map +1 -1
  23. package/dist/api/io-stream.d.ts +65 -61
  24. package/dist/api/io-stream.js +45 -47
  25. package/dist/api/io-stream.js.map +1 -1
  26. package/dist/api/media-input.d.ts +244 -141
  27. package/dist/api/media-input.js +207 -104
  28. package/dist/api/media-input.js.map +1 -1
  29. package/dist/api/media-output.d.ts +206 -128
  30. package/dist/api/media-output.js +212 -129
  31. package/dist/api/media-output.js.map +1 -1
  32. package/dist/api/pipeline.d.ts +168 -38
  33. package/dist/api/pipeline.js +238 -14
  34. package/dist/api/pipeline.js.map +1 -1
  35. package/dist/api/types.d.ts +22 -182
  36. package/dist/api/utilities/audio-sample.d.ts +1 -1
  37. package/dist/api/utilities/image.d.ts +1 -1
  38. package/dist/api/utilities/media-type.d.ts +1 -1
  39. package/dist/api/utilities/pixel-format.d.ts +1 -1
  40. package/dist/api/utilities/sample-format.d.ts +1 -1
  41. package/dist/api/utilities/timestamp.d.ts +1 -1
  42. package/dist/api/utils.d.ts +1 -2
  43. package/dist/api/utils.js +9 -0
  44. package/dist/api/utils.js.map +1 -1
  45. package/dist/{lib → constants}/channel-layouts.d.ts +1 -1
  46. package/dist/constants/channel-layouts.js.map +1 -0
  47. package/dist/{lib → constants}/constants.d.ts +19 -4
  48. package/dist/{lib → constants}/constants.js +15 -1
  49. package/dist/constants/constants.js.map +1 -0
  50. package/dist/constants/decoders.d.ts +609 -0
  51. package/dist/constants/decoders.js +617 -0
  52. package/dist/constants/decoders.js.map +1 -0
  53. package/dist/constants/encoders.d.ts +285 -0
  54. package/dist/constants/encoders.js +298 -0
  55. package/dist/constants/encoders.js.map +1 -0
  56. package/dist/constants/index.d.ts +4 -0
  57. package/dist/constants/index.js +5 -0
  58. package/dist/constants/index.js.map +1 -0
  59. package/dist/index.d.ts +1 -0
  60. package/dist/index.js +2 -0
  61. package/dist/index.js.map +1 -1
  62. package/dist/lib/audio-fifo.d.ts +128 -171
  63. package/dist/lib/audio-fifo.js +130 -173
  64. package/dist/lib/audio-fifo.js.map +1 -1
  65. package/dist/lib/binding.d.ts +7 -5
  66. package/dist/lib/binding.js +5 -0
  67. package/dist/lib/binding.js.map +1 -1
  68. package/dist/lib/bitstream-filter-context.d.ts +139 -184
  69. package/dist/lib/bitstream-filter-context.js +139 -188
  70. package/dist/lib/bitstream-filter-context.js.map +1 -1
  71. package/dist/lib/bitstream-filter.d.ts +69 -55
  72. package/dist/lib/bitstream-filter.js +68 -54
  73. package/dist/lib/bitstream-filter.js.map +1 -1
  74. package/dist/lib/codec-context.d.ts +317 -381
  75. package/dist/lib/codec-context.js +316 -381
  76. package/dist/lib/codec-context.js.map +1 -1
  77. package/dist/lib/codec-parameters.d.ts +161 -171
  78. package/dist/lib/codec-parameters.js +162 -172
  79. package/dist/lib/codec-parameters.js.map +1 -1
  80. package/dist/lib/codec-parser.d.ts +92 -105
  81. package/dist/lib/codec-parser.js +92 -103
  82. package/dist/lib/codec-parser.js.map +1 -1
  83. package/dist/lib/codec.d.ts +328 -217
  84. package/dist/lib/codec.js +392 -218
  85. package/dist/lib/codec.js.map +1 -1
  86. package/dist/lib/dictionary.d.ts +150 -204
  87. package/dist/lib/dictionary.js +159 -213
  88. package/dist/lib/dictionary.js.map +1 -1
  89. package/dist/lib/error.d.ts +97 -131
  90. package/dist/lib/error.js +98 -128
  91. package/dist/lib/error.js.map +1 -1
  92. package/dist/lib/filter-context.d.ts +317 -194
  93. package/dist/lib/filter-context.js +335 -200
  94. package/dist/lib/filter-context.js.map +1 -1
  95. package/dist/lib/filter-graph.d.ts +252 -293
  96. package/dist/lib/filter-graph.js +253 -294
  97. package/dist/lib/filter-graph.js.map +1 -1
  98. package/dist/lib/filter-inout.d.ts +87 -95
  99. package/dist/lib/filter-inout.js +87 -95
  100. package/dist/lib/filter-inout.js.map +1 -1
  101. package/dist/lib/filter.d.ts +93 -111
  102. package/dist/lib/filter.js +94 -112
  103. package/dist/lib/filter.js.map +1 -1
  104. package/dist/lib/format-context.d.ts +321 -429
  105. package/dist/lib/format-context.js +314 -386
  106. package/dist/lib/format-context.js.map +1 -1
  107. package/dist/lib/frame.d.ts +263 -406
  108. package/dist/lib/frame.js +263 -408
  109. package/dist/lib/frame.js.map +1 -1
  110. package/dist/lib/hardware-device-context.d.ts +150 -204
  111. package/dist/lib/hardware-device-context.js +149 -203
  112. package/dist/lib/hardware-device-context.js.map +1 -1
  113. package/dist/lib/hardware-frames-context.d.ts +171 -181
  114. package/dist/lib/hardware-frames-context.js +171 -181
  115. package/dist/lib/hardware-frames-context.js.map +1 -1
  116. package/dist/lib/index.d.ts +2 -3
  117. package/dist/lib/index.js +2 -5
  118. package/dist/lib/index.js.map +1 -1
  119. package/dist/lib/input-format.d.ts +90 -118
  120. package/dist/lib/input-format.js +89 -117
  121. package/dist/lib/input-format.js.map +1 -1
  122. package/dist/lib/io-context.d.ts +210 -242
  123. package/dist/lib/io-context.js +221 -253
  124. package/dist/lib/io-context.js.map +1 -1
  125. package/dist/lib/log.d.ts +86 -120
  126. package/dist/lib/log.js +85 -122
  127. package/dist/lib/log.js.map +1 -1
  128. package/dist/lib/native-types.d.ts +127 -112
  129. package/dist/lib/native-types.js +9 -0
  130. package/dist/lib/native-types.js.map +1 -1
  131. package/dist/lib/option.d.ts +285 -242
  132. package/dist/lib/option.js +310 -250
  133. package/dist/lib/option.js.map +1 -1
  134. package/dist/lib/output-format.d.ts +78 -102
  135. package/dist/lib/output-format.js +77 -101
  136. package/dist/lib/output-format.js.map +1 -1
  137. package/dist/lib/packet.d.ts +173 -241
  138. package/dist/lib/packet.js +172 -241
  139. package/dist/lib/packet.js.map +1 -1
  140. package/dist/lib/rational.d.ts +0 -2
  141. package/dist/lib/rational.js +0 -2
  142. package/dist/lib/rational.js.map +1 -1
  143. package/dist/lib/software-resample-context.d.ts +242 -326
  144. package/dist/lib/software-resample-context.js +242 -326
  145. package/dist/lib/software-resample-context.js.map +1 -1
  146. package/dist/lib/software-scale-context.d.ts +130 -174
  147. package/dist/lib/software-scale-context.js +132 -176
  148. package/dist/lib/software-scale-context.js.map +1 -1
  149. package/dist/lib/stream.d.ts +88 -198
  150. package/dist/lib/stream.js +87 -197
  151. package/dist/lib/stream.js.map +1 -1
  152. package/dist/lib/types.d.ts +1 -1
  153. package/dist/lib/utilities.d.ts +372 -181
  154. package/dist/lib/utilities.js +373 -182
  155. package/dist/lib/utilities.js.map +1 -1
  156. package/install/check.js +0 -1
  157. package/package.json +32 -24
  158. package/release_notes.md +43 -13
  159. package/CHANGELOG.md +0 -8
  160. package/dist/lib/channel-layouts.js.map +0 -1
  161. package/dist/lib/constants.js.map +0 -1
  162. /package/dist/{lib → constants}/channel-layouts.js +0 -0
@@ -0,0 +1,1407 @@
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
+ import { Filter } from '../lib/filter.js';
3
+ import { avGetPixFmtName, avGetSampleFmtName } from '../lib/utilities.js';
4
+ /**
5
+ * Base class for filter preset implementations.
6
+ * Provides common filter building methods that can be overridden by hardware-specific implementations.
7
+ *
8
+ * This class defines the standard filter operations available in FFmpeg,
9
+ * with each method returning a filter string that can be used in a filter graph.
10
+ * Hardware-specific implementations may override these methods to use optimized
11
+ * hardware filters instead of software implementations.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * class CustomPresets extends FilterPresetBase {
16
+ * override scale(width: number, height: number): string | null {
17
+ * return `custom_scale=${width}:${height}`;
18
+ * }
19
+ * }
20
+ * ```
21
+ */
22
+ export class FilterPresetBase {
23
+ /**
24
+ * Creates a scale filter string.
25
+ *
26
+ * @param width - Target width in pixels
27
+ * @param height - Target height in pixels
28
+ * @param options - Additional scaling options (e.g., flags for algorithm)
29
+ * @returns Filter string or null if not supported
30
+ *
31
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#scale | FFmpeg scale filter}
32
+ */
33
+ scale(width, height, options) {
34
+ const flags = options?.flags;
35
+ const base = `scale=${width}:${height}`;
36
+ return flags ? `${base}:flags=${flags}` : base;
37
+ }
38
+ /**
39
+ * Creates a crop filter string.
40
+ *
41
+ * @param width - Width of the cropped area
42
+ * @param height - Height of the cropped area
43
+ * @param x - X coordinate of top-left corner (default: 0)
44
+ * @param y - Y coordinate of top-left corner (default: 0)
45
+ * @returns Filter string or null if not supported
46
+ *
47
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#crop | FFmpeg crop filter}
48
+ */
49
+ crop(width, height, x = 0, y = 0) {
50
+ return `crop=${width}:${height}:${x}:${y}`;
51
+ }
52
+ /**
53
+ * Creates an FPS filter string to change frame rate.
54
+ *
55
+ * @param fps - Target frames per second
56
+ * @returns Filter string or null if not supported
57
+ *
58
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#fps | FFmpeg fps filter}
59
+ */
60
+ fps(fps) {
61
+ return `fps=${fps}`;
62
+ }
63
+ /**
64
+ * Creates a format filter string to convert pixel format.
65
+ *
66
+ * @param pixelFormat - Target pixel format(s) - can be string, AVPixelFormat enum, or array
67
+ * @returns Filter string or null if not supported
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * // Single format
72
+ * presets.format('yuv420p');
73
+ * presets.format(AV_PIX_FMT_YUV420P);
74
+ *
75
+ * // Multiple formats (creates a chain)
76
+ * presets.format(['yuv420p', 'rgb24']);
77
+ * ```
78
+ *
79
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#format | FFmpeg format filter}
80
+ */
81
+ format(pixelFormat) {
82
+ if (Array.isArray(pixelFormat)) {
83
+ // Create a chain of format filters
84
+ const formats = pixelFormat.map((fmt) => {
85
+ const formatName = typeof fmt === 'string' ? fmt : (avGetPixFmtName(fmt) ?? 'yuv420p');
86
+ return `format=${formatName}`;
87
+ });
88
+ return formats.join(',');
89
+ }
90
+ const formatName = typeof pixelFormat === 'string' ? pixelFormat : (avGetPixFmtName(pixelFormat) ?? 'yuv420p');
91
+ return `format=${formatName}`;
92
+ }
93
+ /**
94
+ * Creates a rotate filter string.
95
+ *
96
+ * @param angle - Rotation angle in degrees
97
+ * @returns Filter string or null if not supported
98
+ *
99
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#rotate | FFmpeg rotate filter}
100
+ */
101
+ rotate(angle) {
102
+ return `rotate=${angle}*PI/180`;
103
+ }
104
+ /**
105
+ * Creates a horizontal flip filter string.
106
+ *
107
+ * @returns Filter string or null if not supported
108
+ *
109
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hflip | FFmpeg hflip filter}
110
+ */
111
+ hflip() {
112
+ return 'hflip';
113
+ }
114
+ /**
115
+ * Creates a vertical flip filter string.
116
+ *
117
+ * @returns Filter string or null if not supported
118
+ *
119
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#vflip | FFmpeg vflip filter}
120
+ */
121
+ vflip() {
122
+ return 'vflip';
123
+ }
124
+ /**
125
+ * Creates a fade filter string for video.
126
+ *
127
+ * @param type - Fade type ('in' or 'out')
128
+ * @param start - Start time in seconds
129
+ * @param duration - Fade duration in seconds
130
+ * @returns Filter string or null if not supported
131
+ *
132
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#fade | FFmpeg fade filter}
133
+ */
134
+ fade(type, start, duration) {
135
+ return `fade=t=${type}:st=${start}:d=${duration}`;
136
+ }
137
+ /**
138
+ * Creates an overlay filter string to composite two video streams.
139
+ *
140
+ * @param x - X position for overlay (default: 0)
141
+ * @param y - Y position for overlay (default: 0)
142
+ * @param options - Additional overlay options
143
+ * @returns Filter string or null if not supported
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * // Basic overlay at position
148
+ * presets.overlay(100, 50);
149
+ *
150
+ * // With additional options
151
+ * presets.overlay(0, 0, { format: 'yuv420' });
152
+ * ```
153
+ *
154
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#overlay | FFmpeg overlay filter}
155
+ */
156
+ overlay(x = 0, y = 0, options) {
157
+ let filter = `overlay=${x}:${y}`;
158
+ if (options) {
159
+ for (const [key, value] of Object.entries(options)) {
160
+ filter += `:${key}=${value}`;
161
+ }
162
+ }
163
+ return filter;
164
+ }
165
+ /**
166
+ * Creates a volume filter string for audio.
167
+ *
168
+ * @param factor - Volume multiplication factor (1.0 = unchanged, 2.0 = double)
169
+ * @returns Filter string or null if not supported
170
+ *
171
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#volume | FFmpeg volume filter}
172
+ */
173
+ volume(factor) {
174
+ return `volume=${factor}`;
175
+ }
176
+ /**
177
+ * Creates an audio format filter string.
178
+ *
179
+ * @param sampleFormat - Target sample format (e.g., 's16', 'fltp')
180
+ * @param sampleRate - Target sample rate in Hz (optional)
181
+ * @param channelLayout - Target channel layout (optional)
182
+ * @returns Filter string or null if not supported
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * // Change sample format only
187
+ * presets.aformat('s16');
188
+ *
189
+ * // Change format and sample rate
190
+ * presets.aformat('fltp', 48000);
191
+ *
192
+ * // Full conversion
193
+ * presets.aformat('s16', 44100, 'stereo');
194
+ * ```
195
+ *
196
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#aformat | FFmpeg aformat filter}
197
+ */
198
+ aformat(sampleFormat, sampleRate, channelLayout) {
199
+ const formatName = typeof sampleFormat === 'string' ? sampleFormat : (avGetSampleFmtName(sampleFormat) ?? 's16');
200
+ let filter = `aformat=sample_fmts=${formatName}`;
201
+ if (sampleRate)
202
+ filter += `:sample_rates=${sampleRate}`;
203
+ if (channelLayout)
204
+ filter += `:channel_layouts=${channelLayout}`;
205
+ return filter;
206
+ }
207
+ /**
208
+ * Creates an atempo filter string to change audio playback speed.
209
+ * Factor must be between 0.5 and 2.0. For larger changes, chain multiple atempo filters.
210
+ *
211
+ * @param factor - Tempo factor (0.5 = half speed, 2.0 = double speed)
212
+ * @returns Filter string or null if not supported
213
+ *
214
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#atempo | FFmpeg atempo filter}
215
+ */
216
+ atempo(factor) {
217
+ return `atempo=${factor}`;
218
+ }
219
+ /**
220
+ * Creates an audio fade filter string.
221
+ *
222
+ * @param type - Fade type ('in' or 'out')
223
+ * @param start - Start time in seconds
224
+ * @param duration - Fade duration in seconds
225
+ * @returns Filter string or null if not supported
226
+ *
227
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#afade | FFmpeg afade filter}
228
+ */
229
+ afade(type, start, duration) {
230
+ return `afade=t=${type}:st=${start}:d=${duration}`;
231
+ }
232
+ /**
233
+ * Creates an amix filter string to mix multiple audio streams.
234
+ *
235
+ * @param inputs - Number of input streams to mix (default: 2)
236
+ * @param duration - How to determine output duration (default: 'longest')
237
+ * @returns Filter string or null if not supported
238
+ *
239
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#amix | FFmpeg amix filter}
240
+ */
241
+ amix(inputs = 2, duration = 'longest') {
242
+ return `amix=inputs=${inputs}:duration=${duration}`;
243
+ }
244
+ }
245
+ /**
246
+ * Filter chain builder for composing multiple filters.
247
+ * Allows fluent API for building complex filter graphs by chaining filter operations.
248
+ *
249
+ * @example
250
+ * ```typescript
251
+ * const chain = new FilterChain()
252
+ * .add('scale=1920:1080')
253
+ * .add('fps=30')
254
+ * .custom('rotate=45*PI/180')
255
+ * .build();
256
+ * // Result: "scale=1920:1080,fps=30,rotate=45*PI/180"
257
+ * ```
258
+ */
259
+ export class FilterChain {
260
+ filters = [];
261
+ /**
262
+ * Adds a filter to the chain.
263
+ *
264
+ * @param filter - Filter string to add (ignored if null/undefined)
265
+ * @returns This instance for chaining
266
+ */
267
+ add(filter) {
268
+ if (filter) {
269
+ this.filters.push(filter);
270
+ }
271
+ return this;
272
+ }
273
+ /**
274
+ * Adds a custom filter string to the chain.
275
+ *
276
+ * @param filter - Custom filter string
277
+ * @returns This instance for chaining
278
+ */
279
+ custom(filter) {
280
+ return this.add(filter);
281
+ }
282
+ /**
283
+ * Builds the final filter string.
284
+ *
285
+ * @param separator - Separator between filters (default: ',')
286
+ * @returns Combined filter string
287
+ */
288
+ build(separator = ',') {
289
+ return this.filters.join(separator);
290
+ }
291
+ /**
292
+ * Returns the filters as an array.
293
+ *
294
+ * @returns Array of filter strings
295
+ */
296
+ toArray() {
297
+ return [...this.filters];
298
+ }
299
+ }
300
+ /**
301
+ * Base chain builder with common filter methods.
302
+ * Provides a fluent API for building filter chains using preset methods.
303
+ *
304
+ * @template T The preset type this builder uses
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * const chain = new ChainBuilderBase(presets)
309
+ * .scale(1920, 1080)
310
+ * .fps(30)
311
+ * .fade('in', 0, 2)
312
+ * .build();
313
+ * ```
314
+ */
315
+ export class ChainBuilderBase extends FilterChain {
316
+ presets;
317
+ /**
318
+ * @param presets - The filter presets to use
319
+ * @internal
320
+ */
321
+ constructor(presets) {
322
+ super();
323
+ this.presets = presets;
324
+ }
325
+ /**
326
+ * Adds a scale filter to the chain.
327
+ *
328
+ * @param width - Target width
329
+ * @param height - Target height
330
+ * @param options - Additional scaling options
331
+ * @returns This instance for chaining
332
+ *
333
+ * @see {@link FilterPresetBase.scale}
334
+ */
335
+ scale(width, height, options) {
336
+ return this.add(this.presets.scale(width, height, options));
337
+ }
338
+ /**
339
+ * Adds a crop filter to the chain.
340
+ *
341
+ * @param width - Crop width
342
+ * @param height - Crop height
343
+ * @param x - X position (default: 0)
344
+ * @param y - Y position (default: 0)
345
+ * @returns This instance for chaining
346
+ *
347
+ * @see {@link FilterPresetBase.crop}
348
+ */
349
+ crop(width, height, x = 0, y = 0) {
350
+ return this.add(this.presets.crop(width, height, x, y));
351
+ }
352
+ /**
353
+ * Adds an FPS filter to the chain.
354
+ *
355
+ * @param fps - Target frame rate
356
+ * @returns This instance for chaining
357
+ *
358
+ * @see {@link FilterPresetBase.fps}
359
+ */
360
+ fps(fps) {
361
+ return this.add(this.presets.fps(fps));
362
+ }
363
+ /**
364
+ * Adds a format filter to the chain.
365
+ *
366
+ * @param pixelFormat - Target pixel format(s)
367
+ * @returns This instance for chaining
368
+ *
369
+ * @see {@link FilterPresetBase.format}
370
+ */
371
+ format(pixelFormat) {
372
+ return this.add(this.presets.format(pixelFormat));
373
+ }
374
+ /**
375
+ * Adds a rotate filter to the chain.
376
+ *
377
+ * @param angle - Rotation angle in degrees
378
+ * @returns This instance for chaining
379
+ *
380
+ * @see {@link FilterPresetBase.rotate}
381
+ */
382
+ rotate(angle) {
383
+ return this.add(this.presets.rotate(angle));
384
+ }
385
+ /**
386
+ * Adds a horizontal flip filter to the chain.
387
+ *
388
+ * @returns This instance for chaining
389
+ *
390
+ * @see {@link FilterPresetBase.hflip}
391
+ */
392
+ hflip() {
393
+ return this.add(this.presets.hflip());
394
+ }
395
+ /**
396
+ * Adds a vertical flip filter to the chain.
397
+ *
398
+ * @returns This instance for chaining
399
+ *
400
+ * @see {@link FilterPresetBase.vflip}
401
+ */
402
+ vflip() {
403
+ return this.add(this.presets.vflip());
404
+ }
405
+ /**
406
+ * Adds a fade filter to the chain.
407
+ *
408
+ * @param type - Fade type ('in' or 'out')
409
+ * @param start - Start time in seconds
410
+ * @param duration - Fade duration in seconds
411
+ * @returns This instance for chaining
412
+ *
413
+ * @see {@link FilterPresetBase.fade}
414
+ */
415
+ fade(type, start, duration) {
416
+ return this.add(this.presets.fade(type, start, duration));
417
+ }
418
+ /**
419
+ * Adds an overlay filter to the chain.
420
+ *
421
+ * @param x - X position (default: 0)
422
+ * @param y - Y position (default: 0)
423
+ * @param options - Additional overlay options
424
+ * @returns This instance for chaining
425
+ *
426
+ * @see {@link FilterPresetBase.overlay}
427
+ */
428
+ overlay(x = 0, y = 0, options) {
429
+ return this.add(this.presets.overlay(x, y, options));
430
+ }
431
+ /**
432
+ * Adds a volume filter to the chain.
433
+ *
434
+ * @param factor - Volume factor
435
+ * @returns This instance for chaining
436
+ *
437
+ * @see {@link FilterPresetBase.volume}
438
+ */
439
+ volume(factor) {
440
+ return this.add(this.presets.volume(factor));
441
+ }
442
+ /**
443
+ * Adds an audio format filter to the chain.
444
+ *
445
+ * @param sampleFormat - Target sample format
446
+ * @param sampleRate - Target sample rate (optional)
447
+ * @param channelLayout - Target channel layout (optional)
448
+ * @returns This instance for chaining
449
+ *
450
+ * @see {@link FilterPresetBase.aformat}
451
+ */
452
+ aformat(sampleFormat, sampleRate, channelLayout) {
453
+ return this.add(this.presets.aformat(sampleFormat, sampleRate, channelLayout));
454
+ }
455
+ /**
456
+ * Adds an atempo filter to the chain.
457
+ *
458
+ * @param factor - Tempo factor (0.5 to 2.0)
459
+ * @returns This instance for chaining
460
+ *
461
+ * @see {@link FilterPresetBase.atempo}
462
+ */
463
+ atempo(factor) {
464
+ return this.add(this.presets.atempo(factor));
465
+ }
466
+ /**
467
+ * Adds an audio fade filter to the chain.
468
+ *
469
+ * @param type - Fade type ('in' or 'out')
470
+ * @param start - Start time in seconds
471
+ * @param duration - Fade duration in seconds
472
+ * @returns This instance for chaining
473
+ *
474
+ * @see {@link FilterPresetBase.afade}
475
+ */
476
+ afade(type, start, duration) {
477
+ return this.add(this.presets.afade(type, start, duration));
478
+ }
479
+ /**
480
+ * Adds an amix filter to the chain.
481
+ *
482
+ * @param inputs - Number of inputs (default: 2)
483
+ * @param duration - Duration mode (default: 'longest')
484
+ * @returns This instance for chaining
485
+ *
486
+ * @see {@link FilterPresetBase.amix}
487
+ */
488
+ amix(inputs = 2, duration = 'longest') {
489
+ return this.add(this.presets.amix(inputs, duration));
490
+ }
491
+ /**
492
+ * Adds a transpose filter to the chain (hardware-specific).
493
+ * Only available for hardware presets that support transpose
494
+ *
495
+ * @param dir - Transpose direction (default: 0)
496
+ * @returns This instance for chaining
497
+ *
498
+ */
499
+ transpose(dir = 0) {
500
+ if ('transpose' in this.presets) {
501
+ return this.add(this.presets.transpose(dir));
502
+ }
503
+ return this.add(null);
504
+ }
505
+ /**
506
+ * Adds a tonemap filter to the chain (hardware-specific).
507
+ * Only available for hardware presets that support tonemapping
508
+ *
509
+ * @param options - Tonemapping options
510
+ * @returns This instance for chaining
511
+ *
512
+ */
513
+ tonemap(options) {
514
+ if ('tonemap' in this.presets) {
515
+ return this.add(this.presets.tonemap(options));
516
+ }
517
+ return this.add(null);
518
+ }
519
+ /**
520
+ * Adds a deinterlace filter to the chain (hardware-specific).
521
+ * Only available for hardware presets that support deinterlacing
522
+ *
523
+ * @param mode - Deinterlace mode (optional)
524
+ * @returns This instance for chaining
525
+ *
526
+ */
527
+ deinterlace(mode) {
528
+ if ('deinterlace' in this.presets) {
529
+ return this.add(this.presets.deinterlace(mode));
530
+ }
531
+ return this.add(null);
532
+ }
533
+ /**
534
+ * Adds a flip filter to the chain (hardware-specific).
535
+ * Falls back to hflip/vflip if hardware flip not available
536
+ *
537
+ * @param direction - Flip direction ('h' or 'v')
538
+ * @returns This instance for chaining
539
+ *
540
+ */
541
+ flip(direction) {
542
+ if ('flip' in this.presets) {
543
+ return this.add(this.presets.flip(direction));
544
+ }
545
+ // Fallback to hflip/vflip
546
+ return direction === 'h' ? this.hflip() : this.vflip();
547
+ }
548
+ /**
549
+ * Adds a blur filter to the chain (hardware-specific).
550
+ * Only available for hardware presets that support blur
551
+ *
552
+ * @param type - Blur type (default: 'avg')
553
+ * @param radius - Blur radius (optional)
554
+ * @returns This instance for chaining
555
+ *
556
+ */
557
+ blur(type = 'avg', radius) {
558
+ if ('blur' in this.presets) {
559
+ return this.add(this.presets.blur(type, radius));
560
+ }
561
+ return this.add(null);
562
+ }
563
+ /**
564
+ * Adds a sharpen filter to the chain (hardware-specific).
565
+ * Only available for hardware presets that support sharpening
566
+ *
567
+ * @param amount - Sharpen amount (optional)
568
+ * @returns This instance for chaining
569
+ *
570
+ */
571
+ sharpen(amount) {
572
+ if ('sharpen' in this.presets) {
573
+ return this.add(this.presets.sharpen(amount));
574
+ }
575
+ return this.add(null);
576
+ }
577
+ /**
578
+ * Adds a stack filter to the chain (hardware-specific).
579
+ * Only available for hardware presets that support stacking
580
+ *
581
+ * @param type - Stack type ('h' for horizontal, 'v' for vertical, 'x' for grid)
582
+ * @param inputs - Number of inputs (default: 2)
583
+ * @returns This instance for chaining
584
+ *
585
+ */
586
+ stack(type, inputs = 2) {
587
+ if ('stack' in this.presets) {
588
+ return this.add(this.presets.stack(type, inputs));
589
+ }
590
+ return this.add(null);
591
+ }
592
+ /**
593
+ * Adds a hwupload filter to upload frames to hardware.
594
+ *
595
+ * @returns This instance for chaining
596
+ */
597
+ hwupload() {
598
+ if ('hwupload' in this.presets) {
599
+ return this.add(this.presets.hwupload());
600
+ }
601
+ return this.add('hwupload');
602
+ }
603
+ /**
604
+ * Adds a hwdownload filter to download frames from hardware.
605
+ *
606
+ * @returns This instance for chaining
607
+ */
608
+ hwdownload() {
609
+ if ('hwdownload' in this.presets) {
610
+ return this.add(this.presets.hwdownload());
611
+ }
612
+ return this.add('hwdownload');
613
+ }
614
+ /**
615
+ * Adds a hwmap filter to map frames between hardware devices.
616
+ *
617
+ * @param derive - Device to derive from (optional)
618
+ * @returns This instance for chaining
619
+ */
620
+ hwmap(derive) {
621
+ if ('hwmap' in this.presets) {
622
+ return this.add(this.presets.hwmap(derive));
623
+ }
624
+ return this.add(derive ? `hwmap=derive_device=${derive}` : 'hwmap');
625
+ }
626
+ }
627
+ /**
628
+ * Fluent filter chain builder with preset methods.
629
+ * Provides a convenient API for building filter chains using standard presets.
630
+ *
631
+ * @example
632
+ * ```typescript
633
+ * const filter = FilterPresets.chain()
634
+ * .scale(1920, 1080)
635
+ * .fps(30)
636
+ * .fade('in', 0, 2)
637
+ * .format('yuv420p')
638
+ * .build();
639
+ * ```
640
+ */
641
+ export class FilterChainBuilder extends ChainBuilderBase {
642
+ }
643
+ /**
644
+ * Standard filter presets for software filtering.
645
+ * Provides static methods for creating common filter strings and
646
+ * a chain builder for composing complex filter graphs.
647
+ *
648
+ * @example
649
+ * ```typescript
650
+ * // Static methods for individual filters
651
+ * const scaleFilter = FilterPresets.scale(1920, 1080);
652
+ * const fpsFilter = FilterPresets.fps(30);
653
+ *
654
+ * // Chain builder for complex graphs
655
+ * const chain = FilterPresets.chain()
656
+ * .scale(1920, 1080)
657
+ * .fps(30)
658
+ * .fade('in', 0, 2)
659
+ * .build();
660
+ * ```
661
+ */
662
+ export class FilterPresets extends FilterPresetBase {
663
+ static instance = new FilterPresets();
664
+ /**
665
+ * Creates a new filter chain builder.
666
+ *
667
+ * @returns A new FilterChainBuilder instance
668
+ *
669
+ * @example
670
+ * ```typescript
671
+ * const filter = FilterPresets.chain()
672
+ * .scale(1280, 720)
673
+ * .fps(30)
674
+ * .build();
675
+ * ```
676
+ */
677
+ static chain() {
678
+ return new FilterChainBuilder(FilterPresets.instance);
679
+ }
680
+ /**
681
+ * Creates a scale filter string.
682
+ *
683
+ * @param width - Target width
684
+ * @param height - Target height
685
+ * @param flags - Scaling algorithm flags (optional)
686
+ * @returns Scale filter string
687
+ */
688
+ static scale(width, height, flags) {
689
+ const result = FilterPresets.instance.scale(width, height, { flags });
690
+ return result ?? '';
691
+ }
692
+ /**
693
+ * Creates a crop filter string.
694
+ *
695
+ * @param width - Crop width
696
+ * @param height - Crop height
697
+ * @param x - X position (default: 0)
698
+ * @param y - Y position (default: 0)
699
+ * @returns Crop filter string
700
+ */
701
+ static crop(width, height, x = 0, y = 0) {
702
+ const result = FilterPresets.instance.crop(width, height, x, y);
703
+ return result ?? '';
704
+ }
705
+ /**
706
+ * Creates an FPS filter string.
707
+ *
708
+ * @param fps - Target frame rate
709
+ * @returns FPS filter string
710
+ */
711
+ static fps(fps) {
712
+ const result = FilterPresets.instance.fps(fps);
713
+ return result ?? '';
714
+ }
715
+ /**
716
+ * Creates a format filter string.
717
+ *
718
+ * @param pixelFormat - Target pixel format(s)
719
+ * @returns Format filter string
720
+ */
721
+ static format(pixelFormat) {
722
+ const result = FilterPresets.instance.format(pixelFormat);
723
+ return result ?? '';
724
+ }
725
+ /**
726
+ * Creates a rotate filter string.
727
+ *
728
+ * @param angle - Rotation angle in degrees
729
+ * @returns Rotate filter string
730
+ */
731
+ static rotate(angle) {
732
+ const result = FilterPresets.instance.rotate(angle);
733
+ return result ?? '';
734
+ }
735
+ /**
736
+ * Creates a horizontal flip filter string.
737
+ *
738
+ * @returns Horizontal flip filter string
739
+ */
740
+ static hflip() {
741
+ const result = FilterPresets.instance.hflip();
742
+ return result ?? '';
743
+ }
744
+ /**
745
+ * Creates a vertical flip filter string.
746
+ *
747
+ * @returns Vertical flip filter string
748
+ */
749
+ static vflip() {
750
+ const result = FilterPresets.instance.vflip();
751
+ return result ?? '';
752
+ }
753
+ /**
754
+ * Creates a fade filter string.
755
+ *
756
+ * @param type - Fade type ('in' or 'out')
757
+ * @param start - Start time in seconds
758
+ * @param duration - Fade duration in seconds
759
+ * @returns Fade filter string
760
+ */
761
+ static fade(type, start, duration) {
762
+ const result = FilterPresets.instance.fade(type, start, duration);
763
+ return result ?? '';
764
+ }
765
+ /**
766
+ * Creates an overlay filter string.
767
+ *
768
+ * @param x - X position (default: 0)
769
+ * @param y - Y position (default: 0)
770
+ * @returns Overlay filter string
771
+ */
772
+ static overlay(x = 0, y = 0) {
773
+ const result = FilterPresets.instance.overlay(x, y);
774
+ return result ?? '';
775
+ }
776
+ /**
777
+ * Creates a volume filter string.
778
+ *
779
+ * @param factor - Volume multiplication factor
780
+ * @returns Volume filter string
781
+ */
782
+ static volume(factor) {
783
+ const result = FilterPresets.instance.volume(factor);
784
+ return result ?? '';
785
+ }
786
+ /**
787
+ * Creates an audio format filter string.
788
+ *
789
+ * @param sampleFormat - Target sample format
790
+ * @param sampleRate - Target sample rate (optional)
791
+ * @param channelLayout - Target channel layout (optional)
792
+ * @returns Audio format filter string
793
+ */
794
+ static aformat(sampleFormat, sampleRate, channelLayout) {
795
+ const result = FilterPresets.instance.aformat(sampleFormat, sampleRate, channelLayout);
796
+ return result ?? '';
797
+ }
798
+ /**
799
+ * Creates an atempo filter string.
800
+ *
801
+ * @param factor - Tempo factor (0.5 to 2.0)
802
+ * @returns Atempo filter string
803
+ */
804
+ static atempo(factor) {
805
+ const result = FilterPresets.instance.atempo(factor);
806
+ return result ?? '';
807
+ }
808
+ /**
809
+ * Creates an audio fade filter string.
810
+ *
811
+ * @param type - Fade type ('in' or 'out')
812
+ * @param start - Start time in seconds
813
+ * @param duration - Fade duration in seconds
814
+ * @returns Audio fade filter string
815
+ */
816
+ static afade(type, start, duration) {
817
+ const result = FilterPresets.instance.afade(type, start, duration);
818
+ return result ?? '';
819
+ }
820
+ /**
821
+ * Creates an amix filter string.
822
+ *
823
+ * @param inputs - Number of inputs (default: 2)
824
+ * @param duration - Duration mode (default: 'longest')
825
+ * @returns Amix filter string
826
+ */
827
+ static amix(inputs = 2, duration = 'longest') {
828
+ const result = FilterPresets.instance.amix(inputs, duration);
829
+ return result ?? '';
830
+ }
831
+ }
832
+ /**
833
+ * Hardware-accelerated filter presets.
834
+ * Provides optimized filter implementations for specific hardware types,
835
+ * with automatic fallback when operations aren't supported.
836
+ *
837
+ * @example
838
+ * ```typescript
839
+ * // Create hardware presets for CUDA
840
+ * const hw = new HardwareFilterPresets(AV_HWDEVICE_TYPE_CUDA, 'cuda');
841
+ *
842
+ * // Check capabilities
843
+ * if (hw.support.scale) {
844
+ * const scaleFilter = hw.scale(1920, 1080);
845
+ * }
846
+ *
847
+ * // Use chain builder
848
+ * const chain = hw.chain()
849
+ * .hwupload()
850
+ * .scale(1920, 1080)
851
+ * .tonemap()
852
+ * .hwdownload()
853
+ * .build();
854
+ * ```
855
+ */
856
+ export class HardwareFilterPresets extends FilterPresetBase {
857
+ deviceType;
858
+ deviceTypeName;
859
+ support;
860
+ /**
861
+ * @param deviceType - Hardware device type enum
862
+ * @param deviceTypeName - Hardware device type name (e.g., 'cuda', 'vaapi')
863
+ */
864
+ constructor(deviceType, deviceTypeName) {
865
+ super();
866
+ this.deviceType = deviceType;
867
+ this.deviceTypeName = deviceTypeName;
868
+ this.support = this.getSupport();
869
+ }
870
+ /**
871
+ * Checks if a filter is hardware-accelerated.
872
+ *
873
+ * @param filterName - Name of the filter to check
874
+ * @returns True if the filter uses hardware acceleration
875
+ *
876
+ * @example
877
+ * ```typescript
878
+ * if (HardwareFilterPresets.isHardwareFilter('scale_cuda')) {
879
+ * console.log('Hardware accelerated scaling');
880
+ * }
881
+ * ```
882
+ */
883
+ static isHardwareFilter(filterName) {
884
+ const filter = Filter.getByName(filterName);
885
+ if (!filter) {
886
+ return false;
887
+ }
888
+ // Check if filter has hardware device flag
889
+ return (filter.flags & AVFILTER_FLAG_HWDEVICE) !== 0;
890
+ }
891
+ /**
892
+ * Creates a hardware filter chain builder.
893
+ *
894
+ * @returns A new HardwareFilterChainBuilder instance
895
+ *
896
+ * @example
897
+ * ```typescript
898
+ * const filter = hw.chain()
899
+ * .hwupload()
900
+ * .scale(1920, 1080)
901
+ * .hwdownload()
902
+ * .build();
903
+ * ```
904
+ */
905
+ chain() {
906
+ return new HardwareFilterChainBuilder(this);
907
+ }
908
+ /**
909
+ * Creates a hardware-accelerated scale filter.
910
+ *
911
+ * Different hardware types use different scale filters:
912
+ * - CUDA: scale_cuda or scale_npp (with npp option)
913
+ * - VAAPI: scale_vaapi
914
+ * - QSV: scale_qsv
915
+ * - VideoToolbox: scale_vt
916
+ * - RKMPP: scale_rkrga
917
+ *
918
+ * @param width - Target width
919
+ * @param height - Target height
920
+ * @param options - Hardware-specific scaling options
921
+ * @returns Hardware scale filter string or null if not supported
922
+ *
923
+ *
924
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#scale_005fcuda | FFmpeg scale_cuda filter}
925
+ */
926
+ scale(width, height, options) {
927
+ if (!this.support.scale) {
928
+ return null;
929
+ }
930
+ // Special handling for different hardware scalers
931
+ let filterName;
932
+ if (this.deviceType === AV_HWDEVICE_TYPE_CUDA && options?.npp) {
933
+ filterName = 'scale_npp';
934
+ }
935
+ else if (this.deviceType === AV_HWDEVICE_TYPE_RKMPP) {
936
+ filterName = 'scale_rkrga'; // RKMPP uses RGA for scaling
937
+ }
938
+ else if (this.deviceType === AV_HWDEVICE_TYPE_VIDEOTOOLBOX) {
939
+ filterName = 'scale_vt'; // VideoToolbox uses scale_vt
940
+ }
941
+ else {
942
+ filterName = `scale_${this.deviceTypeName}`;
943
+ }
944
+ let filter = `${filterName}=${width}:${height}`;
945
+ if (options) {
946
+ for (const [key, value] of Object.entries(options)) {
947
+ if (key !== 'npp') {
948
+ // Skip our special npp flag
949
+ filter += `:${key}=${value}`;
950
+ }
951
+ }
952
+ }
953
+ return filter;
954
+ }
955
+ /**
956
+ * Creates a hardware-accelerated overlay filter.
957
+ *
958
+ * @param x - X position (default: 0)
959
+ * @param y - Y position (default: 0)
960
+ * @param options - Hardware-specific overlay options
961
+ * @returns Hardware overlay filter string or null if not supported
962
+ *
963
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#overlay_005fcuda | FFmpeg overlay_cuda filter}
964
+ */
965
+ overlay(x = 0, y = 0, options) {
966
+ if (!this.support.overlay) {
967
+ return null;
968
+ }
969
+ // Special handling for RKMPP which uses RGA
970
+ const filterName = this.deviceType === AV_HWDEVICE_TYPE_RKMPP ? 'overlay_rkrga' : `overlay_${this.deviceTypeName}`;
971
+ let filter = `${filterName}=${x}:${y}`;
972
+ if (options) {
973
+ for (const [key, value] of Object.entries(options)) {
974
+ filter += `:${key}=${value}`;
975
+ }
976
+ }
977
+ return filter;
978
+ }
979
+ /**
980
+ * Creates a hardware-accelerated transpose filter.
981
+ *
982
+ * Direction values:
983
+ * - 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
987
+ *
988
+ * @param dir - Transpose direction (default: 0)
989
+ * @returns Hardware transpose filter string or null if not supported
990
+ *
991
+ */
992
+ transpose(dir = 0) {
993
+ if (!this.support.transpose) {
994
+ return null;
995
+ }
996
+ // Special handling for different hardware transpose implementations
997
+ let filterName;
998
+ if (this.deviceType === AV_HWDEVICE_TYPE_CUDA) {
999
+ filterName = 'transpose_cuda'; // Uses transpose_cuda from patch, not NPP
1000
+ }
1001
+ else if (this.deviceType === AV_HWDEVICE_TYPE_VIDEOTOOLBOX) {
1002
+ filterName = 'transpose_vt'; // CoreImage-based transpose
1003
+ }
1004
+ else {
1005
+ filterName = `transpose_${this.deviceTypeName}`;
1006
+ }
1007
+ return `${filterName}=dir=${dir}`;
1008
+ }
1009
+ /**
1010
+ * Creates a hardware-accelerated tonemap filter.
1011
+ * Used for HDR to SDR conversion with hardware acceleration.
1012
+ *
1013
+ * @param options - Tonemapping options (algorithm, parameters)
1014
+ * @returns Hardware tonemap filter string or null if not supported
1015
+ *
1016
+ */
1017
+ tonemap(options) {
1018
+ if (!this.support.tonemap) {
1019
+ return null;
1020
+ }
1021
+ // VideoToolbox uses different filter name
1022
+ const filterName = this.deviceType === AV_HWDEVICE_TYPE_VIDEOTOOLBOX ? 'tonemap_videotoolbox' : `tonemap_${this.deviceTypeName}`;
1023
+ let filter = filterName;
1024
+ if (options) {
1025
+ const opts = Object.entries(options)
1026
+ .map(([k, v]) => `${k}=${v}`)
1027
+ .join(':');
1028
+ filter += `=${opts}`;
1029
+ }
1030
+ return filter;
1031
+ }
1032
+ /**
1033
+ * Creates a hardware-accelerated deinterlace filter.
1034
+ *
1035
+ * Different hardware types use different deinterlacers:
1036
+ * - CUDA: yadif_cuda
1037
+ * - VAAPI: deinterlace_vaapi
1038
+ * - QSV: deinterlace_qsv
1039
+ * - Vulkan: bwdif_vulkan
1040
+ * - VideoToolbox: yadif_videotoolbox
1041
+ *
1042
+ * @param mode - Deinterlacing mode (optional)
1043
+ * @returns Hardware deinterlace filter string or null if not supported
1044
+ *
1045
+ */
1046
+ deinterlace(mode) {
1047
+ if (!this.support.deinterlace) {
1048
+ return null;
1049
+ }
1050
+ switch (this.deviceType) {
1051
+ case AV_HWDEVICE_TYPE_CUDA:
1052
+ return mode ? `yadif_cuda=mode=${mode}` : 'yadif_cuda';
1053
+ case AV_HWDEVICE_TYPE_VAAPI:
1054
+ return mode ? `deinterlace_vaapi=mode=${mode}` : 'deinterlace_vaapi';
1055
+ case AV_HWDEVICE_TYPE_QSV:
1056
+ return mode ? `deinterlace_qsv=mode=${mode}` : 'deinterlace_qsv';
1057
+ case AV_HWDEVICE_TYPE_VULKAN:
1058
+ return mode ? `bwdif_vulkan=mode=${mode}` : 'bwdif_vulkan';
1059
+ case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
1060
+ return mode ? `yadif_videotoolbox=mode=${mode}` : 'yadif_videotoolbox';
1061
+ default:
1062
+ return null;
1063
+ }
1064
+ }
1065
+ /**
1066
+ * Creates a hardware-accelerated flip filter.
1067
+ * Currently only Vulkan supports hardware flip filters.
1068
+ *
1069
+ * @param direction - Flip direction ('h' for horizontal, 'v' for vertical)
1070
+ * @returns Hardware flip filter string or null if not supported
1071
+ *
1072
+ */
1073
+ flip(direction) {
1074
+ if (!this.support.flip) {
1075
+ return null;
1076
+ }
1077
+ if (this.deviceType === AV_HWDEVICE_TYPE_VULKAN) {
1078
+ return direction === 'h' ? 'hflip_vulkan' : 'vflip_vulkan';
1079
+ }
1080
+ return null;
1081
+ }
1082
+ /**
1083
+ * Creates a hardware-accelerated blur filter.
1084
+ *
1085
+ * Different hardware types support different blur filters:
1086
+ * - CUDA: bilateral_cuda
1087
+ * - Vulkan: avgblur_vulkan, gblur_vulkan
1088
+ * - OpenCL: avgblur_opencl, boxblur_opencl
1089
+ *
1090
+ * @param type - Blur type ('avg', 'gaussian', or 'box', default: 'avg')
1091
+ * @param radius - Blur radius (optional)
1092
+ * @returns Hardware blur filter string or null if not supported
1093
+ *
1094
+ */
1095
+ blur(type = 'avg', radius) {
1096
+ if (!this.support.blur) {
1097
+ return null;
1098
+ }
1099
+ switch (this.deviceType) {
1100
+ case AV_HWDEVICE_TYPE_CUDA:
1101
+ return radius ? `bilateral_cuda=sigmaS=${radius}` : 'bilateral_cuda';
1102
+ case AV_HWDEVICE_TYPE_VULKAN:
1103
+ return type === 'gaussian' ? (radius ? `gblur_vulkan=sigma=${radius}` : 'gblur_vulkan') : radius ? `avgblur_vulkan=sizeX=${radius}` : 'avgblur_vulkan';
1104
+ case AV_HWDEVICE_TYPE_OPENCL:
1105
+ return type === 'box' ? (radius ? `boxblur_opencl=luma_radius=${radius}` : 'boxblur_opencl') : radius ? `avgblur_opencl=sizeX=${radius}` : 'avgblur_opencl';
1106
+ default:
1107
+ return null;
1108
+ }
1109
+ }
1110
+ /**
1111
+ * Creates a hardware-accelerated sharpen filter.
1112
+ *
1113
+ * Hardware sharpening support:
1114
+ * - VAAPI: sharpness_vaapi
1115
+ * - OpenCL: unsharp_opencl
1116
+ * - CUDA: sharpen_npp (NPP-based)
1117
+ *
1118
+ * @param amount - Sharpening amount (optional)
1119
+ * @returns Hardware sharpen filter string or null if not supported
1120
+ *
1121
+ */
1122
+ sharpen(amount) {
1123
+ if (!this.support.sharpen) {
1124
+ return null;
1125
+ }
1126
+ switch (this.deviceType) {
1127
+ case AV_HWDEVICE_TYPE_VAAPI:
1128
+ return amount ? `sharpness_vaapi=sharpness=${amount}` : 'sharpness_vaapi';
1129
+ case AV_HWDEVICE_TYPE_OPENCL:
1130
+ return amount ? `unsharp_opencl=amount=${amount}` : 'unsharp_opencl';
1131
+ case AV_HWDEVICE_TYPE_CUDA:
1132
+ // CUDA uses NPP for sharpening
1133
+ return 'sharpen_npp';
1134
+ default:
1135
+ return null;
1136
+ }
1137
+ }
1138
+ /**
1139
+ * Creates a hardware-accelerated stack filter.
1140
+ * Only VAAPI and QSV support hardware stacking.
1141
+ *
1142
+ * @param type - Stack type ('h' for horizontal, 'v' for vertical, 'x' for grid)
1143
+ * @param inputs - Number of inputs to stack (default: 2)
1144
+ * @returns Hardware stack filter string or null if not supported
1145
+ *
1146
+ */
1147
+ stack(type, inputs = 2) {
1148
+ if (!this.support.stack) {
1149
+ return null;
1150
+ }
1151
+ if (this.deviceType === AV_HWDEVICE_TYPE_VAAPI || this.deviceType === AV_HWDEVICE_TYPE_QSV) {
1152
+ return `${type}stack_${this.deviceTypeName}=inputs=${inputs}`;
1153
+ }
1154
+ return null;
1155
+ }
1156
+ /**
1157
+ * Creates a hwupload filter to upload frames to hardware memory.
1158
+ * CUDA uses hwupload_cuda, others use generic hwupload.
1159
+ *
1160
+ * @returns Hardware upload filter string
1161
+ *
1162
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwupload | FFmpeg hwupload filter}
1163
+ */
1164
+ hwupload() {
1165
+ if (this.deviceType === AV_HWDEVICE_TYPE_CUDA) {
1166
+ return 'hwupload_cuda';
1167
+ }
1168
+ return 'hwupload';
1169
+ }
1170
+ /**
1171
+ * Creates a hwdownload filter to download frames from hardware memory.
1172
+ *
1173
+ * @returns Hardware download filter string
1174
+ *
1175
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwdownload | FFmpeg hwdownload filter}
1176
+ */
1177
+ hwdownload() {
1178
+ return 'hwdownload';
1179
+ }
1180
+ /**
1181
+ * Creates a hwmap filter to map frames between hardware devices.
1182
+ *
1183
+ * @param derive - Device to derive from (optional)
1184
+ * @returns Hardware map filter string
1185
+ *
1186
+ * @see {@link https://ffmpeg.org/ffmpeg-filters.html#hwmap | FFmpeg hwmap filter}
1187
+ */
1188
+ hwmap(derive) {
1189
+ return derive ? `hwmap=derive_device=${derive}` : 'hwmap';
1190
+ }
1191
+ /**
1192
+ * Gets the filter capabilities for this hardware type.
1193
+ *
1194
+ * @returns Object describing which filters are supported
1195
+ *
1196
+ * @example
1197
+ * ```typescript
1198
+ * const caps = hw.getCapabilities();
1199
+ * if (caps.scale && caps.overlay) {
1200
+ * console.log('Hardware supports scaling and overlay');
1201
+ * }
1202
+ * ```
1203
+ */
1204
+ getCapabilities() {
1205
+ return this.support;
1206
+ }
1207
+ /**
1208
+ * Determines filter support for the hardware type.
1209
+ *
1210
+ * @returns Hardware filter support configuration
1211
+ *
1212
+ * @internal
1213
+ */
1214
+ getSupport() {
1215
+ switch (this.deviceType) {
1216
+ case AV_HWDEVICE_TYPE_CUDA:
1217
+ return {
1218
+ scale: true, // scale_cuda
1219
+ overlay: true, // overlay_cuda
1220
+ transpose: true, // transpose_cuda (patch 0054)
1221
+ tonemap: true, // tonemap_cuda (patch 0004)
1222
+ deinterlace: true, // bwdif_cuda, yadif_cuda
1223
+ denoise: false,
1224
+ flip: false,
1225
+ blur: true, // bilateral_cuda
1226
+ sharpen: false, // Uses NPP
1227
+ chromakey: true, // chromakey_cuda
1228
+ colorspace: true, // colorspace_cuda
1229
+ pad: false,
1230
+ stack: false,
1231
+ };
1232
+ case AV_HWDEVICE_TYPE_VAAPI:
1233
+ return {
1234
+ scale: true, // scale_vaapi
1235
+ overlay: true, // overlay_vaapi
1236
+ transpose: true, // transpose_vaapi
1237
+ tonemap: true, // tonemap_vaapi
1238
+ deinterlace: true, // deinterlace_vaapi
1239
+ denoise: true, // denoise_vaapi
1240
+ flip: false,
1241
+ blur: false,
1242
+ sharpen: true, // sharpness_vaapi
1243
+ chromakey: false,
1244
+ colorspace: false,
1245
+ pad: true, // pad_vaapi
1246
+ stack: true, // hstack_vaapi, vstack_vaapi, xstack_vaapi
1247
+ };
1248
+ case AV_HWDEVICE_TYPE_QSV:
1249
+ return {
1250
+ scale: true, // scale_qsv
1251
+ overlay: true, // overlay_qsv
1252
+ transpose: false,
1253
+ tonemap: false,
1254
+ deinterlace: true, // deinterlace_qsv
1255
+ denoise: false,
1256
+ flip: false,
1257
+ blur: false,
1258
+ sharpen: false,
1259
+ chromakey: false,
1260
+ colorspace: false,
1261
+ pad: false,
1262
+ stack: true, // hstack_qsv, vstack_qsv, xstack_qsv
1263
+ };
1264
+ case AV_HWDEVICE_TYPE_VULKAN:
1265
+ return {
1266
+ scale: true, // scale_vulkan
1267
+ overlay: true, // overlay_vulkan
1268
+ transpose: true, // transpose_vulkan
1269
+ tonemap: false,
1270
+ deinterlace: true, // bwdif_vulkan
1271
+ denoise: false,
1272
+ flip: true, // flip_vulkan, hflip_vulkan, vflip_vulkan
1273
+ blur: true, // avgblur_vulkan, gblur_vulkan
1274
+ sharpen: false,
1275
+ chromakey: false,
1276
+ colorspace: false,
1277
+ pad: false,
1278
+ stack: false,
1279
+ };
1280
+ case AV_HWDEVICE_TYPE_OPENCL:
1281
+ return {
1282
+ scale: true, // scale_opencl (patch 0006)
1283
+ overlay: true, // overlay_opencl (+ PGS support patch 0008)
1284
+ transpose: true, // transpose_opencl
1285
+ tonemap: true, // tonemap_opencl (enhanced in patch 0007)
1286
+ deinterlace: false,
1287
+ denoise: false,
1288
+ flip: false,
1289
+ blur: true, // avgblur_opencl, boxblur_opencl
1290
+ sharpen: true, // unsharp_opencl
1291
+ chromakey: true, // colorkey_opencl
1292
+ colorspace: false,
1293
+ pad: true, // pad_opencl
1294
+ stack: false,
1295
+ };
1296
+ case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
1297
+ return {
1298
+ scale: true, // scale_vt (patch 0047 adds format option)
1299
+ overlay: true, // overlay_videotoolbox (patch 0048)
1300
+ transpose: true, // transpose_vt (patch 0049, CoreImage based)
1301
+ tonemap: true, // tonemap_videotoolbox (patch 0050)
1302
+ deinterlace: true, // yadif_videotoolbox
1303
+ denoise: false,
1304
+ flip: false,
1305
+ blur: false,
1306
+ sharpen: false,
1307
+ chromakey: false,
1308
+ colorspace: false,
1309
+ pad: false,
1310
+ stack: false,
1311
+ };
1312
+ case AV_HWDEVICE_TYPE_MEDIACODEC:
1313
+ // MediaCodec is Android's hardware acceleration - mainly for decode/encode
1314
+ return {
1315
+ scale: false,
1316
+ overlay: false,
1317
+ transpose: false,
1318
+ tonemap: false,
1319
+ deinterlace: false,
1320
+ denoise: false,
1321
+ flip: false,
1322
+ blur: false,
1323
+ sharpen: false,
1324
+ chromakey: false,
1325
+ colorspace: false,
1326
+ pad: false,
1327
+ stack: false,
1328
+ };
1329
+ case AV_HWDEVICE_TYPE_RKMPP: // Rockchip - has RGA filters via patch 0046
1330
+ // Note: RKMPP uses separate RKRGA (Rockchip 2D Raster Graphic Acceleration)
1331
+ // for filtering operations, configured with --enable-rkrga
1332
+ return {
1333
+ scale: true, // scale_rkrga (patch 0046)
1334
+ overlay: true, // overlay_rkrga (patch 0046)
1335
+ transpose: false,
1336
+ tonemap: false,
1337
+ deinterlace: false,
1338
+ denoise: false,
1339
+ flip: false,
1340
+ blur: false,
1341
+ sharpen: false,
1342
+ chromakey: false,
1343
+ colorspace: false,
1344
+ pad: false,
1345
+ stack: false,
1346
+ };
1347
+ // These hardware types don't have dedicated filters - they're mainly for decode/encode
1348
+ case AV_HWDEVICE_TYPE_VDPAU: // Decode-only, deprecated in favor of VAAPI
1349
+ case AV_HWDEVICE_TYPE_DXVA2: // Windows decode-only
1350
+ case AV_HWDEVICE_TYPE_D3D11VA: // Windows decode-only
1351
+ case AV_HWDEVICE_TYPE_D3D12VA: // Has HEVC encoder but no filters
1352
+ case AV_HWDEVICE_TYPE_DRM: // Linux DRM buffer sharing, not processing
1353
+ return {
1354
+ scale: false,
1355
+ overlay: false,
1356
+ transpose: false,
1357
+ tonemap: false,
1358
+ deinterlace: false,
1359
+ denoise: false,
1360
+ flip: false,
1361
+ blur: false,
1362
+ sharpen: false,
1363
+ chromakey: false,
1364
+ colorspace: false,
1365
+ pad: false,
1366
+ stack: false,
1367
+ };
1368
+ default:
1369
+ // Unknown hardware - no support
1370
+ // NPP is not a separate hardware type, it's CUDA-based
1371
+ // We handle it through CUDA with special filter names
1372
+ return {
1373
+ scale: false,
1374
+ overlay: false,
1375
+ transpose: false,
1376
+ tonemap: false,
1377
+ deinterlace: false,
1378
+ denoise: false,
1379
+ flip: false,
1380
+ blur: false,
1381
+ sharpen: false,
1382
+ chromakey: false,
1383
+ colorspace: false,
1384
+ pad: false,
1385
+ stack: false,
1386
+ };
1387
+ }
1388
+ }
1389
+ }
1390
+ /**
1391
+ * Hardware filter chain builder with fluent API.
1392
+ * Automatically skips unsupported filters (returns null) allowing graceful fallback.
1393
+ *
1394
+ * @example
1395
+ * ```typescript
1396
+ * const hw = new HardwareFilterPresets(AV_HWDEVICE_TYPE_CUDA, 'cuda');
1397
+ * const chain = hw.chain()
1398
+ * .hwupload()
1399
+ * .scale(1920, 1080)
1400
+ * .tonemap() // Skipped if not supported
1401
+ * .hwdownload()
1402
+ * .build();
1403
+ * ```
1404
+ */
1405
+ export class HardwareFilterChainBuilder extends ChainBuilderBase {
1406
+ }
1407
+ //# sourceMappingURL=filter-presets.js.map