node-av 1.1.0 → 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 +51 -38
- package/dist/api/bitstream-filter.d.ts +180 -123
- package/dist/api/bitstream-filter.js +180 -125
- package/dist/api/bitstream-filter.js.map +1 -1
- package/dist/api/decoder.d.ts +279 -132
- package/dist/api/decoder.js +285 -142
- package/dist/api/decoder.js.map +1 -1
- package/dist/api/encoder.d.ts +246 -162
- package/dist/api/encoder.js +272 -208
- package/dist/api/encoder.js.map +1 -1
- package/dist/api/filter-presets.d.ts +690 -94
- package/dist/api/filter-presets.js +686 -102
- package/dist/api/filter-presets.js.map +1 -1
- package/dist/api/filter.d.ts +249 -213
- package/dist/api/filter.js +252 -242
- package/dist/api/filter.js.map +1 -1
- package/dist/api/hardware.d.ts +224 -117
- package/dist/api/hardware.js +380 -214
- package/dist/api/hardware.js.map +1 -1
- package/dist/api/index.d.ts +3 -3
- package/dist/api/index.js +1 -1
- package/dist/api/index.js.map +1 -1
- package/dist/api/io-stream.d.ts +65 -61
- package/dist/api/io-stream.js +43 -46
- package/dist/api/io-stream.js.map +1 -1
- package/dist/api/media-input.d.ts +242 -140
- package/dist/api/media-input.js +205 -103
- package/dist/api/media-input.js.map +1 -1
- package/dist/api/media-output.d.ts +206 -128
- package/dist/api/media-output.js +210 -128
- 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 +21 -187
- 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/audio-fifo.d.ts +127 -170
- package/dist/lib/audio-fifo.js +130 -173
- package/dist/lib/audio-fifo.js.map +1 -1
- 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 +68 -54
- package/dist/lib/bitstream-filter.js +68 -54
- package/dist/lib/bitstream-filter.js.map +1 -1
- package/dist/lib/codec-context.d.ts +316 -380
- package/dist/lib/codec-context.js +316 -381
- package/dist/lib/codec-context.js.map +1 -1
- package/dist/lib/codec-parameters.d.ts +160 -170
- package/dist/lib/codec-parameters.js +162 -172
- package/dist/lib/codec-parameters.js.map +1 -1
- package/dist/lib/codec-parser.d.ts +91 -104
- package/dist/lib/codec-parser.js +92 -103
- package/dist/lib/codec-parser.js.map +1 -1
- package/dist/lib/codec.d.ts +264 -281
- package/dist/lib/codec.js +268 -285
- package/dist/lib/codec.js.map +1 -1
- package/dist/lib/dictionary.d.ts +149 -203
- package/dist/lib/dictionary.js +158 -212
- package/dist/lib/dictionary.js.map +1 -1
- package/dist/lib/error.d.ts +96 -130
- package/dist/lib/error.js +98 -128
- package/dist/lib/error.js.map +1 -1
- package/dist/lib/filter-context.d.ts +284 -218
- package/dist/lib/filter-context.js +290 -227
- package/dist/lib/filter-context.js.map +1 -1
- package/dist/lib/filter-graph.d.ts +251 -292
- 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 +93 -111
- package/dist/lib/filter.js.map +1 -1
- package/dist/lib/format-context.d.ts +320 -428
- package/dist/lib/format-context.js +313 -385
- package/dist/lib/format-context.js.map +1 -1
- package/dist/lib/frame.d.ts +262 -405
- package/dist/lib/frame.js +263 -408
- package/dist/lib/frame.js.map +1 -1
- package/dist/lib/hardware-device-context.d.ts +149 -203
- 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 +170 -180
- 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 -1
- package/dist/lib/index.js +2 -2
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/input-format.d.ts +89 -117
- package/dist/lib/input-format.js +89 -117
- package/dist/lib/input-format.js.map +1 -1
- package/dist/lib/io-context.d.ts +209 -241
- package/dist/lib/io-context.js +220 -252
- package/dist/lib/io-context.js.map +1 -1
- package/dist/lib/log.d.ts +85 -119
- package/dist/lib/log.js +85 -122
- package/dist/lib/log.js.map +1 -1
- package/dist/lib/native-types.d.ts +117 -106
- package/dist/lib/native-types.js +0 -7
- package/dist/lib/native-types.js.map +1 -1
- package/dist/lib/option.d.ts +284 -241
- package/dist/lib/option.js +309 -249
- package/dist/lib/option.js.map +1 -1
- package/dist/lib/output-format.d.ts +77 -101
- package/dist/lib/output-format.js +77 -101
- package/dist/lib/output-format.js.map +1 -1
- package/dist/lib/packet.d.ts +172 -240
- 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 +241 -325
- 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 +129 -173
- package/dist/lib/software-scale-context.js +131 -175
- package/dist/lib/software-scale-context.js.map +1 -1
- package/dist/lib/stream.d.ts +87 -197
- package/dist/lib/stream.js +87 -197
- package/dist/lib/stream.js.map +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 +21 -12
- package/release_notes.md +43 -59
- package/CHANGELOG.md +0 -8
|
@@ -1,25 +1,34 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FilterPresets - Pre-defined filter configurations
|
|
3
|
-
*
|
|
4
|
-
* Provides convenient filter string builders for common operations.
|
|
5
|
-
* Includes both software and hardware-accelerated filter presets.
|
|
6
|
-
*
|
|
7
|
-
* Simplifies filter creation with type-safe parameter handling.
|
|
8
|
-
* Supports platform-specific hardware acceleration capabilities.
|
|
9
|
-
*
|
|
10
|
-
* @module api/filter-presets
|
|
11
|
-
*/
|
|
12
1
|
import { AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_D3D11VA, AV_HWDEVICE_TYPE_D3D12VA, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_DXVA2, AV_HWDEVICE_TYPE_MEDIACODEC, AV_HWDEVICE_TYPE_OPENCL, AV_HWDEVICE_TYPE_QSV, AV_HWDEVICE_TYPE_RKMPP, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_VDPAU, AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_VULKAN, AVFILTER_FLAG_HWDEVICE, } from '../constants/constants.js';
|
|
13
2
|
import { Filter } from '../lib/filter.js';
|
|
14
3
|
import { avGetPixFmtName, avGetSampleFmtName } from '../lib/utilities.js';
|
|
15
4
|
/**
|
|
16
5
|
* Base class for filter preset implementations.
|
|
17
|
-
* Provides common filter building methods that can be overridden.
|
|
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
|
+
* ```
|
|
18
21
|
*/
|
|
19
22
|
export class FilterPresetBase {
|
|
20
23
|
/**
|
|
21
|
-
*
|
|
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)
|
|
22
29
|
* @returns Filter string or null if not supported
|
|
30
|
+
*
|
|
31
|
+
* @see {@link https://ffmpeg.org/ffmpeg-filters.html#scale | FFmpeg scale filter}
|
|
23
32
|
*/
|
|
24
33
|
scale(width, height, options) {
|
|
25
34
|
const flags = options?.flags;
|
|
@@ -27,21 +36,47 @@ export class FilterPresetBase {
|
|
|
27
36
|
return flags ? `${base}:flags=${flags}` : base;
|
|
28
37
|
}
|
|
29
38
|
/**
|
|
30
|
-
*
|
|
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}
|
|
31
48
|
*/
|
|
32
49
|
crop(width, height, x = 0, y = 0) {
|
|
33
50
|
return `crop=${width}:${height}:${x}:${y}`;
|
|
34
51
|
}
|
|
35
52
|
/**
|
|
36
|
-
*
|
|
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}
|
|
37
59
|
*/
|
|
38
60
|
fps(fps) {
|
|
39
61
|
return `fps=${fps}`;
|
|
40
62
|
}
|
|
41
63
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
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}
|
|
45
80
|
*/
|
|
46
81
|
format(pixelFormat) {
|
|
47
82
|
if (Array.isArray(pixelFormat)) {
|
|
@@ -56,31 +91,67 @@ export class FilterPresetBase {
|
|
|
56
91
|
return `format=${formatName}`;
|
|
57
92
|
}
|
|
58
93
|
/**
|
|
59
|
-
*
|
|
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}
|
|
60
100
|
*/
|
|
61
101
|
rotate(angle) {
|
|
62
102
|
return `rotate=${angle}*PI/180`;
|
|
63
103
|
}
|
|
64
104
|
/**
|
|
65
|
-
*
|
|
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}
|
|
66
110
|
*/
|
|
67
111
|
hflip() {
|
|
68
112
|
return 'hflip';
|
|
69
113
|
}
|
|
70
114
|
/**
|
|
71
|
-
*
|
|
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}
|
|
72
120
|
*/
|
|
73
121
|
vflip() {
|
|
74
122
|
return 'vflip';
|
|
75
123
|
}
|
|
76
124
|
/**
|
|
77
|
-
*
|
|
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}
|
|
78
133
|
*/
|
|
79
134
|
fade(type, start, duration) {
|
|
80
135
|
return `fade=t=${type}:st=${start}:d=${duration}`;
|
|
81
136
|
}
|
|
82
137
|
/**
|
|
83
|
-
*
|
|
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}
|
|
84
155
|
*/
|
|
85
156
|
overlay(x = 0, y = 0, options) {
|
|
86
157
|
let filter = `overlay=${x}:${y}`;
|
|
@@ -92,13 +163,37 @@ export class FilterPresetBase {
|
|
|
92
163
|
return filter;
|
|
93
164
|
}
|
|
94
165
|
/**
|
|
95
|
-
*
|
|
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}
|
|
96
172
|
*/
|
|
97
173
|
volume(factor) {
|
|
98
174
|
return `volume=${factor}`;
|
|
99
175
|
}
|
|
100
176
|
/**
|
|
101
|
-
*
|
|
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}
|
|
102
197
|
*/
|
|
103
198
|
aformat(sampleFormat, sampleRate, channelLayout) {
|
|
104
199
|
const formatName = typeof sampleFormat === 'string' ? sampleFormat : (avGetSampleFmtName(sampleFormat) ?? 's16');
|
|
@@ -110,19 +205,38 @@ export class FilterPresetBase {
|
|
|
110
205
|
return filter;
|
|
111
206
|
}
|
|
112
207
|
/**
|
|
113
|
-
*
|
|
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}
|
|
114
215
|
*/
|
|
115
216
|
atempo(factor) {
|
|
116
217
|
return `atempo=${factor}`;
|
|
117
218
|
}
|
|
118
219
|
/**
|
|
119
|
-
*
|
|
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}
|
|
120
228
|
*/
|
|
121
229
|
afade(type, start, duration) {
|
|
122
230
|
return `afade=t=${type}:st=${start}:d=${duration}`;
|
|
123
231
|
}
|
|
124
232
|
/**
|
|
125
|
-
*
|
|
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}
|
|
126
240
|
*/
|
|
127
241
|
amix(inputs = 2, duration = 'longest') {
|
|
128
242
|
return `amix=inputs=${inputs}:duration=${duration}`;
|
|
@@ -130,13 +244,25 @@ export class FilterPresetBase {
|
|
|
130
244
|
}
|
|
131
245
|
/**
|
|
132
246
|
* Filter chain builder for composing multiple filters.
|
|
133
|
-
* Allows fluent API for building complex filter graphs.
|
|
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
|
+
* ```
|
|
134
258
|
*/
|
|
135
259
|
export class FilterChain {
|
|
136
260
|
filters = [];
|
|
137
261
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
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
|
|
140
266
|
*/
|
|
141
267
|
add(filter) {
|
|
142
268
|
if (filter) {
|
|
@@ -145,20 +271,27 @@ export class FilterChain {
|
|
|
145
271
|
return this;
|
|
146
272
|
}
|
|
147
273
|
/**
|
|
148
|
-
*
|
|
274
|
+
* Adds a custom filter string to the chain.
|
|
275
|
+
*
|
|
276
|
+
* @param filter - Custom filter string
|
|
277
|
+
* @returns This instance for chaining
|
|
149
278
|
*/
|
|
150
279
|
custom(filter) {
|
|
151
280
|
return this.add(filter);
|
|
152
281
|
}
|
|
153
282
|
/**
|
|
154
|
-
*
|
|
283
|
+
* Builds the final filter string.
|
|
284
|
+
*
|
|
155
285
|
* @param separator - Separator between filters (default: ',')
|
|
286
|
+
* @returns Combined filter string
|
|
156
287
|
*/
|
|
157
288
|
build(separator = ',') {
|
|
158
289
|
return this.filters.join(separator);
|
|
159
290
|
}
|
|
160
291
|
/**
|
|
161
|
-
*
|
|
292
|
+
* Returns the filters as an array.
|
|
293
|
+
*
|
|
294
|
+
* @returns Array of filter strings
|
|
162
295
|
*/
|
|
163
296
|
toArray() {
|
|
164
297
|
return [...this.filters];
|
|
@@ -166,75 +299,245 @@ export class FilterChain {
|
|
|
166
299
|
}
|
|
167
300
|
/**
|
|
168
301
|
* Base chain builder with common filter methods.
|
|
302
|
+
* Provides a fluent API for building filter chains using preset methods.
|
|
303
|
+
*
|
|
169
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
|
+
* ```
|
|
170
314
|
*/
|
|
171
315
|
export class ChainBuilderBase extends FilterChain {
|
|
172
316
|
presets;
|
|
317
|
+
/**
|
|
318
|
+
* @param presets - The filter presets to use
|
|
319
|
+
* @internal
|
|
320
|
+
*/
|
|
173
321
|
constructor(presets) {
|
|
174
322
|
super();
|
|
175
323
|
this.presets = presets;
|
|
176
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
|
+
*/
|
|
177
335
|
scale(width, height, options) {
|
|
178
336
|
return this.add(this.presets.scale(width, height, options));
|
|
179
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
|
+
*/
|
|
180
349
|
crop(width, height, x = 0, y = 0) {
|
|
181
350
|
return this.add(this.presets.crop(width, height, x, y));
|
|
182
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
|
+
*/
|
|
183
360
|
fps(fps) {
|
|
184
361
|
return this.add(this.presets.fps(fps));
|
|
185
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
|
+
*/
|
|
186
371
|
format(pixelFormat) {
|
|
187
372
|
return this.add(this.presets.format(pixelFormat));
|
|
188
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
|
+
*/
|
|
189
382
|
rotate(angle) {
|
|
190
383
|
return this.add(this.presets.rotate(angle));
|
|
191
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
|
+
*/
|
|
192
392
|
hflip() {
|
|
193
393
|
return this.add(this.presets.hflip());
|
|
194
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
|
+
*/
|
|
195
402
|
vflip() {
|
|
196
403
|
return this.add(this.presets.vflip());
|
|
197
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
|
+
*/
|
|
198
415
|
fade(type, start, duration) {
|
|
199
416
|
return this.add(this.presets.fade(type, start, duration));
|
|
200
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
|
+
*/
|
|
201
428
|
overlay(x = 0, y = 0, options) {
|
|
202
429
|
return this.add(this.presets.overlay(x, y, options));
|
|
203
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
|
+
*/
|
|
204
439
|
volume(factor) {
|
|
205
440
|
return this.add(this.presets.volume(factor));
|
|
206
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
|
+
*/
|
|
207
452
|
aformat(sampleFormat, sampleRate, channelLayout) {
|
|
208
453
|
return this.add(this.presets.aformat(sampleFormat, sampleRate, channelLayout));
|
|
209
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
|
+
*/
|
|
210
463
|
atempo(factor) {
|
|
211
464
|
return this.add(this.presets.atempo(factor));
|
|
212
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
|
+
*/
|
|
213
476
|
afade(type, start, duration) {
|
|
214
477
|
return this.add(this.presets.afade(type, start, duration));
|
|
215
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
|
+
*/
|
|
216
488
|
amix(inputs = 2, duration = 'longest') {
|
|
217
489
|
return this.add(this.presets.amix(inputs, duration));
|
|
218
490
|
}
|
|
219
|
-
|
|
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
|
+
*/
|
|
220
499
|
transpose(dir = 0) {
|
|
221
500
|
if ('transpose' in this.presets) {
|
|
222
501
|
return this.add(this.presets.transpose(dir));
|
|
223
502
|
}
|
|
224
503
|
return this.add(null);
|
|
225
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
|
+
*/
|
|
226
513
|
tonemap(options) {
|
|
227
514
|
if ('tonemap' in this.presets) {
|
|
228
515
|
return this.add(this.presets.tonemap(options));
|
|
229
516
|
}
|
|
230
517
|
return this.add(null);
|
|
231
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
|
+
*/
|
|
232
527
|
deinterlace(mode) {
|
|
233
528
|
if ('deinterlace' in this.presets) {
|
|
234
529
|
return this.add(this.presets.deinterlace(mode));
|
|
235
530
|
}
|
|
236
531
|
return this.add(null);
|
|
237
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
|
+
*/
|
|
238
541
|
flip(direction) {
|
|
239
542
|
if ('flip' in this.presets) {
|
|
240
543
|
return this.add(this.presets.flip(direction));
|
|
@@ -242,36 +545,78 @@ export class ChainBuilderBase extends FilterChain {
|
|
|
242
545
|
// Fallback to hflip/vflip
|
|
243
546
|
return direction === 'h' ? this.hflip() : this.vflip();
|
|
244
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
|
+
*/
|
|
245
557
|
blur(type = 'avg', radius) {
|
|
246
558
|
if ('blur' in this.presets) {
|
|
247
559
|
return this.add(this.presets.blur(type, radius));
|
|
248
560
|
}
|
|
249
561
|
return this.add(null);
|
|
250
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
|
+
*/
|
|
251
571
|
sharpen(amount) {
|
|
252
572
|
if ('sharpen' in this.presets) {
|
|
253
573
|
return this.add(this.presets.sharpen(amount));
|
|
254
574
|
}
|
|
255
575
|
return this.add(null);
|
|
256
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
|
+
*/
|
|
257
586
|
stack(type, inputs = 2) {
|
|
258
587
|
if ('stack' in this.presets) {
|
|
259
588
|
return this.add(this.presets.stack(type, inputs));
|
|
260
589
|
}
|
|
261
590
|
return this.add(null);
|
|
262
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Adds a hwupload filter to upload frames to hardware.
|
|
594
|
+
*
|
|
595
|
+
* @returns This instance for chaining
|
|
596
|
+
*/
|
|
263
597
|
hwupload() {
|
|
264
598
|
if ('hwupload' in this.presets) {
|
|
265
599
|
return this.add(this.presets.hwupload());
|
|
266
600
|
}
|
|
267
601
|
return this.add('hwupload');
|
|
268
602
|
}
|
|
603
|
+
/**
|
|
604
|
+
* Adds a hwdownload filter to download frames from hardware.
|
|
605
|
+
*
|
|
606
|
+
* @returns This instance for chaining
|
|
607
|
+
*/
|
|
269
608
|
hwdownload() {
|
|
270
609
|
if ('hwdownload' in this.presets) {
|
|
271
610
|
return this.add(this.presets.hwdownload());
|
|
272
611
|
}
|
|
273
612
|
return this.add('hwdownload');
|
|
274
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
|
+
*/
|
|
275
620
|
hwmap(derive) {
|
|
276
621
|
if ('hwmap' in this.presets) {
|
|
277
622
|
return this.add(this.presets.hwmap(derive));
|
|
@@ -281,91 +626,204 @@ export class ChainBuilderBase extends FilterChain {
|
|
|
281
626
|
}
|
|
282
627
|
/**
|
|
283
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
|
+
* ```
|
|
284
640
|
*/
|
|
285
641
|
export class FilterChainBuilder extends ChainBuilderBase {
|
|
286
642
|
}
|
|
287
643
|
/**
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
* Can be used with Filter.create() for quick setup.
|
|
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.
|
|
292
647
|
*
|
|
293
648
|
* @example
|
|
294
649
|
* ```typescript
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
* );
|
|
650
|
+
* // Static methods for individual filters
|
|
651
|
+
* const scaleFilter = FilterPresets.scale(1920, 1080);
|
|
652
|
+
* const fpsFilter = FilterPresets.fps(30);
|
|
299
653
|
*
|
|
300
|
-
* //
|
|
654
|
+
* // Chain builder for complex graphs
|
|
301
655
|
* const chain = FilterPresets.chain()
|
|
302
656
|
* .scale(1920, 1080)
|
|
303
|
-
* .
|
|
304
|
-
* .
|
|
657
|
+
* .fps(30)
|
|
658
|
+
* .fade('in', 0, 2)
|
|
305
659
|
* .build();
|
|
306
660
|
* ```
|
|
307
661
|
*/
|
|
308
662
|
export class FilterPresets extends FilterPresetBase {
|
|
309
663
|
static instance = new FilterPresets();
|
|
310
664
|
/**
|
|
311
|
-
*
|
|
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
|
+
* ```
|
|
312
676
|
*/
|
|
313
677
|
static chain() {
|
|
314
678
|
return new FilterChainBuilder(FilterPresets.instance);
|
|
315
679
|
}
|
|
316
|
-
|
|
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
|
+
*/
|
|
317
688
|
static scale(width, height, flags) {
|
|
318
689
|
const result = FilterPresets.instance.scale(width, height, { flags });
|
|
319
690
|
return result ?? '';
|
|
320
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
|
+
*/
|
|
321
701
|
static crop(width, height, x = 0, y = 0) {
|
|
322
702
|
const result = FilterPresets.instance.crop(width, height, x, y);
|
|
323
703
|
return result ?? '';
|
|
324
704
|
}
|
|
705
|
+
/**
|
|
706
|
+
* Creates an FPS filter string.
|
|
707
|
+
*
|
|
708
|
+
* @param fps - Target frame rate
|
|
709
|
+
* @returns FPS filter string
|
|
710
|
+
*/
|
|
325
711
|
static fps(fps) {
|
|
326
712
|
const result = FilterPresets.instance.fps(fps);
|
|
327
713
|
return result ?? '';
|
|
328
714
|
}
|
|
715
|
+
/**
|
|
716
|
+
* Creates a format filter string.
|
|
717
|
+
*
|
|
718
|
+
* @param pixelFormat - Target pixel format(s)
|
|
719
|
+
* @returns Format filter string
|
|
720
|
+
*/
|
|
329
721
|
static format(pixelFormat) {
|
|
330
722
|
const result = FilterPresets.instance.format(pixelFormat);
|
|
331
723
|
return result ?? '';
|
|
332
724
|
}
|
|
725
|
+
/**
|
|
726
|
+
* Creates a rotate filter string.
|
|
727
|
+
*
|
|
728
|
+
* @param angle - Rotation angle in degrees
|
|
729
|
+
* @returns Rotate filter string
|
|
730
|
+
*/
|
|
333
731
|
static rotate(angle) {
|
|
334
732
|
const result = FilterPresets.instance.rotate(angle);
|
|
335
733
|
return result ?? '';
|
|
336
734
|
}
|
|
735
|
+
/**
|
|
736
|
+
* Creates a horizontal flip filter string.
|
|
737
|
+
*
|
|
738
|
+
* @returns Horizontal flip filter string
|
|
739
|
+
*/
|
|
337
740
|
static hflip() {
|
|
338
741
|
const result = FilterPresets.instance.hflip();
|
|
339
742
|
return result ?? '';
|
|
340
743
|
}
|
|
744
|
+
/**
|
|
745
|
+
* Creates a vertical flip filter string.
|
|
746
|
+
*
|
|
747
|
+
* @returns Vertical flip filter string
|
|
748
|
+
*/
|
|
341
749
|
static vflip() {
|
|
342
750
|
const result = FilterPresets.instance.vflip();
|
|
343
751
|
return result ?? '';
|
|
344
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
|
+
*/
|
|
345
761
|
static fade(type, start, duration) {
|
|
346
762
|
const result = FilterPresets.instance.fade(type, start, duration);
|
|
347
763
|
return result ?? '';
|
|
348
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
|
+
*/
|
|
349
772
|
static overlay(x = 0, y = 0) {
|
|
350
773
|
const result = FilterPresets.instance.overlay(x, y);
|
|
351
774
|
return result ?? '';
|
|
352
775
|
}
|
|
776
|
+
/**
|
|
777
|
+
* Creates a volume filter string.
|
|
778
|
+
*
|
|
779
|
+
* @param factor - Volume multiplication factor
|
|
780
|
+
* @returns Volume filter string
|
|
781
|
+
*/
|
|
353
782
|
static volume(factor) {
|
|
354
783
|
const result = FilterPresets.instance.volume(factor);
|
|
355
784
|
return result ?? '';
|
|
356
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
|
+
*/
|
|
357
794
|
static aformat(sampleFormat, sampleRate, channelLayout) {
|
|
358
795
|
const result = FilterPresets.instance.aformat(sampleFormat, sampleRate, channelLayout);
|
|
359
796
|
return result ?? '';
|
|
360
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
|
+
*/
|
|
361
804
|
static atempo(factor) {
|
|
362
805
|
const result = FilterPresets.instance.atempo(factor);
|
|
363
806
|
return result ?? '';
|
|
364
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
|
+
*/
|
|
365
816
|
static afade(type, start, duration) {
|
|
366
817
|
const result = FilterPresets.instance.afade(type, start, duration);
|
|
367
818
|
return result ?? '';
|
|
368
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
|
+
*/
|
|
369
827
|
static amix(inputs = 2, duration = 'longest') {
|
|
370
828
|
const result = FilterPresets.instance.amix(inputs, duration);
|
|
371
829
|
return result ?? '';
|
|
@@ -373,47 +831,54 @@ export class FilterPresets extends FilterPresetBase {
|
|
|
373
831
|
}
|
|
374
832
|
/**
|
|
375
833
|
* Hardware-accelerated filter presets.
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
* Created and managed by HardwareContext for type-safe hardware operations.
|
|
834
|
+
* Provides optimized filter implementations for specific hardware types,
|
|
835
|
+
* with automatic fallback when operations aren't supported.
|
|
379
836
|
*
|
|
380
837
|
* @example
|
|
381
838
|
* ```typescript
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
* // Get hardware-specific scale filter (returns null if unsupported)
|
|
385
|
-
* const scaleFilter = hw.filterPresets.scale(1920, 1080);
|
|
839
|
+
* // Create hardware presets for CUDA
|
|
840
|
+
* const hw = new HardwareFilterPresets(AV_HWDEVICE_TYPE_CUDA, 'cuda');
|
|
386
841
|
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
* .scale(1920, 1080)
|
|
391
|
-
* .tonemap() // Skipped if not supported
|
|
392
|
-
* .custom('unsharp=5:5:1.0')
|
|
393
|
-
* .hwdownload()
|
|
394
|
-
* .build();
|
|
842
|
+
* // Check capabilities
|
|
843
|
+
* if (hw.support.scale) {
|
|
844
|
+
* const scaleFilter = hw.scale(1920, 1080);
|
|
395
845
|
* }
|
|
846
|
+
*
|
|
847
|
+
* // Use chain builder
|
|
848
|
+
* const chain = hw.chain()
|
|
849
|
+
* .hwupload()
|
|
850
|
+
* .scale(1920, 1080)
|
|
851
|
+
* .tonemap()
|
|
852
|
+
* .hwdownload()
|
|
853
|
+
* .build();
|
|
396
854
|
* ```
|
|
397
855
|
*/
|
|
398
856
|
export class HardwareFilterPresets extends FilterPresetBase {
|
|
399
857
|
deviceType;
|
|
400
|
-
|
|
858
|
+
deviceTypeName;
|
|
401
859
|
support;
|
|
402
860
|
/**
|
|
403
|
-
*
|
|
404
|
-
* @
|
|
861
|
+
* @param deviceType - Hardware device type enum
|
|
862
|
+
* @param deviceTypeName - Hardware device type name (e.g., 'cuda', 'vaapi')
|
|
405
863
|
*/
|
|
406
|
-
constructor(deviceType,
|
|
864
|
+
constructor(deviceType, deviceTypeName) {
|
|
407
865
|
super();
|
|
408
866
|
this.deviceType = deviceType;
|
|
409
|
-
this.
|
|
867
|
+
this.deviceTypeName = deviceTypeName;
|
|
410
868
|
this.support = this.getSupport();
|
|
411
869
|
}
|
|
412
870
|
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* @param filterName -
|
|
416
|
-
* @returns True if
|
|
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
|
+
* ```
|
|
417
882
|
*/
|
|
418
883
|
static isHardwareFilter(filterName) {
|
|
419
884
|
const filter = Filter.getByName(filterName);
|
|
@@ -424,14 +889,39 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
424
889
|
return (filter.flags & AVFILTER_FLAG_HWDEVICE) !== 0;
|
|
425
890
|
}
|
|
426
891
|
/**
|
|
427
|
-
*
|
|
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
|
+
* ```
|
|
428
904
|
*/
|
|
429
905
|
chain() {
|
|
430
906
|
return new HardwareFilterChainBuilder(this);
|
|
431
907
|
}
|
|
432
908
|
/**
|
|
433
|
-
*
|
|
434
|
-
*
|
|
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}
|
|
435
925
|
*/
|
|
436
926
|
scale(width, height, options) {
|
|
437
927
|
if (!this.support.scale) {
|
|
@@ -449,7 +939,7 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
449
939
|
filterName = 'scale_vt'; // VideoToolbox uses scale_vt
|
|
450
940
|
}
|
|
451
941
|
else {
|
|
452
|
-
filterName = `scale_${this.
|
|
942
|
+
filterName = `scale_${this.deviceTypeName}`;
|
|
453
943
|
}
|
|
454
944
|
let filter = `${filterName}=${width}:${height}`;
|
|
455
945
|
if (options) {
|
|
@@ -463,15 +953,21 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
463
953
|
return filter;
|
|
464
954
|
}
|
|
465
955
|
/**
|
|
466
|
-
*
|
|
467
|
-
*
|
|
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}
|
|
468
964
|
*/
|
|
469
965
|
overlay(x = 0, y = 0, options) {
|
|
470
966
|
if (!this.support.overlay) {
|
|
471
967
|
return null;
|
|
472
968
|
}
|
|
473
969
|
// Special handling for RKMPP which uses RGA
|
|
474
|
-
const filterName = this.deviceType === AV_HWDEVICE_TYPE_RKMPP ? 'overlay_rkrga' : `overlay_${this.
|
|
970
|
+
const filterName = this.deviceType === AV_HWDEVICE_TYPE_RKMPP ? 'overlay_rkrga' : `overlay_${this.deviceTypeName}`;
|
|
475
971
|
let filter = `${filterName}=${x}:${y}`;
|
|
476
972
|
if (options) {
|
|
477
973
|
for (const [key, value] of Object.entries(options)) {
|
|
@@ -481,8 +977,17 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
481
977
|
return filter;
|
|
482
978
|
}
|
|
483
979
|
/**
|
|
484
|
-
*
|
|
485
|
-
*
|
|
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
|
+
*
|
|
486
991
|
*/
|
|
487
992
|
transpose(dir = 0) {
|
|
488
993
|
if (!this.support.transpose) {
|
|
@@ -497,20 +1002,24 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
497
1002
|
filterName = 'transpose_vt'; // CoreImage-based transpose
|
|
498
1003
|
}
|
|
499
1004
|
else {
|
|
500
|
-
filterName = `transpose_${this.
|
|
1005
|
+
filterName = `transpose_${this.deviceTypeName}`;
|
|
501
1006
|
}
|
|
502
1007
|
return `${filterName}=dir=${dir}`;
|
|
503
1008
|
}
|
|
504
1009
|
/**
|
|
505
|
-
*
|
|
506
|
-
*
|
|
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
|
+
*
|
|
507
1016
|
*/
|
|
508
1017
|
tonemap(options) {
|
|
509
1018
|
if (!this.support.tonemap) {
|
|
510
1019
|
return null;
|
|
511
1020
|
}
|
|
512
1021
|
// VideoToolbox uses different filter name
|
|
513
|
-
const filterName = this.deviceType === AV_HWDEVICE_TYPE_VIDEOTOOLBOX ? 'tonemap_videotoolbox' : `tonemap_${this.
|
|
1022
|
+
const filterName = this.deviceType === AV_HWDEVICE_TYPE_VIDEOTOOLBOX ? 'tonemap_videotoolbox' : `tonemap_${this.deviceTypeName}`;
|
|
514
1023
|
let filter = filterName;
|
|
515
1024
|
if (options) {
|
|
516
1025
|
const opts = Object.entries(options)
|
|
@@ -521,8 +1030,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
521
1030
|
return filter;
|
|
522
1031
|
}
|
|
523
1032
|
/**
|
|
524
|
-
*
|
|
525
|
-
*
|
|
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
|
+
*
|
|
526
1045
|
*/
|
|
527
1046
|
deinterlace(mode) {
|
|
528
1047
|
if (!this.support.deinterlace) {
|
|
@@ -544,8 +1063,12 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
544
1063
|
}
|
|
545
1064
|
}
|
|
546
1065
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
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
|
+
*
|
|
549
1072
|
*/
|
|
550
1073
|
flip(direction) {
|
|
551
1074
|
if (!this.support.flip) {
|
|
@@ -557,8 +1080,17 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
557
1080
|
return null;
|
|
558
1081
|
}
|
|
559
1082
|
/**
|
|
560
|
-
*
|
|
561
|
-
*
|
|
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
|
+
*
|
|
562
1094
|
*/
|
|
563
1095
|
blur(type = 'avg', radius) {
|
|
564
1096
|
if (!this.support.blur) {
|
|
@@ -576,8 +1108,16 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
576
1108
|
}
|
|
577
1109
|
}
|
|
578
1110
|
/**
|
|
579
|
-
*
|
|
580
|
-
*
|
|
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
|
+
*
|
|
581
1121
|
*/
|
|
582
1122
|
sharpen(amount) {
|
|
583
1123
|
if (!this.support.sharpen) {
|
|
@@ -596,20 +1136,30 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
596
1136
|
}
|
|
597
1137
|
}
|
|
598
1138
|
/**
|
|
599
|
-
*
|
|
600
|
-
*
|
|
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
|
+
*
|
|
601
1146
|
*/
|
|
602
1147
|
stack(type, inputs = 2) {
|
|
603
1148
|
if (!this.support.stack) {
|
|
604
1149
|
return null;
|
|
605
1150
|
}
|
|
606
1151
|
if (this.deviceType === AV_HWDEVICE_TYPE_VAAPI || this.deviceType === AV_HWDEVICE_TYPE_QSV) {
|
|
607
|
-
return `${type}stack_${this.
|
|
1152
|
+
return `${type}stack_${this.deviceTypeName}=inputs=${inputs}`;
|
|
608
1153
|
}
|
|
609
1154
|
return null;
|
|
610
1155
|
}
|
|
611
1156
|
/**
|
|
612
|
-
*
|
|
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}
|
|
613
1163
|
*/
|
|
614
1164
|
hwupload() {
|
|
615
1165
|
if (this.deviceType === AV_HWDEVICE_TYPE_CUDA) {
|
|
@@ -618,25 +1168,48 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
618
1168
|
return 'hwupload';
|
|
619
1169
|
}
|
|
620
1170
|
/**
|
|
621
|
-
*
|
|
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}
|
|
622
1176
|
*/
|
|
623
1177
|
hwdownload() {
|
|
624
1178
|
return 'hwdownload';
|
|
625
1179
|
}
|
|
626
1180
|
/**
|
|
627
|
-
*
|
|
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}
|
|
628
1187
|
*/
|
|
629
1188
|
hwmap(derive) {
|
|
630
1189
|
return derive ? `hwmap=derive_device=${derive}` : 'hwmap';
|
|
631
1190
|
}
|
|
632
1191
|
/**
|
|
633
|
-
*
|
|
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
|
+
* ```
|
|
634
1203
|
*/
|
|
635
1204
|
getCapabilities() {
|
|
636
1205
|
return this.support;
|
|
637
1206
|
}
|
|
638
1207
|
/**
|
|
639
|
-
*
|
|
1208
|
+
* Determines filter support for the hardware type.
|
|
1209
|
+
*
|
|
1210
|
+
* @returns Hardware filter support configuration
|
|
1211
|
+
*
|
|
1212
|
+
* @internal
|
|
640
1213
|
*/
|
|
641
1214
|
getSupport() {
|
|
642
1215
|
switch (this.deviceType) {
|
|
@@ -816,7 +1389,18 @@ export class HardwareFilterPresets extends FilterPresetBase {
|
|
|
816
1389
|
}
|
|
817
1390
|
/**
|
|
818
1391
|
* Hardware filter chain builder with fluent API.
|
|
819
|
-
* Automatically skips unsupported filters (returns null).
|
|
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
|
+
* ```
|
|
820
1404
|
*/
|
|
821
1405
|
export class HardwareFilterChainBuilder extends ChainBuilderBase {
|
|
822
1406
|
}
|