@gannochenko/staticstripes 0.0.1
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/.prettierrc +8 -0
- package/Makefile +69 -0
- package/dist/asset-manager.d.ts +16 -0
- package/dist/asset-manager.d.ts.map +1 -0
- package/dist/asset-manager.js +50 -0
- package/dist/asset-manager.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +257 -0
- package/dist/cli.js.map +1 -0
- package/dist/container-renderer.d.ts +21 -0
- package/dist/container-renderer.d.ts.map +1 -0
- package/dist/container-renderer.js +149 -0
- package/dist/container-renderer.js.map +1 -0
- package/dist/expression-parser.d.ts +63 -0
- package/dist/expression-parser.d.ts.map +1 -0
- package/dist/expression-parser.js +145 -0
- package/dist/expression-parser.js.map +1 -0
- package/dist/ffmpeg.d.ts +375 -0
- package/dist/ffmpeg.d.ts.map +1 -0
- package/dist/ffmpeg.js +997 -0
- package/dist/ffmpeg.js.map +1 -0
- package/dist/ffprobe.d.ts +2 -0
- package/dist/ffprobe.d.ts.map +1 -0
- package/dist/ffprobe.js +31 -0
- package/dist/ffprobe.js.map +1 -0
- package/dist/html-parser.d.ts +56 -0
- package/dist/html-parser.d.ts.map +1 -0
- package/dist/html-parser.js +208 -0
- package/dist/html-parser.js.map +1 -0
- package/dist/html-project-parser.d.ts +169 -0
- package/dist/html-project-parser.d.ts.map +1 -0
- package/dist/html-project-parser.js +954 -0
- package/dist/html-project-parser.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/label-generator.d.ts +35 -0
- package/dist/label-generator.d.ts.map +1 -0
- package/dist/label-generator.js +69 -0
- package/dist/label-generator.js.map +1 -0
- package/dist/project.d.ts +29 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +137 -0
- package/dist/project.js.map +1 -0
- package/dist/sample-sequences.d.ts +5 -0
- package/dist/sample-sequences.d.ts.map +1 -0
- package/dist/sample-sequences.js +199 -0
- package/dist/sample-sequences.js.map +1 -0
- package/dist/sample-streams.d.ts +2 -0
- package/dist/sample-streams.d.ts.map +1 -0
- package/dist/sample-streams.js +109 -0
- package/dist/sample-streams.js.map +1 -0
- package/dist/sequence.d.ts +21 -0
- package/dist/sequence.d.ts.map +1 -0
- package/dist/sequence.js +269 -0
- package/dist/sequence.js.map +1 -0
- package/dist/stream.d.ts +135 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +779 -0
- package/dist/stream.js.map +1 -0
- package/dist/type.d.ts +73 -0
- package/dist/type.d.ts.map +1 -0
- package/dist/type.js +3 -0
- package/dist/type.js.map +1 -0
- package/eslint.config.js +44 -0
- package/package.json +50 -0
- package/src/asset-manager.ts +55 -0
- package/src/cli.ts +306 -0
- package/src/container-renderer.ts +190 -0
- package/src/expression-parser.test.ts +459 -0
- package/src/expression-parser.ts +199 -0
- package/src/ffmpeg.ts +1403 -0
- package/src/ffprobe.ts +29 -0
- package/src/html-parser.ts +221 -0
- package/src/html-project-parser.ts +1195 -0
- package/src/index.ts +9 -0
- package/src/label-generator.ts +74 -0
- package/src/project.ts +180 -0
- package/src/sample-sequences.ts +225 -0
- package/src/sample-streams.ts +142 -0
- package/src/sequence.ts +330 -0
- package/src/stream.ts +1012 -0
- package/src/type.ts +81 -0
- package/tsconfig.json +24 -0
package/dist/stream.js
ADDED
|
@@ -0,0 +1,779 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Stream = exports.FilterBuffer = exports.VisualFilter = exports.Colors = exports.ChromakeyBlend = exports.ChromakeySimilarity = exports.Direction = exports.AMBIENT = exports.PILLARBOX = void 0;
|
|
4
|
+
exports.makeStream = makeStream;
|
|
5
|
+
exports.makeSilentStream = makeSilentStream;
|
|
6
|
+
exports.makeBlankStream = makeBlankStream;
|
|
7
|
+
const ffmpeg_1 = require("./ffmpeg");
|
|
8
|
+
exports.PILLARBOX = 'pillarbox';
|
|
9
|
+
exports.AMBIENT = 'ambient';
|
|
10
|
+
var Direction;
|
|
11
|
+
(function (Direction) {
|
|
12
|
+
Direction[Direction["CW"] = 0] = "CW";
|
|
13
|
+
Direction[Direction["CW2"] = 1] = "CW2";
|
|
14
|
+
Direction[Direction["CCW"] = 2] = "CCW";
|
|
15
|
+
Direction[Direction["CCW2"] = 3] = "CCW2";
|
|
16
|
+
})(Direction || (exports.Direction = Direction = {}));
|
|
17
|
+
var ChromakeySimilarity;
|
|
18
|
+
(function (ChromakeySimilarity) {
|
|
19
|
+
ChromakeySimilarity[ChromakeySimilarity["Strict"] = 0.1] = "Strict";
|
|
20
|
+
ChromakeySimilarity[ChromakeySimilarity["Good"] = 0.3] = "Good";
|
|
21
|
+
ChromakeySimilarity[ChromakeySimilarity["Forgiving"] = 0.5] = "Forgiving";
|
|
22
|
+
ChromakeySimilarity[ChromakeySimilarity["Loose"] = 0.7] = "Loose";
|
|
23
|
+
})(ChromakeySimilarity || (exports.ChromakeySimilarity = ChromakeySimilarity = {}));
|
|
24
|
+
var ChromakeyBlend;
|
|
25
|
+
(function (ChromakeyBlend) {
|
|
26
|
+
ChromakeyBlend[ChromakeyBlend["Hard"] = 0] = "Hard";
|
|
27
|
+
ChromakeyBlend[ChromakeyBlend["Smooth"] = 0.1] = "Smooth";
|
|
28
|
+
ChromakeyBlend[ChromakeyBlend["Soft"] = 0.2] = "Soft";
|
|
29
|
+
})(ChromakeyBlend || (exports.ChromakeyBlend = ChromakeyBlend = {}));
|
|
30
|
+
var Colors;
|
|
31
|
+
(function (Colors) {
|
|
32
|
+
Colors["Transparent"] = "#00000000";
|
|
33
|
+
})(Colors || (exports.Colors = Colors = {}));
|
|
34
|
+
var VisualFilter;
|
|
35
|
+
(function (VisualFilter) {
|
|
36
|
+
VisualFilter["InstagramClarendon"] = "instagram-clarendon";
|
|
37
|
+
VisualFilter["InstagramGingham"] = "instagram-gingham";
|
|
38
|
+
VisualFilter["InstagramJuno"] = "instagram-juno";
|
|
39
|
+
VisualFilter["InstagramLark"] = "instagram-lark";
|
|
40
|
+
VisualFilter["InstagramLudwig"] = "instagram-ludwig";
|
|
41
|
+
VisualFilter["InstagramNashville"] = "instagram-nashville";
|
|
42
|
+
VisualFilter["InstagramValencia"] = "instagram-valencia";
|
|
43
|
+
VisualFilter["InstagramXProII"] = "instagram-xpro2";
|
|
44
|
+
VisualFilter["InstagramWillow"] = "instagram-willow";
|
|
45
|
+
VisualFilter["InstagramLoFi"] = "instagram-lofi";
|
|
46
|
+
VisualFilter["InstagramInkwell"] = "instagram-inkwell";
|
|
47
|
+
VisualFilter["InstagramMoon"] = "instagram-moon";
|
|
48
|
+
VisualFilter["InstagramHudson"] = "instagram-hudson";
|
|
49
|
+
VisualFilter["InstagramToaster"] = "instagram-toaster";
|
|
50
|
+
VisualFilter["InstagramWalden"] = "instagram-walden";
|
|
51
|
+
VisualFilter["InstagramRise"] = "instagram-rise";
|
|
52
|
+
VisualFilter["InstagramAmaro"] = "instagram-amaro";
|
|
53
|
+
VisualFilter["InstagramMayfair"] = "instagram-mayfair";
|
|
54
|
+
VisualFilter["InstagramEarlybird"] = "instagram-earlybird";
|
|
55
|
+
VisualFilter["InstagramSutro"] = "instagram-sutro";
|
|
56
|
+
VisualFilter["InstagramAden"] = "instagram-aden";
|
|
57
|
+
VisualFilter["InstagramCrema"] = "instagram-crema";
|
|
58
|
+
})(VisualFilter || (exports.VisualFilter = VisualFilter = {}));
|
|
59
|
+
class FilterBuffer {
|
|
60
|
+
filters = [];
|
|
61
|
+
append(filter) {
|
|
62
|
+
this.filters.push(filter);
|
|
63
|
+
}
|
|
64
|
+
render() {
|
|
65
|
+
return this.filters.map((filter) => filter.render()).join(';');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.FilterBuffer = FilterBuffer;
|
|
69
|
+
function makeStream(label, buf) {
|
|
70
|
+
return new Stream(label, buf);
|
|
71
|
+
}
|
|
72
|
+
function makeSilentStream(duration, buf) {
|
|
73
|
+
const filter = (0, ffmpeg_1.makeAnullsrc)({ duration });
|
|
74
|
+
buf.append(filter);
|
|
75
|
+
return new Stream(filter.outputs[0], buf);
|
|
76
|
+
}
|
|
77
|
+
function makeBlankStream(duration, width, height, fps, buf) {
|
|
78
|
+
const filter = (0, ffmpeg_1.makeColor)({
|
|
79
|
+
duration,
|
|
80
|
+
width,
|
|
81
|
+
height,
|
|
82
|
+
fps,
|
|
83
|
+
color: '#00000000',
|
|
84
|
+
});
|
|
85
|
+
buf.append(filter);
|
|
86
|
+
return new Stream(filter.outputs[0], buf);
|
|
87
|
+
}
|
|
88
|
+
class Stream {
|
|
89
|
+
looseEnd;
|
|
90
|
+
buf;
|
|
91
|
+
constructor(looseEnd, buf) {
|
|
92
|
+
this.looseEnd = looseEnd;
|
|
93
|
+
this.buf = buf;
|
|
94
|
+
}
|
|
95
|
+
trim(start, end) {
|
|
96
|
+
const res = (0, ffmpeg_1.makeTrim)([this.looseEnd], start, end);
|
|
97
|
+
this.looseEnd = res.outputs[0];
|
|
98
|
+
this.buf.append(res);
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
fitOutputSimple(dimensions) {
|
|
102
|
+
// Step 1: Scale video to fit within dimensions while maintaining aspect ratio
|
|
103
|
+
// Using 'force_original_aspect_ratio=decrease' ensures the video fits inside the box
|
|
104
|
+
const scaleRes = (0, ffmpeg_1.makeScale)([this.looseEnd], {
|
|
105
|
+
width: dimensions.width,
|
|
106
|
+
height: dimensions.height,
|
|
107
|
+
flags: 'force_original_aspect_ratio=decrease',
|
|
108
|
+
});
|
|
109
|
+
this.looseEnd = scaleRes.outputs[0];
|
|
110
|
+
this.buf.append(scaleRes);
|
|
111
|
+
// Step 2: Pad to exact dimensions with black bars (centered)
|
|
112
|
+
const padRes = (0, ffmpeg_1.makePad)([this.looseEnd], {
|
|
113
|
+
width: dimensions.width,
|
|
114
|
+
height: dimensions.height,
|
|
115
|
+
// x and y default to '(ow-iw)/2' and '(oh-ih)/2' which centers the video
|
|
116
|
+
});
|
|
117
|
+
this.looseEnd = padRes.outputs[0];
|
|
118
|
+
this.buf.append(padRes);
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
fitOutputCover(dimensions) {
|
|
122
|
+
// Step 1: Scale video to cover dimensions while maintaining aspect ratio
|
|
123
|
+
// Using 'force_original_aspect_ratio=increase' ensures the video fills the entire box
|
|
124
|
+
const scaleRes = (0, ffmpeg_1.makeScale)([this.looseEnd], {
|
|
125
|
+
width: dimensions.width,
|
|
126
|
+
height: dimensions.height,
|
|
127
|
+
flags: 'force_original_aspect_ratio=increase',
|
|
128
|
+
});
|
|
129
|
+
this.looseEnd = scaleRes.outputs[0];
|
|
130
|
+
this.buf.append(scaleRes);
|
|
131
|
+
// Step 2: Crop to exact dimensions (centered)
|
|
132
|
+
const cropRes = (0, ffmpeg_1.makeCrop)([this.looseEnd], {
|
|
133
|
+
width: dimensions.width,
|
|
134
|
+
height: dimensions.height,
|
|
135
|
+
// x and y default to '(in_w-out_w)/2' and '(in_h-out_h)/2' which centers the crop
|
|
136
|
+
});
|
|
137
|
+
this.looseEnd = cropRes.outputs[0];
|
|
138
|
+
this.buf.append(cropRes);
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
fitOutputContain(dimensions, options = {}) {
|
|
142
|
+
if (options.ambient) {
|
|
143
|
+
const blurStrength = options.ambient?.blurStrength ?? 20;
|
|
144
|
+
const brightness = options.ambient?.brightness ?? -0.3;
|
|
145
|
+
const saturation = options.ambient?.saturation ?? 0.8;
|
|
146
|
+
// Split input into 2 streams: background and foreground
|
|
147
|
+
const splitRes = (0, ffmpeg_1.makeSplit)([this.looseEnd]);
|
|
148
|
+
this.buf.append(splitRes);
|
|
149
|
+
const [bgLabel, fgLabel] = splitRes.outputs;
|
|
150
|
+
// // Background stream: cover + blur + darken
|
|
151
|
+
const bgScaleRes = (0, ffmpeg_1.makeScale)([bgLabel], {
|
|
152
|
+
width: dimensions.width,
|
|
153
|
+
height: dimensions.height,
|
|
154
|
+
flags: 'force_original_aspect_ratio=increase',
|
|
155
|
+
});
|
|
156
|
+
this.buf.append(bgScaleRes);
|
|
157
|
+
const bgCropRes = (0, ffmpeg_1.makeCrop)(bgScaleRes.outputs, {
|
|
158
|
+
width: dimensions.width,
|
|
159
|
+
height: dimensions.height,
|
|
160
|
+
});
|
|
161
|
+
this.buf.append(bgCropRes);
|
|
162
|
+
const bgBlurRes = (0, ffmpeg_1.makeGblur)(bgCropRes.outputs, {
|
|
163
|
+
sigma: blurStrength,
|
|
164
|
+
steps: 2,
|
|
165
|
+
});
|
|
166
|
+
this.buf.append(bgBlurRes);
|
|
167
|
+
const bgFinal = (0, ffmpeg_1.makeEq)(bgBlurRes.outputs, {
|
|
168
|
+
brightness,
|
|
169
|
+
saturation,
|
|
170
|
+
});
|
|
171
|
+
this.buf.append(bgFinal);
|
|
172
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
173
|
+
const fgScale = (0, ffmpeg_1.makeScale)([fgLabel], {
|
|
174
|
+
width: dimensions.width,
|
|
175
|
+
height: dimensions.height,
|
|
176
|
+
flags: 'force_original_aspect_ratio=decrease',
|
|
177
|
+
});
|
|
178
|
+
this.buf.append(fgScale);
|
|
179
|
+
// Step 2: Pad to exact dimensions with black bars (centered)
|
|
180
|
+
const fgFinal = (0, ffmpeg_1.makePad)(fgScale.outputs, {
|
|
181
|
+
width: dimensions.width,
|
|
182
|
+
height: dimensions.height,
|
|
183
|
+
color: '#00000000', // transparent
|
|
184
|
+
// x and y default to '(ow-iw)/2' and '(oh-ih)/2' which centers the video
|
|
185
|
+
});
|
|
186
|
+
this.buf.append(fgFinal);
|
|
187
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
188
|
+
// Overlay foreground centered on background
|
|
189
|
+
// (W-w)/2 and (H-h)/2 center the overlay on the background
|
|
190
|
+
const overlayRes = (0, ffmpeg_1.makeOverlay)([bgFinal.outputs[0], fgFinal.outputs[0]], {
|
|
191
|
+
x: '(W-w)/2',
|
|
192
|
+
y: '(H-h)/2',
|
|
193
|
+
});
|
|
194
|
+
this.buf.append(overlayRes);
|
|
195
|
+
this.looseEnd = overlayRes.outputs[0];
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
// usual pillarbox
|
|
199
|
+
const color = options?.pillarbox?.color ?? '#000000';
|
|
200
|
+
const scaleRes = (0, ffmpeg_1.makeScale)([this.looseEnd], {
|
|
201
|
+
width: dimensions.width,
|
|
202
|
+
height: dimensions.height,
|
|
203
|
+
flags: 'force_original_aspect_ratio=decrease',
|
|
204
|
+
});
|
|
205
|
+
this.looseEnd = scaleRes.outputs[0];
|
|
206
|
+
this.buf.append(scaleRes);
|
|
207
|
+
// Step 2: Pad to exact dimensions with black bars (centered)
|
|
208
|
+
const padRes = (0, ffmpeg_1.makePad)([this.looseEnd], {
|
|
209
|
+
width: dimensions.width,
|
|
210
|
+
height: dimensions.height,
|
|
211
|
+
color: color,
|
|
212
|
+
// x and y default to '(ow-iw)/2' and '(oh-ih)/2' which centers the video
|
|
213
|
+
});
|
|
214
|
+
this.looseEnd = padRes.outputs[0];
|
|
215
|
+
this.buf.append(padRes);
|
|
216
|
+
}
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
chromakey(parameters) {
|
|
220
|
+
// Apply chromakey filter
|
|
221
|
+
const chromakeyRes = (0, ffmpeg_1.makeChromakey)([this.looseEnd], {
|
|
222
|
+
color: parameters.color,
|
|
223
|
+
similarity: parameters.similarity,
|
|
224
|
+
blend: parameters.blend,
|
|
225
|
+
});
|
|
226
|
+
this.looseEnd = chromakeyRes.outputs[0];
|
|
227
|
+
this.buf.append(chromakeyRes);
|
|
228
|
+
return this;
|
|
229
|
+
}
|
|
230
|
+
fps(value) {
|
|
231
|
+
const res = (0, ffmpeg_1.makeFps)([this.looseEnd], value);
|
|
232
|
+
this.looseEnd = res.outputs[0];
|
|
233
|
+
this.buf.append(res);
|
|
234
|
+
return this;
|
|
235
|
+
}
|
|
236
|
+
blur(strength) {
|
|
237
|
+
const res = (0, ffmpeg_1.makeGblur)([this.looseEnd], {
|
|
238
|
+
sigma: strength,
|
|
239
|
+
});
|
|
240
|
+
this.looseEnd = res.outputs[0];
|
|
241
|
+
this.buf.append(res);
|
|
242
|
+
return this;
|
|
243
|
+
}
|
|
244
|
+
fade(options) {
|
|
245
|
+
const res = (0, ffmpeg_1.makeFade)([this.looseEnd], options);
|
|
246
|
+
this.looseEnd = res.outputs[0];
|
|
247
|
+
this.buf.append(res);
|
|
248
|
+
return this;
|
|
249
|
+
}
|
|
250
|
+
transpose(value) {
|
|
251
|
+
const res = (0, ffmpeg_1.makeTranspose)([this.looseEnd], value);
|
|
252
|
+
this.looseEnd = res.outputs[0];
|
|
253
|
+
this.buf.append(res);
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
cwRotate(direction) {
|
|
257
|
+
switch (direction) {
|
|
258
|
+
case Direction.CW:
|
|
259
|
+
// 90° clockwise: transpose=1
|
|
260
|
+
this.transpose(1);
|
|
261
|
+
break;
|
|
262
|
+
case Direction.CCW:
|
|
263
|
+
// 90° counterclockwise: transpose=2
|
|
264
|
+
this.transpose(2);
|
|
265
|
+
break;
|
|
266
|
+
case Direction.CW2:
|
|
267
|
+
case Direction.CCW2:
|
|
268
|
+
// 180° rotation (same for both directions): hflip + vflip
|
|
269
|
+
const hflipRes = (0, ffmpeg_1.makeHflip)([this.looseEnd]);
|
|
270
|
+
this.looseEnd = hflipRes.outputs[0];
|
|
271
|
+
this.buf.append(hflipRes);
|
|
272
|
+
const vflipRes = (0, ffmpeg_1.makeVflip)([this.looseEnd]);
|
|
273
|
+
this.looseEnd = vflipRes.outputs[0];
|
|
274
|
+
this.buf.append(vflipRes);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
return this;
|
|
278
|
+
}
|
|
279
|
+
concatStream(stream) {
|
|
280
|
+
return this.concatStreams([stream]);
|
|
281
|
+
}
|
|
282
|
+
concatStreams(streams) {
|
|
283
|
+
// todo: check streams type here, it can either be all audio or all video
|
|
284
|
+
const res = (0, ffmpeg_1.makeConcat)([
|
|
285
|
+
this.looseEnd,
|
|
286
|
+
...streams.map((st) => st.getLooseEnd()),
|
|
287
|
+
]);
|
|
288
|
+
this.looseEnd = res.outputs[0];
|
|
289
|
+
if (res.outputs.length > 1) {
|
|
290
|
+
throw new Error('concat produced several outputs, possible mixup between video and audio streams');
|
|
291
|
+
}
|
|
292
|
+
this.buf.append(res);
|
|
293
|
+
return this;
|
|
294
|
+
}
|
|
295
|
+
mixStream(stream, options) {
|
|
296
|
+
return this.mixStreams([stream], options);
|
|
297
|
+
}
|
|
298
|
+
mixStreams(streams, options) {
|
|
299
|
+
const res = (0, ffmpeg_1.makeAmix)([this.looseEnd, ...streams.map((st) => st.getLooseEnd())], options);
|
|
300
|
+
this.looseEnd = res.outputs[0];
|
|
301
|
+
this.buf.append(res);
|
|
302
|
+
return this;
|
|
303
|
+
}
|
|
304
|
+
tPad(options = {}) {
|
|
305
|
+
const res = (0, ffmpeg_1.makeTPad)([this.looseEnd], options);
|
|
306
|
+
this.looseEnd = res.outputs[0];
|
|
307
|
+
this.buf.append(res);
|
|
308
|
+
return this;
|
|
309
|
+
}
|
|
310
|
+
/*
|
|
311
|
+
this stream becomes the bottom layer, and the joining stream - top layer
|
|
312
|
+
For video: uses overlay filter
|
|
313
|
+
For audio: uses amix filter
|
|
314
|
+
*/
|
|
315
|
+
overlayStream(stream, options) {
|
|
316
|
+
const offset = options.offset;
|
|
317
|
+
const flip = !!options.flipLayers;
|
|
318
|
+
const isAudio = this.looseEnd.isAudio;
|
|
319
|
+
// Validate that both streams are of the same type
|
|
320
|
+
if (isAudio !== stream.getLooseEnd().isAudio) {
|
|
321
|
+
throw new Error('overlayStream: both streams must be of the same type (both video or both audio)');
|
|
322
|
+
}
|
|
323
|
+
if (!offset || !offset.otherStreamOffsetLeft) {
|
|
324
|
+
// usual overlay/mix, no offset
|
|
325
|
+
if (isAudio) {
|
|
326
|
+
const res = (0, ffmpeg_1.makeAmix)([this.looseEnd, stream.getLooseEnd()]);
|
|
327
|
+
this.looseEnd = res.outputs[0];
|
|
328
|
+
this.buf.append(res);
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
const res = (0, ffmpeg_1.makeOverlay)(flip
|
|
332
|
+
? [stream.getLooseEnd(), this.looseEnd]
|
|
333
|
+
: [this.looseEnd, stream.getLooseEnd()]);
|
|
334
|
+
this.looseEnd = res.outputs[0];
|
|
335
|
+
this.buf.append(res);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
if (offset.streamDuration === undefined) {
|
|
340
|
+
throw new Error('exact duration of the fragment in the stream must be provided');
|
|
341
|
+
}
|
|
342
|
+
if (offset.otherStreamDuration === undefined) {
|
|
343
|
+
throw new Error('exact duration of the fragment in the joining stream must be provided');
|
|
344
|
+
}
|
|
345
|
+
const offsetLeft = offset.otherStreamOffsetLeft;
|
|
346
|
+
if (offsetLeft > 0) {
|
|
347
|
+
// Pad the joining stream on the left
|
|
348
|
+
stream.tPad({
|
|
349
|
+
start: offsetLeft,
|
|
350
|
+
...(isAudio ? {} : { color: Colors.Transparent }),
|
|
351
|
+
});
|
|
352
|
+
// Pad the main stream on the right if needed
|
|
353
|
+
const mainLeftover = offset.otherStreamDuration + offsetLeft - offset.streamDuration;
|
|
354
|
+
if (mainLeftover > 0) {
|
|
355
|
+
this.tPad({
|
|
356
|
+
stop: mainLeftover,
|
|
357
|
+
...(isAudio ? {} : { color: Colors.Transparent }),
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
// Mix or overlay the streams
|
|
361
|
+
if (isAudio) {
|
|
362
|
+
const res = (0, ffmpeg_1.makeAmix)([this.looseEnd, stream.getLooseEnd()]);
|
|
363
|
+
this.looseEnd = res.outputs[0];
|
|
364
|
+
this.buf.append(res);
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
const overlayRes = (0, ffmpeg_1.makeOverlay)(flip
|
|
368
|
+
? [stream.getLooseEnd(), this.looseEnd]
|
|
369
|
+
: [this.looseEnd, stream.getLooseEnd()]);
|
|
370
|
+
this.looseEnd = overlayRes.outputs[0];
|
|
371
|
+
this.buf.append(overlayRes);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
else if (offsetLeft < 0) {
|
|
375
|
+
throw new Error('negative offset is not supported for overlayStream');
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return this;
|
|
379
|
+
}
|
|
380
|
+
endTo(label) {
|
|
381
|
+
const res = (0, ffmpeg_1.makeNull)([this.looseEnd]);
|
|
382
|
+
res.outputs[0] = label;
|
|
383
|
+
this.buf.append(res);
|
|
384
|
+
return this;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Applies an Instagram-style filter to the video stream
|
|
388
|
+
* @param filterName - The filter to apply
|
|
389
|
+
*/
|
|
390
|
+
filter(filterName) {
|
|
391
|
+
if (this.looseEnd.isAudio) {
|
|
392
|
+
throw new Error('filter() can only be applied to video streams');
|
|
393
|
+
}
|
|
394
|
+
switch (filterName) {
|
|
395
|
+
case VisualFilter.InstagramClarendon:
|
|
396
|
+
// Brightens, increases contrast and saturation
|
|
397
|
+
const clarendonEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
398
|
+
contrast: 1.2,
|
|
399
|
+
brightness: 0.1,
|
|
400
|
+
saturation: 1.3,
|
|
401
|
+
});
|
|
402
|
+
this.looseEnd = clarendonEq.outputs[0];
|
|
403
|
+
this.buf.append(clarendonEq);
|
|
404
|
+
break;
|
|
405
|
+
case VisualFilter.InstagramGingham:
|
|
406
|
+
// Vintage washed-out look
|
|
407
|
+
const ginghamEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
408
|
+
saturation: 0.6,
|
|
409
|
+
brightness: 0.05,
|
|
410
|
+
});
|
|
411
|
+
this.looseEnd = ginghamEq.outputs[0];
|
|
412
|
+
this.buf.append(ginghamEq);
|
|
413
|
+
const ginghamBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
414
|
+
rm: 0.1,
|
|
415
|
+
bm: 0.05,
|
|
416
|
+
});
|
|
417
|
+
this.looseEnd = ginghamBalance.outputs[0];
|
|
418
|
+
this.buf.append(ginghamBalance);
|
|
419
|
+
break;
|
|
420
|
+
case VisualFilter.InstagramJuno:
|
|
421
|
+
// High contrast, saturated, cool tones
|
|
422
|
+
const junoEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
423
|
+
contrast: 1.3,
|
|
424
|
+
saturation: 1.4,
|
|
425
|
+
});
|
|
426
|
+
this.looseEnd = junoEq.outputs[0];
|
|
427
|
+
this.buf.append(junoEq);
|
|
428
|
+
const junoBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
429
|
+
bh: 0.15,
|
|
430
|
+
gh: 0.1,
|
|
431
|
+
});
|
|
432
|
+
this.looseEnd = junoBalance.outputs[0];
|
|
433
|
+
this.buf.append(junoBalance);
|
|
434
|
+
break;
|
|
435
|
+
case VisualFilter.InstagramLark:
|
|
436
|
+
// Brightens, desaturated, cool tones
|
|
437
|
+
const larkEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
438
|
+
brightness: 0.15,
|
|
439
|
+
saturation: 0.7,
|
|
440
|
+
});
|
|
441
|
+
this.looseEnd = larkEq.outputs[0];
|
|
442
|
+
this.buf.append(larkEq);
|
|
443
|
+
const larkBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
444
|
+
bm: 0.1,
|
|
445
|
+
});
|
|
446
|
+
this.looseEnd = larkBalance.outputs[0];
|
|
447
|
+
this.buf.append(larkBalance);
|
|
448
|
+
break;
|
|
449
|
+
case VisualFilter.InstagramLudwig:
|
|
450
|
+
// Cool tones, subtle vignette
|
|
451
|
+
const ludwigBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
452
|
+
bm: 0.08,
|
|
453
|
+
bs: 0.05,
|
|
454
|
+
});
|
|
455
|
+
this.looseEnd = ludwigBalance.outputs[0];
|
|
456
|
+
this.buf.append(ludwigBalance);
|
|
457
|
+
const ludwigVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
458
|
+
angle: 'PI/4',
|
|
459
|
+
});
|
|
460
|
+
this.looseEnd = ludwigVignette.outputs[0];
|
|
461
|
+
this.buf.append(ludwigVignette);
|
|
462
|
+
break;
|
|
463
|
+
case VisualFilter.InstagramNashville:
|
|
464
|
+
// Warm vintage, pink tint, vignette
|
|
465
|
+
const nashvilleBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
466
|
+
rm: 0.2,
|
|
467
|
+
rh: 0.1,
|
|
468
|
+
bm: -0.1,
|
|
469
|
+
});
|
|
470
|
+
this.looseEnd = nashvilleBalance.outputs[0];
|
|
471
|
+
this.buf.append(nashvilleBalance);
|
|
472
|
+
const nashvilleEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
473
|
+
contrast: 0.9,
|
|
474
|
+
saturation: 1.2,
|
|
475
|
+
});
|
|
476
|
+
this.looseEnd = nashvilleEq.outputs[0];
|
|
477
|
+
this.buf.append(nashvilleEq);
|
|
478
|
+
const nashvilleVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
479
|
+
angle: 'PI/4.5',
|
|
480
|
+
});
|
|
481
|
+
this.looseEnd = nashvilleVignette.outputs[0];
|
|
482
|
+
this.buf.append(nashvilleVignette);
|
|
483
|
+
break;
|
|
484
|
+
case VisualFilter.InstagramValencia:
|
|
485
|
+
// Warm tones, slight fade
|
|
486
|
+
const valenciaBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
487
|
+
rm: 0.15,
|
|
488
|
+
gm: 0.05,
|
|
489
|
+
});
|
|
490
|
+
this.looseEnd = valenciaBalance.outputs[0];
|
|
491
|
+
this.buf.append(valenciaBalance);
|
|
492
|
+
const valenciaEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
493
|
+
contrast: 0.95,
|
|
494
|
+
brightness: 0.05,
|
|
495
|
+
});
|
|
496
|
+
this.looseEnd = valenciaEq.outputs[0];
|
|
497
|
+
this.buf.append(valenciaEq);
|
|
498
|
+
break;
|
|
499
|
+
case VisualFilter.InstagramXProII:
|
|
500
|
+
// High contrast, warm highlights, cool shadows, vignette
|
|
501
|
+
const xproBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
502
|
+
rh: 0.2,
|
|
503
|
+
bs: 0.15,
|
|
504
|
+
});
|
|
505
|
+
this.looseEnd = xproBalance.outputs[0];
|
|
506
|
+
this.buf.append(xproBalance);
|
|
507
|
+
const xproEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
508
|
+
contrast: 1.4,
|
|
509
|
+
saturation: 1.2,
|
|
510
|
+
});
|
|
511
|
+
this.looseEnd = xproEq.outputs[0];
|
|
512
|
+
this.buf.append(xproEq);
|
|
513
|
+
const xproVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
514
|
+
angle: 'PI/4',
|
|
515
|
+
});
|
|
516
|
+
this.looseEnd = xproVignette.outputs[0];
|
|
517
|
+
this.buf.append(xproVignette);
|
|
518
|
+
break;
|
|
519
|
+
case VisualFilter.InstagramWillow:
|
|
520
|
+
// Black and white-ish, desaturated, slight yellow tint
|
|
521
|
+
const willowEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
522
|
+
saturation: 0.2,
|
|
523
|
+
brightness: 0.05,
|
|
524
|
+
});
|
|
525
|
+
this.looseEnd = willowEq.outputs[0];
|
|
526
|
+
this.buf.append(willowEq);
|
|
527
|
+
const willowBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
528
|
+
rm: 0.05,
|
|
529
|
+
gm: 0.05,
|
|
530
|
+
});
|
|
531
|
+
this.looseEnd = willowBalance.outputs[0];
|
|
532
|
+
this.buf.append(willowBalance);
|
|
533
|
+
break;
|
|
534
|
+
case VisualFilter.InstagramLoFi:
|
|
535
|
+
// High contrast, high saturation, vignette
|
|
536
|
+
const lofiEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
537
|
+
contrast: 1.5,
|
|
538
|
+
saturation: 1.4,
|
|
539
|
+
});
|
|
540
|
+
this.looseEnd = lofiEq.outputs[0];
|
|
541
|
+
this.buf.append(lofiEq);
|
|
542
|
+
const lofiVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
543
|
+
angle: 'PI/4',
|
|
544
|
+
});
|
|
545
|
+
this.looseEnd = lofiVignette.outputs[0];
|
|
546
|
+
this.buf.append(lofiVignette);
|
|
547
|
+
break;
|
|
548
|
+
case VisualFilter.InstagramInkwell:
|
|
549
|
+
// Classic black and white
|
|
550
|
+
const inkwellEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
551
|
+
saturation: 0,
|
|
552
|
+
contrast: 1.1,
|
|
553
|
+
});
|
|
554
|
+
this.looseEnd = inkwellEq.outputs[0];
|
|
555
|
+
this.buf.append(inkwellEq);
|
|
556
|
+
break;
|
|
557
|
+
case VisualFilter.InstagramMoon:
|
|
558
|
+
// Black and white with high contrast and cool tone
|
|
559
|
+
const moonEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
560
|
+
saturation: 0,
|
|
561
|
+
contrast: 1.4,
|
|
562
|
+
brightness: -0.05,
|
|
563
|
+
});
|
|
564
|
+
this.looseEnd = moonEq.outputs[0];
|
|
565
|
+
this.buf.append(moonEq);
|
|
566
|
+
const moonBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
567
|
+
bs: 0.1,
|
|
568
|
+
bm: 0.08,
|
|
569
|
+
});
|
|
570
|
+
this.looseEnd = moonBalance.outputs[0];
|
|
571
|
+
this.buf.append(moonBalance);
|
|
572
|
+
const moonVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
573
|
+
angle: 'PI/4.5',
|
|
574
|
+
});
|
|
575
|
+
this.looseEnd = moonVignette.outputs[0];
|
|
576
|
+
this.buf.append(moonVignette);
|
|
577
|
+
break;
|
|
578
|
+
case VisualFilter.InstagramHudson:
|
|
579
|
+
// Cool tones, high contrast, vignette
|
|
580
|
+
const hudsonBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
581
|
+
bm: 0.2,
|
|
582
|
+
bs: 0.15,
|
|
583
|
+
});
|
|
584
|
+
this.looseEnd = hudsonBalance.outputs[0];
|
|
585
|
+
this.buf.append(hudsonBalance);
|
|
586
|
+
const hudsonEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
587
|
+
contrast: 1.3,
|
|
588
|
+
});
|
|
589
|
+
this.looseEnd = hudsonEq.outputs[0];
|
|
590
|
+
this.buf.append(hudsonEq);
|
|
591
|
+
const hudsonVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
592
|
+
angle: 'PI/4.5',
|
|
593
|
+
});
|
|
594
|
+
this.looseEnd = hudsonVignette.outputs[0];
|
|
595
|
+
this.buf.append(hudsonVignette);
|
|
596
|
+
break;
|
|
597
|
+
case VisualFilter.InstagramToaster:
|
|
598
|
+
// Warm tones, vignette
|
|
599
|
+
const toasterBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
600
|
+
rm: 0.25,
|
|
601
|
+
rh: 0.15,
|
|
602
|
+
});
|
|
603
|
+
this.looseEnd = toasterBalance.outputs[0];
|
|
604
|
+
this.buf.append(toasterBalance);
|
|
605
|
+
const toasterEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
606
|
+
contrast: 1.2,
|
|
607
|
+
});
|
|
608
|
+
this.looseEnd = toasterEq.outputs[0];
|
|
609
|
+
this.buf.append(toasterEq);
|
|
610
|
+
const toasterVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
611
|
+
angle: 'PI/4',
|
|
612
|
+
});
|
|
613
|
+
this.looseEnd = toasterVignette.outputs[0];
|
|
614
|
+
this.buf.append(toasterVignette);
|
|
615
|
+
break;
|
|
616
|
+
case VisualFilter.InstagramWalden:
|
|
617
|
+
// Increased exposure, yellow tones
|
|
618
|
+
const waldenBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
619
|
+
rm: 0.1,
|
|
620
|
+
gm: 0.1,
|
|
621
|
+
});
|
|
622
|
+
this.looseEnd = waldenBalance.outputs[0];
|
|
623
|
+
this.buf.append(waldenBalance);
|
|
624
|
+
const waldenEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
625
|
+
brightness: 0.15,
|
|
626
|
+
saturation: 1.1,
|
|
627
|
+
});
|
|
628
|
+
this.looseEnd = waldenEq.outputs[0];
|
|
629
|
+
this.buf.append(waldenEq);
|
|
630
|
+
break;
|
|
631
|
+
case VisualFilter.InstagramRise:
|
|
632
|
+
// Soft, warm glow
|
|
633
|
+
const riseBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
634
|
+
rm: 0.12,
|
|
635
|
+
rh: 0.08,
|
|
636
|
+
});
|
|
637
|
+
this.looseEnd = riseBalance.outputs[0];
|
|
638
|
+
this.buf.append(riseBalance);
|
|
639
|
+
const riseEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
640
|
+
brightness: 0.1,
|
|
641
|
+
contrast: 0.9,
|
|
642
|
+
saturation: 1.15,
|
|
643
|
+
});
|
|
644
|
+
this.looseEnd = riseEq.outputs[0];
|
|
645
|
+
this.buf.append(riseEq);
|
|
646
|
+
break;
|
|
647
|
+
case VisualFilter.InstagramAmaro:
|
|
648
|
+
// Increases contrast, adds vignette, cool tone
|
|
649
|
+
const amaroBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
650
|
+
bm: 0.1,
|
|
651
|
+
});
|
|
652
|
+
this.looseEnd = amaroBalance.outputs[0];
|
|
653
|
+
this.buf.append(amaroBalance);
|
|
654
|
+
const amaroEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
655
|
+
contrast: 1.3,
|
|
656
|
+
saturation: 1.2,
|
|
657
|
+
});
|
|
658
|
+
this.looseEnd = amaroEq.outputs[0];
|
|
659
|
+
this.buf.append(amaroEq);
|
|
660
|
+
const amaroVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
661
|
+
angle: 'PI/4.5',
|
|
662
|
+
});
|
|
663
|
+
this.looseEnd = amaroVignette.outputs[0];
|
|
664
|
+
this.buf.append(amaroVignette);
|
|
665
|
+
break;
|
|
666
|
+
case VisualFilter.InstagramMayfair:
|
|
667
|
+
// Warm center, cool edges, vignette
|
|
668
|
+
const mayfairBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
669
|
+
rh: 0.15,
|
|
670
|
+
bs: 0.1,
|
|
671
|
+
});
|
|
672
|
+
this.looseEnd = mayfairBalance.outputs[0];
|
|
673
|
+
this.buf.append(mayfairBalance);
|
|
674
|
+
const mayfairEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
675
|
+
contrast: 1.1,
|
|
676
|
+
saturation: 1.15,
|
|
677
|
+
});
|
|
678
|
+
this.looseEnd = mayfairEq.outputs[0];
|
|
679
|
+
this.buf.append(mayfairEq);
|
|
680
|
+
const mayfairVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
681
|
+
angle: 'PI/4',
|
|
682
|
+
});
|
|
683
|
+
this.looseEnd = mayfairVignette.outputs[0];
|
|
684
|
+
this.buf.append(mayfairVignette);
|
|
685
|
+
break;
|
|
686
|
+
case VisualFilter.InstagramEarlybird:
|
|
687
|
+
// Vintage sepia, vignette
|
|
688
|
+
const earlybirdBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
689
|
+
rm: 0.2,
|
|
690
|
+
gm: 0.1,
|
|
691
|
+
bm: -0.15,
|
|
692
|
+
});
|
|
693
|
+
this.looseEnd = earlybirdBalance.outputs[0];
|
|
694
|
+
this.buf.append(earlybirdBalance);
|
|
695
|
+
const earlybirdEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
696
|
+
contrast: 1.2,
|
|
697
|
+
saturation: 1.1,
|
|
698
|
+
});
|
|
699
|
+
this.looseEnd = earlybirdEq.outputs[0];
|
|
700
|
+
this.buf.append(earlybirdEq);
|
|
701
|
+
const earlybirdVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
702
|
+
angle: 'PI/4',
|
|
703
|
+
});
|
|
704
|
+
this.looseEnd = earlybirdVignette.outputs[0];
|
|
705
|
+
this.buf.append(earlybirdVignette);
|
|
706
|
+
break;
|
|
707
|
+
case VisualFilter.InstagramSutro:
|
|
708
|
+
// Muted colors, purple/brown tint, vignette
|
|
709
|
+
const sutroBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
710
|
+
rm: 0.1,
|
|
711
|
+
bm: 0.15,
|
|
712
|
+
});
|
|
713
|
+
this.looseEnd = sutroBalance.outputs[0];
|
|
714
|
+
this.buf.append(sutroBalance);
|
|
715
|
+
const sutroEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
716
|
+
saturation: 0.8,
|
|
717
|
+
contrast: 1.2,
|
|
718
|
+
});
|
|
719
|
+
this.looseEnd = sutroEq.outputs[0];
|
|
720
|
+
this.buf.append(sutroEq);
|
|
721
|
+
const sutroVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
722
|
+
angle: 'PI/3.5',
|
|
723
|
+
});
|
|
724
|
+
this.looseEnd = sutroVignette.outputs[0];
|
|
725
|
+
this.buf.append(sutroVignette);
|
|
726
|
+
break;
|
|
727
|
+
case VisualFilter.InstagramAden:
|
|
728
|
+
// Muted, cool tones, slight vignette
|
|
729
|
+
const adenBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
730
|
+
bm: 0.12,
|
|
731
|
+
});
|
|
732
|
+
this.looseEnd = adenBalance.outputs[0];
|
|
733
|
+
this.buf.append(adenBalance);
|
|
734
|
+
const adenEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
735
|
+
saturation: 0.85,
|
|
736
|
+
brightness: 0.08,
|
|
737
|
+
});
|
|
738
|
+
this.looseEnd = adenEq.outputs[0];
|
|
739
|
+
this.buf.append(adenEq);
|
|
740
|
+
const adenVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
741
|
+
angle: 'PI/5',
|
|
742
|
+
});
|
|
743
|
+
this.looseEnd = adenVignette.outputs[0];
|
|
744
|
+
this.buf.append(adenVignette);
|
|
745
|
+
break;
|
|
746
|
+
case VisualFilter.InstagramCrema:
|
|
747
|
+
// Creamy warmth, slight vignette
|
|
748
|
+
const cremaBalance = (0, ffmpeg_1.makeColorBalance)([this.looseEnd], {
|
|
749
|
+
rm: 0.08,
|
|
750
|
+
gm: 0.05,
|
|
751
|
+
});
|
|
752
|
+
this.looseEnd = cremaBalance.outputs[0];
|
|
753
|
+
this.buf.append(cremaBalance);
|
|
754
|
+
const cremaEq = (0, ffmpeg_1.makeEq)([this.looseEnd], {
|
|
755
|
+
brightness: 0.05,
|
|
756
|
+
contrast: 0.95,
|
|
757
|
+
});
|
|
758
|
+
this.looseEnd = cremaEq.outputs[0];
|
|
759
|
+
this.buf.append(cremaEq);
|
|
760
|
+
const cremaVignette = (0, ffmpeg_1.makeVignette)([this.looseEnd], {
|
|
761
|
+
angle: 'PI/5',
|
|
762
|
+
});
|
|
763
|
+
this.looseEnd = cremaVignette.outputs[0];
|
|
764
|
+
this.buf.append(cremaVignette);
|
|
765
|
+
break;
|
|
766
|
+
default:
|
|
767
|
+
throw new Error(`Unknown Instagram filter: ${filterName}`);
|
|
768
|
+
}
|
|
769
|
+
return this;
|
|
770
|
+
}
|
|
771
|
+
getLooseEnd() {
|
|
772
|
+
return this.looseEnd;
|
|
773
|
+
}
|
|
774
|
+
render() {
|
|
775
|
+
return this.buf.render();
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
exports.Stream = Stream;
|
|
779
|
+
//# sourceMappingURL=stream.js.map
|