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.
- package/README.md +56 -41
- package/dist/api/bitstream-filter.d.ts +180 -123
- package/dist/api/bitstream-filter.js +182 -126
- package/dist/api/bitstream-filter.js.map +1 -1
- package/dist/api/decoder.d.ts +286 -130
- package/dist/api/decoder.js +321 -159
- package/dist/api/decoder.js.map +1 -1
- package/dist/api/encoder.d.ts +254 -158
- package/dist/api/encoder.js +326 -298
- package/dist/api/encoder.js.map +1 -1
- package/dist/api/filter-presets.d.ts +912 -0
- package/dist/api/filter-presets.js +1407 -0
- package/dist/api/filter-presets.js.map +1 -0
- package/dist/api/filter.d.ts +280 -284
- package/dist/api/filter.js +435 -509
- package/dist/api/filter.js.map +1 -1
- package/dist/api/hardware.d.ts +226 -159
- package/dist/api/hardware.js +405 -287
- package/dist/api/hardware.js.map +1 -1
- package/dist/api/index.d.ts +3 -2
- package/dist/api/index.js +1 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/io-stream.d.ts +65 -61
- package/dist/api/io-stream.js +45 -47
- package/dist/api/io-stream.js.map +1 -1
- package/dist/api/media-input.d.ts +244 -141
- package/dist/api/media-input.js +207 -104
- package/dist/api/media-input.js.map +1 -1
- package/dist/api/media-output.d.ts +206 -128
- package/dist/api/media-output.js +212 -129
- package/dist/api/media-output.js.map +1 -1
- package/dist/api/pipeline.d.ts +168 -38
- package/dist/api/pipeline.js +238 -14
- package/dist/api/pipeline.js.map +1 -1
- package/dist/api/types.d.ts +22 -182
- package/dist/api/utilities/audio-sample.d.ts +1 -1
- package/dist/api/utilities/image.d.ts +1 -1
- package/dist/api/utilities/media-type.d.ts +1 -1
- package/dist/api/utilities/pixel-format.d.ts +1 -1
- package/dist/api/utilities/sample-format.d.ts +1 -1
- package/dist/api/utilities/timestamp.d.ts +1 -1
- package/dist/api/utils.d.ts +1 -2
- package/dist/api/utils.js +9 -0
- package/dist/api/utils.js.map +1 -1
- package/dist/{lib → constants}/channel-layouts.d.ts +1 -1
- package/dist/constants/channel-layouts.js.map +1 -0
- package/dist/{lib → constants}/constants.d.ts +19 -4
- package/dist/{lib → constants}/constants.js +15 -1
- package/dist/constants/constants.js.map +1 -0
- package/dist/constants/decoders.d.ts +609 -0
- package/dist/constants/decoders.js +617 -0
- package/dist/constants/decoders.js.map +1 -0
- package/dist/constants/encoders.d.ts +285 -0
- package/dist/constants/encoders.js +298 -0
- package/dist/constants/encoders.js.map +1 -0
- package/dist/constants/index.d.ts +4 -0
- package/dist/constants/index.js +5 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/audio-fifo.d.ts +128 -171
- package/dist/lib/audio-fifo.js +130 -173
- package/dist/lib/audio-fifo.js.map +1 -1
- package/dist/lib/binding.d.ts +7 -5
- package/dist/lib/binding.js +5 -0
- package/dist/lib/binding.js.map +1 -1
- package/dist/lib/bitstream-filter-context.d.ts +139 -184
- package/dist/lib/bitstream-filter-context.js +139 -188
- package/dist/lib/bitstream-filter-context.js.map +1 -1
- package/dist/lib/bitstream-filter.d.ts +69 -55
- package/dist/lib/bitstream-filter.js +68 -54
- package/dist/lib/bitstream-filter.js.map +1 -1
- package/dist/lib/codec-context.d.ts +317 -381
- package/dist/lib/codec-context.js +316 -381
- package/dist/lib/codec-context.js.map +1 -1
- package/dist/lib/codec-parameters.d.ts +161 -171
- package/dist/lib/codec-parameters.js +162 -172
- package/dist/lib/codec-parameters.js.map +1 -1
- package/dist/lib/codec-parser.d.ts +92 -105
- package/dist/lib/codec-parser.js +92 -103
- package/dist/lib/codec-parser.js.map +1 -1
- package/dist/lib/codec.d.ts +328 -217
- package/dist/lib/codec.js +392 -218
- package/dist/lib/codec.js.map +1 -1
- package/dist/lib/dictionary.d.ts +150 -204
- package/dist/lib/dictionary.js +159 -213
- package/dist/lib/dictionary.js.map +1 -1
- package/dist/lib/error.d.ts +97 -131
- package/dist/lib/error.js +98 -128
- package/dist/lib/error.js.map +1 -1
- package/dist/lib/filter-context.d.ts +317 -194
- package/dist/lib/filter-context.js +335 -200
- package/dist/lib/filter-context.js.map +1 -1
- package/dist/lib/filter-graph.d.ts +252 -293
- package/dist/lib/filter-graph.js +253 -294
- package/dist/lib/filter-graph.js.map +1 -1
- package/dist/lib/filter-inout.d.ts +87 -95
- package/dist/lib/filter-inout.js +87 -95
- package/dist/lib/filter-inout.js.map +1 -1
- package/dist/lib/filter.d.ts +93 -111
- package/dist/lib/filter.js +94 -112
- package/dist/lib/filter.js.map +1 -1
- package/dist/lib/format-context.d.ts +321 -429
- package/dist/lib/format-context.js +314 -386
- package/dist/lib/format-context.js.map +1 -1
- package/dist/lib/frame.d.ts +263 -406
- package/dist/lib/frame.js +263 -408
- package/dist/lib/frame.js.map +1 -1
- package/dist/lib/hardware-device-context.d.ts +150 -204
- package/dist/lib/hardware-device-context.js +149 -203
- package/dist/lib/hardware-device-context.js.map +1 -1
- package/dist/lib/hardware-frames-context.d.ts +171 -181
- package/dist/lib/hardware-frames-context.js +171 -181
- package/dist/lib/hardware-frames-context.js.map +1 -1
- package/dist/lib/index.d.ts +2 -3
- package/dist/lib/index.js +2 -5
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/input-format.d.ts +90 -118
- package/dist/lib/input-format.js +89 -117
- package/dist/lib/input-format.js.map +1 -1
- package/dist/lib/io-context.d.ts +210 -242
- package/dist/lib/io-context.js +221 -253
- package/dist/lib/io-context.js.map +1 -1
- package/dist/lib/log.d.ts +86 -120
- package/dist/lib/log.js +85 -122
- package/dist/lib/log.js.map +1 -1
- package/dist/lib/native-types.d.ts +127 -112
- package/dist/lib/native-types.js +9 -0
- package/dist/lib/native-types.js.map +1 -1
- package/dist/lib/option.d.ts +285 -242
- package/dist/lib/option.js +310 -250
- package/dist/lib/option.js.map +1 -1
- package/dist/lib/output-format.d.ts +78 -102
- package/dist/lib/output-format.js +77 -101
- package/dist/lib/output-format.js.map +1 -1
- package/dist/lib/packet.d.ts +173 -241
- package/dist/lib/packet.js +172 -241
- package/dist/lib/packet.js.map +1 -1
- package/dist/lib/rational.d.ts +0 -2
- package/dist/lib/rational.js +0 -2
- package/dist/lib/rational.js.map +1 -1
- package/dist/lib/software-resample-context.d.ts +242 -326
- package/dist/lib/software-resample-context.js +242 -326
- package/dist/lib/software-resample-context.js.map +1 -1
- package/dist/lib/software-scale-context.d.ts +130 -174
- package/dist/lib/software-scale-context.js +132 -176
- package/dist/lib/software-scale-context.js.map +1 -1
- package/dist/lib/stream.d.ts +88 -198
- package/dist/lib/stream.js +87 -197
- package/dist/lib/stream.js.map +1 -1
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/utilities.d.ts +372 -181
- package/dist/lib/utilities.js +373 -182
- package/dist/lib/utilities.js.map +1 -1
- package/install/check.js +0 -1
- package/package.json +32 -24
- package/release_notes.md +43 -13
- package/CHANGELOG.md +0 -8
- package/dist/lib/channel-layouts.js.map +0 -1
- package/dist/lib/constants.js.map +0 -1
- /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
|