@remotion/renderer 4.0.22 → 4.0.24
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/.prettierignore +2 -0
- package/dist/assets/get-video-stream-duration.d.ts +9 -0
- package/dist/assets/get-video-stream-duration.js +71 -0
- package/dist/audio-codec.d.ts +3 -3
- package/dist/calculate-sar-dar-pixels.d.ts +9 -0
- package/dist/calculate-sar-dar-pixels.js +19 -0
- package/dist/client.d.ts +154 -8
- package/dist/client.js +4 -0
- package/dist/codec.d.ts +1 -1
- package/dist/compositor/compositor.d.ts +2 -2
- package/dist/compositor/compositor.js +22 -19
- package/dist/compositor/payloads.d.ts +2 -2
- package/dist/copy-to-clipboard.js +1 -1
- package/dist/create-ffmpeg-complex-filter.d.ts +4 -1
- package/dist/determine-resize-params.d.ts +4 -0
- package/dist/determine-resize-params.js +10 -0
- package/dist/determine-vcodec-ffmpeg-flags.d.ts +2 -0
- package/dist/determine-vcodec-ffmpeg-flags.js +13 -0
- package/dist/ensure-ffmpeg.d.ts +18 -0
- package/dist/ensure-ffmpeg.js +58 -0
- package/dist/ensure-presentation-timestamp.d.ts +15 -0
- package/dist/ensure-presentation-timestamp.js +88 -0
- package/dist/extract-frame-from-video.d.ts +16 -0
- package/dist/extract-frame-from-video.js +191 -0
- package/dist/ffmpeg-executable.d.ts +1 -0
- package/dist/ffmpeg-executable.js +2 -0
- package/dist/ffmpeg-flags.d.ts +31 -0
- package/dist/ffmpeg-flags.js +245 -0
- package/dist/file-extensions.d.ts +1 -1
- package/dist/format-logs.js +3 -1
- package/dist/frame-to-ffmpeg-timestamp.d.ts +1 -0
- package/dist/frame-to-ffmpeg-timestamp.js +8 -0
- package/dist/get-can-extract-frames-fast.d.ts +14 -0
- package/dist/get-can-extract-frames-fast.js +71 -0
- package/dist/get-compositions.d.ts +5 -2
- package/dist/get-compositions.js +4 -1
- package/dist/get-extension-from-codec.js +1 -2
- package/dist/get-frame-of-video-slow.d.ts +17 -0
- package/dist/get-frame-of-video-slow.js +72 -0
- package/dist/get-silent-parts.js +1 -1
- package/dist/get-video-info.d.ts +8 -0
- package/dist/get-video-info.js +59 -0
- package/dist/get-video-metadata.js +1 -1
- package/dist/image-format.d.ts +2 -2
- package/dist/index.d.ts +38 -14
- package/dist/is-beyond-last-frame.d.ts +3 -0
- package/dist/is-beyond-last-frame.js +12 -0
- package/dist/last-frame-from-video-cache.d.ts +17 -0
- package/dist/last-frame-from-video-cache.js +55 -0
- package/dist/legacy-webpack-config.d.ts +9 -0
- package/dist/legacy-webpack-config.js +13 -0
- package/dist/log-level.d.ts +1 -1
- package/dist/offthread-video-server.d.ts +2 -1
- package/dist/offthread-video-server.js +4 -2
- package/dist/open-browser.d.ts +1 -1
- package/dist/options/audio-bitrate.d.ts +8 -2
- package/dist/options/audio-bitrate.js +1 -0
- package/dist/options/crf.d.ts +8 -2
- package/dist/options/crf.js +1 -0
- package/dist/options/enforce-audio.d.ts +8 -2
- package/dist/options/enforce-audio.js +1 -0
- package/dist/options/jpeg-quality.d.ts +8 -2
- package/dist/options/jpeg-quality.js +1 -0
- package/dist/options/mute.d.ts +8 -2
- package/dist/options/mute.js +1 -0
- package/dist/options/offthreadvideo-cache-size.d.ts +9 -0
- package/dist/options/offthreadvideo-cache-size.js +33 -0
- package/dist/options/option.d.ts +7 -2
- package/dist/options/options-map.d.ts +82 -0
- package/dist/options/options-map.js +16 -0
- package/dist/options/scale.d.ts +8 -2
- package/dist/options/scale.js +1 -0
- package/dist/options/video-bitrate.d.ts +8 -2
- package/dist/options/video-bitrate.js +1 -0
- package/dist/options/video-codec.d.ts +8 -2
- package/dist/options/video-codec.js +1 -0
- package/dist/pixel-format.d.ts +1 -1
- package/dist/prepare-server.d.ts +2 -1
- package/dist/prepare-server.js +3 -1
- package/dist/prores-profile.d.ts +1 -1
- package/dist/provide-screenshot.d.ts +0 -1
- package/dist/puppeteer-screenshot.d.ts +0 -1
- package/dist/quality.d.ts +1 -0
- package/dist/quality.js +21 -0
- package/dist/render-frames.d.ts +5 -2
- package/dist/render-frames.js +4 -2
- package/dist/render-media.d.ts +6 -3
- package/dist/render-media.js +5 -2
- package/dist/render-still.d.ts +5 -1
- package/dist/render-still.js +3 -1
- package/dist/screenshot-dom-element.d.ts +0 -1
- package/dist/screenshot-task.d.ts +0 -1
- package/dist/select-composition.d.ts +4 -1
- package/dist/select-composition.js +5 -1
- package/dist/serve-static.d.ts +1 -0
- package/dist/serve-static.js +1 -0
- package/dist/stitch-frames-to-video.d.ts +0 -1
- package/dist/take-frame-and-compose.d.ts +0 -1
- package/dist/try-to-extract-frame-of-video-fast.d.ts +12 -0
- package/dist/try-to-extract-frame-of-video-fast.js +55 -0
- package/dist/validate-ffmpeg.d.ts +7 -0
- package/dist/validate-ffmpeg.js +77 -0
- package/dist/validate-opengl-renderer.d.ts +1 -1
- package/dist/warn-about-ffmpeg-version.d.ts +5 -0
- package/dist/warn-about-ffmpeg-version.js +37 -0
- package/dist/x264-preset.d.ts +1 -1
- package/package.json +11 -12
- package/dist/presets-profile.d.ts +0 -7
- package/dist/presets-profile.js +0 -27
package/.prettierignore
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FfmpegExecutable } from '../ffmpeg-executable';
|
|
2
|
+
import type { DownloadMap, VideoDurationResult } from './download-map';
|
|
3
|
+
export declare const parseVideoStreamDuration: (stdout: string) => VideoDurationResult;
|
|
4
|
+
export declare function getVideoStreamDurationwithoutCache({ src, ffprobeExecutable, remotionRoot, }: {
|
|
5
|
+
src: string;
|
|
6
|
+
ffprobeExecutable: FfmpegExecutable;
|
|
7
|
+
remotionRoot: string;
|
|
8
|
+
}): Promise<VideoDurationResult>;
|
|
9
|
+
export declare const getVideoStreamDuration: (downloadMap: DownloadMap, src: string, ffprobeExecutable: FfmpegExecutable, remotionRoot: string) => Promise<VideoDurationResult>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getVideoStreamDuration = exports.getVideoStreamDurationwithoutCache = exports.parseVideoStreamDuration = void 0;
|
|
7
|
+
const execa_1 = __importDefault(require("execa"));
|
|
8
|
+
const ffmpeg_flags_1 = require("../ffmpeg-flags");
|
|
9
|
+
const p_limit_1 = require("../p-limit");
|
|
10
|
+
const limit = (0, p_limit_1.pLimit)(1);
|
|
11
|
+
const parseAlternativeDuration = (stdout) => {
|
|
12
|
+
const webmDuration = stdout.match(/TAG:DURATION=([0-9.]+):([0-9.]+):([0-9.]+)/);
|
|
13
|
+
if (!webmDuration) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const [, hours, minutes, seconds] = webmDuration;
|
|
17
|
+
const hoursAsNumber = Number(hours);
|
|
18
|
+
if (Number.isNaN(hoursAsNumber)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const minutesAsNumber = Number(minutes);
|
|
22
|
+
if (Number.isNaN(minutesAsNumber)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const secondsAsNumber = Number(seconds);
|
|
26
|
+
if (Number.isNaN(secondsAsNumber)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return secondsAsNumber + minutesAsNumber * 60 + hoursAsNumber * 3600;
|
|
30
|
+
};
|
|
31
|
+
const parseVideoStreamDuration = (stdout) => {
|
|
32
|
+
const duration = stdout.match(/duration=([0-9.]+)/);
|
|
33
|
+
const alternativeDuration = parseAlternativeDuration(stdout);
|
|
34
|
+
const fps = stdout.match(/r_frame_rate=([0-9.]+)\/([0-9.]+)/);
|
|
35
|
+
const result = {
|
|
36
|
+
duration: duration ? parseFloat(duration[1]) : alternativeDuration,
|
|
37
|
+
fps: fps ? parseInt(fps[1], 10) / parseInt(fps[2], 10) : null,
|
|
38
|
+
};
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
exports.parseVideoStreamDuration = parseVideoStreamDuration;
|
|
42
|
+
async function getVideoStreamDurationwithoutCache({ src, ffprobeExecutable, remotionRoot, }) {
|
|
43
|
+
const args = [
|
|
44
|
+
['-v', 'error'],
|
|
45
|
+
['-select_streams', 'v:0'],
|
|
46
|
+
['-show_entries', 'stream'],
|
|
47
|
+
[src],
|
|
48
|
+
]
|
|
49
|
+
.reduce((acc, val) => acc.concat(val), [])
|
|
50
|
+
.filter(Boolean);
|
|
51
|
+
const task = await (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffprobeExecutable, remotionRoot, 'ffprobe'), args);
|
|
52
|
+
const result = (0, exports.parseVideoStreamDuration)(task.stdout);
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
exports.getVideoStreamDurationwithoutCache = getVideoStreamDurationwithoutCache;
|
|
56
|
+
async function getVideoStreamDurationUnlimited(downloadMap, src, ffprobeExecutable, remotionRoot) {
|
|
57
|
+
if (downloadMap.videoDurationResultCache[src]) {
|
|
58
|
+
return downloadMap.videoDurationResultCache[src];
|
|
59
|
+
}
|
|
60
|
+
const result = await getVideoStreamDurationwithoutCache({
|
|
61
|
+
src,
|
|
62
|
+
ffprobeExecutable,
|
|
63
|
+
remotionRoot,
|
|
64
|
+
});
|
|
65
|
+
downloadMap.videoDurationResultCache[src] = result;
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
const getVideoStreamDuration = (downloadMap, src, ffprobeExecutable, remotionRoot) => {
|
|
69
|
+
return limit(() => getVideoStreamDurationUnlimited(downloadMap, src, ffprobeExecutable, remotionRoot));
|
|
70
|
+
};
|
|
71
|
+
exports.getVideoStreamDuration = getVideoStreamDuration;
|
package/dist/audio-codec.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Codec } from './codec';
|
|
2
2
|
export declare const validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
|
|
3
|
-
export type AudioCodec = typeof validAudioCodecs[number];
|
|
3
|
+
export type AudioCodec = (typeof validAudioCodecs)[number];
|
|
4
4
|
export declare const supportedAudioCodecs: {
|
|
5
5
|
readonly h264: readonly ["aac", "pcm-16", "mp3"];
|
|
6
6
|
readonly 'h264-mkv': readonly ["pcm-16", "mp3"];
|
|
@@ -14,11 +14,11 @@ export declare const supportedAudioCodecs: {
|
|
|
14
14
|
readonly wav: readonly ["pcm-16"];
|
|
15
15
|
};
|
|
16
16
|
declare const audioCodecNames: readonly ["pcm_s16le", "aac", "libmp3lame", "libopus"];
|
|
17
|
-
type FfmpegAudioCodecName = typeof audioCodecNames[number];
|
|
17
|
+
type FfmpegAudioCodecName = (typeof audioCodecNames)[number];
|
|
18
18
|
export declare const mapAudioCodecToFfmpegAudioCodecName: (audioCodec: AudioCodec) => FfmpegAudioCodecName;
|
|
19
19
|
export declare const defaultAudioCodecs: {
|
|
20
20
|
[key in Codec]: {
|
|
21
|
-
[k in 'compressed' | 'lossless']: typeof supportedAudioCodecs[key][number] | null;
|
|
21
|
+
[k in 'compressed' | 'lossless']: (typeof supportedAudioCodecs)[key][number] | null;
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
export declare const getDefaultAudioCodec: ({ codec, preferLossless, }: {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// https://superuser.com/questions/907933/correct-aspect-ratio-without-re-encoding-video-file
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.calculateDisplayVideoSize = void 0;
|
|
5
|
+
const calculateDisplayVideoSize = ({ darX, darY, x, y, }) => {
|
|
6
|
+
// We know two equations:
|
|
7
|
+
// newWidth / newHeight = darX / darY
|
|
8
|
+
// and:
|
|
9
|
+
// x * y = (newWidth * newHeight)
|
|
10
|
+
// I solved it then on pen and paper and simplified the formula:
|
|
11
|
+
const dimensions = x * y;
|
|
12
|
+
const newWidth = Math.sqrt(dimensions * (darX / darY));
|
|
13
|
+
const newHeight = dimensions / newWidth;
|
|
14
|
+
return {
|
|
15
|
+
height: Math.round(newHeight),
|
|
16
|
+
width: Math.round(newWidth),
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
exports.calculateDisplayVideoSize = calculateDisplayVideoSize;
|
package/dist/client.d.ts
CHANGED
|
@@ -194,14 +194,160 @@ export declare const BrowserSafeApis: {
|
|
|
194
194
|
preferLossless: boolean;
|
|
195
195
|
}) => void;
|
|
196
196
|
options: {
|
|
197
|
-
scaleOption:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
197
|
+
scaleOption: {
|
|
198
|
+
name: string;
|
|
199
|
+
cliFlag: string;
|
|
200
|
+
description: JSX.Element;
|
|
201
|
+
ssrName: string;
|
|
202
|
+
docLink: string;
|
|
203
|
+
type: number;
|
|
204
|
+
};
|
|
205
|
+
crfOption: {
|
|
206
|
+
name: string;
|
|
207
|
+
cliFlag: string;
|
|
208
|
+
description: JSX.Element;
|
|
209
|
+
ssrName: string;
|
|
210
|
+
docLink: string;
|
|
211
|
+
type: number;
|
|
212
|
+
};
|
|
213
|
+
jpegQualityOption: {
|
|
214
|
+
name: string;
|
|
215
|
+
cliFlag: string;
|
|
216
|
+
description: JSX.Element;
|
|
217
|
+
ssrName: string;
|
|
218
|
+
docLink: string;
|
|
219
|
+
type: number;
|
|
220
|
+
};
|
|
221
|
+
videoBitrate: {
|
|
222
|
+
name: string;
|
|
223
|
+
cliFlag: string;
|
|
224
|
+
description: JSX.Element;
|
|
225
|
+
ssrName: string;
|
|
226
|
+
docLink: string;
|
|
227
|
+
type: string;
|
|
228
|
+
};
|
|
229
|
+
audioBitrateOption: {
|
|
230
|
+
name: string;
|
|
231
|
+
cliFlag: string;
|
|
232
|
+
description: JSX.Element;
|
|
233
|
+
ssrName: string;
|
|
234
|
+
docLink: string;
|
|
235
|
+
type: string;
|
|
236
|
+
};
|
|
237
|
+
enforceAudioOption: {
|
|
238
|
+
name: string;
|
|
239
|
+
cliFlag: string;
|
|
240
|
+
description: JSX.Element;
|
|
241
|
+
ssrName: string;
|
|
242
|
+
docLink: string;
|
|
243
|
+
type: boolean;
|
|
244
|
+
};
|
|
245
|
+
muteOption: {
|
|
246
|
+
name: string;
|
|
247
|
+
cliFlag: string;
|
|
248
|
+
description: JSX.Element;
|
|
249
|
+
ssrName: string;
|
|
250
|
+
docLink: string;
|
|
251
|
+
type: boolean;
|
|
252
|
+
};
|
|
253
|
+
videoCodecOption: {
|
|
254
|
+
name: string;
|
|
255
|
+
cliFlag: string;
|
|
256
|
+
description: JSX.Element;
|
|
257
|
+
ssrName: string;
|
|
258
|
+
docLink: string;
|
|
259
|
+
type: string;
|
|
260
|
+
};
|
|
261
|
+
offthreadVideoCacheSizeInBytesOption: {
|
|
262
|
+
name: string;
|
|
263
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
264
|
+
description: JSX.Element;
|
|
265
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
266
|
+
docLink: string;
|
|
267
|
+
type: number | null;
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
optionsMap: {
|
|
271
|
+
readonly renderMedia: readonly [{
|
|
272
|
+
name: string;
|
|
273
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
274
|
+
description: JSX.Element;
|
|
275
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
276
|
+
docLink: string;
|
|
277
|
+
type: number | null;
|
|
278
|
+
}];
|
|
279
|
+
readonly renderStill: readonly [{
|
|
280
|
+
name: string;
|
|
281
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
282
|
+
description: JSX.Element;
|
|
283
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
284
|
+
docLink: string;
|
|
285
|
+
type: number | null;
|
|
286
|
+
}];
|
|
287
|
+
readonly getCompositions: readonly [{
|
|
288
|
+
name: string;
|
|
289
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
290
|
+
description: JSX.Element;
|
|
291
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
292
|
+
docLink: string;
|
|
293
|
+
type: number | null;
|
|
294
|
+
}];
|
|
295
|
+
readonly selectComposition: readonly [{
|
|
296
|
+
name: string;
|
|
297
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
298
|
+
description: JSX.Element;
|
|
299
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
300
|
+
docLink: string;
|
|
301
|
+
type: number | null;
|
|
302
|
+
}];
|
|
303
|
+
readonly renderFrames: readonly [{
|
|
304
|
+
name: string;
|
|
305
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
306
|
+
description: JSX.Element;
|
|
307
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
308
|
+
docLink: string;
|
|
309
|
+
type: number | null;
|
|
310
|
+
}];
|
|
311
|
+
readonly renderMediaOnLambda: readonly [{
|
|
312
|
+
name: string;
|
|
313
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
314
|
+
description: JSX.Element;
|
|
315
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
316
|
+
docLink: string;
|
|
317
|
+
type: number | null;
|
|
318
|
+
}];
|
|
319
|
+
readonly renderStillOnLambda: readonly [{
|
|
320
|
+
name: string;
|
|
321
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
322
|
+
description: JSX.Element;
|
|
323
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
324
|
+
docLink: string;
|
|
325
|
+
type: number | null;
|
|
326
|
+
}];
|
|
327
|
+
readonly getCompositionsOnLambda: readonly [{
|
|
328
|
+
name: string;
|
|
329
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
330
|
+
description: JSX.Element;
|
|
331
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
332
|
+
docLink: string;
|
|
333
|
+
type: number | null;
|
|
334
|
+
}];
|
|
335
|
+
readonly renderMediaOnCloudRun: readonly [{
|
|
336
|
+
name: string;
|
|
337
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
338
|
+
description: JSX.Element;
|
|
339
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
340
|
+
docLink: string;
|
|
341
|
+
type: number | null;
|
|
342
|
+
}];
|
|
343
|
+
readonly renderStillOnCloudRun: readonly [{
|
|
344
|
+
name: string;
|
|
345
|
+
cliFlag: "offthreadvideo-cache-size-in-bytes";
|
|
346
|
+
description: JSX.Element;
|
|
347
|
+
ssrName: "offthreadVideoCacheSizeInBytes";
|
|
348
|
+
docLink: string;
|
|
349
|
+
type: number | null;
|
|
350
|
+
}];
|
|
205
351
|
};
|
|
206
352
|
codecSupportsCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
|
|
207
353
|
codecSupportsVideoBitrate: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
|
package/dist/client.js
CHANGED
|
@@ -13,6 +13,8 @@ const crf_2 = require("./options/crf");
|
|
|
13
13
|
const enforce_audio_1 = require("./options/enforce-audio");
|
|
14
14
|
const jpeg_quality_1 = require("./options/jpeg-quality");
|
|
15
15
|
const mute_1 = require("./options/mute");
|
|
16
|
+
const offthreadvideo_cache_size_1 = require("./options/offthreadvideo-cache-size");
|
|
17
|
+
const options_map_1 = require("./options/options-map");
|
|
16
18
|
const scale_1 = require("./options/scale");
|
|
17
19
|
const video_bitrate_1 = require("./options/video-bitrate");
|
|
18
20
|
const video_codec_1 = require("./options/video-codec");
|
|
@@ -45,7 +47,9 @@ exports.BrowserSafeApis = {
|
|
|
45
47
|
enforceAudioOption: enforce_audio_1.enforceAudioOption,
|
|
46
48
|
muteOption: mute_1.muteOption,
|
|
47
49
|
videoCodecOption: video_codec_1.videoCodecOption,
|
|
50
|
+
offthreadVideoCacheSizeInBytesOption: offthreadvideo_cache_size_1.offthreadVideoCacheSizeInBytesOption,
|
|
48
51
|
},
|
|
52
|
+
optionsMap: options_map_1.optionsMap,
|
|
49
53
|
codecSupportsCrf: codec_supports_media_1.codecSupportsCrf,
|
|
50
54
|
codecSupportsVideoBitrate: codec_supports_media_1.codecSupportsVideoBitrate,
|
|
51
55
|
};
|
package/dist/codec.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
|
|
2
|
-
export type Codec = typeof validCodecs[number];
|
|
2
|
+
export type Codec = (typeof validCodecs)[number];
|
|
3
3
|
export type CodecOrUndefined = Codec | undefined;
|
|
4
4
|
export declare const DEFAULT_CODEC: Codec;
|
|
@@ -7,6 +7,6 @@ export type Compositor = {
|
|
|
7
7
|
waitForDone: () => Promise<void>;
|
|
8
8
|
pid: number | null;
|
|
9
9
|
};
|
|
10
|
-
export declare const
|
|
11
|
-
export declare const startLongRunningCompositor: (
|
|
10
|
+
export declare const getIdealMaximumFrameCacheSizeInBytes: () => number;
|
|
11
|
+
export declare const startLongRunningCompositor: (maximumFrameCacheItemsInBytes: number, logLevel: LogLevel, indent: boolean) => Compositor;
|
|
12
12
|
export declare const startCompositor: <T extends keyof CompositorCommand>(type: T, payload: CompositorCommand[T], logLevel: LogLevel, indent: boolean) => Compositor;
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.startCompositor = exports.startLongRunningCompositor = exports.
|
|
6
|
+
exports.startCompositor = exports.startLongRunningCompositor = exports.getIdealMaximumFrameCacheSizeInBytes = void 0;
|
|
7
7
|
const node_child_process_1 = require("node:child_process");
|
|
8
8
|
const node_fs_1 = require("node:fs");
|
|
9
9
|
const node_os_1 = __importDefault(require("node:os"));
|
|
@@ -14,21 +14,20 @@ const logger_1 = require("../logger");
|
|
|
14
14
|
const compose_1 = require("./compose");
|
|
15
15
|
const get_executable_path_1 = require("./get-executable-path");
|
|
16
16
|
const make_nonce_1 = require("./make-nonce");
|
|
17
|
-
const
|
|
17
|
+
const getIdealMaximumFrameCacheSizeInBytes = () => {
|
|
18
18
|
const freeMemory = node_os_1.default.freemem();
|
|
19
|
-
// Assuming 1 frame is approximately 24MB
|
|
20
|
-
// (4K video)
|
|
21
19
|
// Assuming only half the available memory should be used
|
|
22
|
-
const max =
|
|
23
|
-
// Never store more than 2000
|
|
24
|
-
// But
|
|
25
|
-
return Math.max(
|
|
20
|
+
const max = freeMemory / 2;
|
|
21
|
+
// Never store more than 2000 MB
|
|
22
|
+
// But 240MB is needed even if it's going to swap
|
|
23
|
+
return Math.max(mbToBytes(240), Math.min(max, mbToBytes(2000)));
|
|
26
24
|
};
|
|
27
|
-
exports.
|
|
28
|
-
const
|
|
25
|
+
exports.getIdealMaximumFrameCacheSizeInBytes = getIdealMaximumFrameCacheSizeInBytes;
|
|
26
|
+
const mbToBytes = (mb) => mb * 1024 * 1024;
|
|
27
|
+
const startLongRunningCompositor = (maximumFrameCacheItemsInBytes, logLevel, indent) => {
|
|
29
28
|
return (0, exports.startCompositor)('StartLongRunningProcess', {
|
|
30
29
|
concurrency: (0, get_concurrency_1.getActualConcurrency)(null),
|
|
31
|
-
|
|
30
|
+
maximum_frame_cache_size_in_bytes: maximumFrameCacheItemsInBytes,
|
|
32
31
|
verbose: (0, log_level_1.isEqualOrBelowLogLevel)(logLevel, 'verbose'),
|
|
33
32
|
}, logLevel, indent);
|
|
34
33
|
};
|
|
@@ -149,17 +148,17 @@ const startCompositor = (type, payload, logLevel, indent) => {
|
|
|
149
148
|
child.on('close', (code, signal) => {
|
|
150
149
|
const waitersToKill = Array.from(waiters.values());
|
|
151
150
|
if (code === 0) {
|
|
152
|
-
runningStatus = { type: 'quit-without-error' };
|
|
151
|
+
runningStatus = { type: 'quit-without-error', signal };
|
|
153
152
|
resolve === null || resolve === void 0 ? void 0 : resolve();
|
|
154
153
|
for (const waiter of waitersToKill) {
|
|
155
|
-
waiter.reject(new Error(`Compositor
|
|
154
|
+
waiter.reject(new Error(`Compositor quit${signal ? ` with signal ${signal}` : ''}`));
|
|
156
155
|
}
|
|
157
156
|
waiters.clear();
|
|
158
157
|
}
|
|
159
158
|
else {
|
|
160
159
|
const errorMessage = Buffer.concat(stderrChunks).toString('utf-8') +
|
|
161
160
|
outputBuffer.toString('utf-8');
|
|
162
|
-
runningStatus = { type: 'quit-with-error', error: errorMessage };
|
|
161
|
+
runningStatus = { type: 'quit-with-error', error: errorMessage, signal };
|
|
163
162
|
const error = code === null
|
|
164
163
|
? new Error(`Compositor exited with signal ${signal}`)
|
|
165
164
|
: new Error(`Compositor panicked with code ${code}: ${errorMessage}`);
|
|
@@ -174,11 +173,15 @@ const startCompositor = (type, payload, logLevel, indent) => {
|
|
|
174
173
|
waitForDone: () => {
|
|
175
174
|
return new Promise((res, rej) => {
|
|
176
175
|
if (runningStatus.type === 'quit-without-error') {
|
|
177
|
-
rej(new Error(
|
|
176
|
+
rej(new Error(`Compositor quit${runningStatus.signal
|
|
177
|
+
? ` with signal ${runningStatus.signal}`
|
|
178
|
+
: ''}`));
|
|
178
179
|
return;
|
|
179
180
|
}
|
|
180
181
|
if (runningStatus.type === 'quit-with-error') {
|
|
181
|
-
rej(new Error(`Compositor
|
|
182
|
+
rej(new Error(`Compositor quit${runningStatus.signal
|
|
183
|
+
? ` with signal ${runningStatus.signal}`
|
|
184
|
+
: ''}: ${runningStatus.error}`));
|
|
182
185
|
return;
|
|
183
186
|
}
|
|
184
187
|
resolve = res;
|
|
@@ -187,16 +190,16 @@ const startCompositor = (type, payload, logLevel, indent) => {
|
|
|
187
190
|
},
|
|
188
191
|
finishCommands: () => {
|
|
189
192
|
if (runningStatus.type === 'quit-with-error') {
|
|
190
|
-
throw new Error(`Compositor
|
|
193
|
+
throw new Error(`Compositor quit${runningStatus.signal ? ` with signal ${runningStatus.signal}` : ''}: ${runningStatus.error}`);
|
|
191
194
|
}
|
|
192
195
|
if (runningStatus.type === 'quit-without-error') {
|
|
193
|
-
throw new Error(
|
|
196
|
+
throw new Error(`Compositor quit${runningStatus.signal ? ` with signal ${runningStatus.signal}` : ''}`);
|
|
194
197
|
}
|
|
195
198
|
child.stdin.write('EOF\n');
|
|
196
199
|
},
|
|
197
200
|
executeCommand: (command, params) => {
|
|
198
201
|
if (runningStatus.type === 'quit-without-error') {
|
|
199
|
-
throw new Error(
|
|
202
|
+
throw new Error(`Compositor quit${runningStatus.signal ? ` with signal ${runningStatus.signal}` : ''}`);
|
|
200
203
|
}
|
|
201
204
|
if (runningStatus.type === 'quit-with-error') {
|
|
202
205
|
throw new Error(`Compositor quit: ${runningStatus.error}`);
|
|
@@ -72,7 +72,7 @@ export type CompositorCommand = {
|
|
|
72
72
|
};
|
|
73
73
|
StartLongRunningProcess: {
|
|
74
74
|
concurrency: number;
|
|
75
|
-
|
|
75
|
+
maximum_frame_cache_size_in_bytes: number;
|
|
76
76
|
verbose: boolean;
|
|
77
77
|
};
|
|
78
78
|
CopyImageToClipboard: {
|
|
@@ -82,7 +82,7 @@ export type CompositorCommand = {
|
|
|
82
82
|
DeliberatePanic: {};
|
|
83
83
|
CloseAllVideos: {};
|
|
84
84
|
FreeUpMemory: {
|
|
85
|
-
|
|
85
|
+
remaining_bytes: number;
|
|
86
86
|
};
|
|
87
87
|
GetVideoMetadata: {
|
|
88
88
|
src: string;
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.copyImageToClipboard = void 0;
|
|
4
4
|
const compositor_1 = require("./compositor/compositor");
|
|
5
5
|
const copyImageToClipboard = async (src, logLevel) => {
|
|
6
|
-
const compositor = (0, compositor_1.startLongRunningCompositor)((0, compositor_1.
|
|
6
|
+
const compositor = (0, compositor_1.startLongRunningCompositor)((0, compositor_1.getIdealMaximumFrameCacheSizeInBytes)(), logLevel, false);
|
|
7
7
|
await compositor.executeCommand('CopyImageToClipboard', {
|
|
8
8
|
src,
|
|
9
9
|
});
|
|
@@ -4,6 +4,9 @@ export declare const createFfmpegComplexFilter: ({ filters, downloadMap, }: {
|
|
|
4
4
|
filters: PreprocessedAudioTrack[];
|
|
5
5
|
downloadMap: DownloadMap;
|
|
6
6
|
}) => Promise<{
|
|
7
|
-
complexFilterFlag: [
|
|
7
|
+
complexFilterFlag: [
|
|
8
|
+
string,
|
|
9
|
+
string
|
|
10
|
+
] | null;
|
|
8
11
|
cleanup: () => void;
|
|
9
12
|
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.determineResizeParams = void 0;
|
|
4
|
+
const determineResizeParams = (needsResize) => {
|
|
5
|
+
if (needsResize === null) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
return ['-s', `${needsResize[0]}x${needsResize[1]}`];
|
|
9
|
+
};
|
|
10
|
+
exports.determineResizeParams = determineResizeParams;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.determineVcodecFfmpegFlags = void 0;
|
|
4
|
+
const truthy_1 = require("./truthy");
|
|
5
|
+
const determineVcodecFfmpegFlags = (vcodecFlag) => {
|
|
6
|
+
return [
|
|
7
|
+
vcodecFlag === 'vp9' ? '-vcodec' : null,
|
|
8
|
+
vcodecFlag === 'vp9' ? 'libvpx-vp9' : null,
|
|
9
|
+
vcodecFlag === 'vp8' ? '-vcodec' : null,
|
|
10
|
+
vcodecFlag === 'vp8' ? 'libvpx' : null,
|
|
11
|
+
].filter(truthy_1.truthy);
|
|
12
|
+
};
|
|
13
|
+
exports.determineVcodecFfmpegFlags = determineVcodecFfmpegFlags;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type EnsureFfmpegOptions = {
|
|
2
|
+
remotionRoot?: string;
|
|
3
|
+
};
|
|
4
|
+
type Result = {
|
|
5
|
+
result: 'found-in-path' | 'found-in-node-modules' | 'installed';
|
|
6
|
+
wasAlreadyInstalled: boolean;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* @description Checks if the ffmpeg binary is installed and if it is not, downloads it and puts it into your node_modules folder.
|
|
10
|
+
* @see [Documentation](https://www.remotion.dev/docs/renderer/ensure-ffmpeg)
|
|
11
|
+
*/
|
|
12
|
+
export declare const ensureFfmpeg: (options?: EnsureFfmpegOptions) => Promise<Result>;
|
|
13
|
+
/**
|
|
14
|
+
* @description Checks if the ffprobe binary is installed and if it is not, downloads it and puts it into your node_modules folder.
|
|
15
|
+
* @see [Documentation](https://www.remotion.dev/docs/renderer/ensure-ffprobe)
|
|
16
|
+
*/
|
|
17
|
+
export declare const ensureFfprobe: (options?: EnsureFfmpegOptions) => Promise<Result>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ensureFfprobe = exports.ensureFfmpeg = void 0;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
const ffmpeg_flags_1 = require("./ffmpeg-flags");
|
|
10
|
+
const validate_ffmpeg_1 = require("./validate-ffmpeg");
|
|
11
|
+
const ensureFfmpegOrFfprobe = async (binary, options) => {
|
|
12
|
+
var _a;
|
|
13
|
+
const exists = (0, validate_ffmpeg_1.binaryExists)(binary);
|
|
14
|
+
const remotionRoot = (_a = options === null || options === void 0 ? void 0 : options.remotionRoot) !== null && _a !== void 0 ? _a : process.cwd();
|
|
15
|
+
if (exists) {
|
|
16
|
+
return {
|
|
17
|
+
wasAlreadyInstalled: true,
|
|
18
|
+
result: 'found-in-path',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (process.platform === 'linux' && (0, fs_1.existsSync)(ffmpeg_flags_1.lambdaFfmpegPaths[binary])) {
|
|
22
|
+
return {
|
|
23
|
+
wasAlreadyInstalled: true,
|
|
24
|
+
result: 'found-in-path',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if ((0, ffmpeg_flags_1.ffmpegInNodeModules)(remotionRoot, binary)) {
|
|
28
|
+
return {
|
|
29
|
+
result: 'found-in-node-modules',
|
|
30
|
+
wasAlreadyInstalled: true,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const binaryUrl = (0, ffmpeg_flags_1.getBinaryDownloadUrl)(binary);
|
|
34
|
+
if (binaryUrl) {
|
|
35
|
+
await (0, ffmpeg_flags_1.downloadBinary)(remotionRoot, binaryUrl.url, binary);
|
|
36
|
+
return {
|
|
37
|
+
result: 'installed',
|
|
38
|
+
wasAlreadyInstalled: false,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`${binary} could not be installed automatically. Your architecture and OS combination (os = ${os_1.default.platform()}, arch = ${process.arch}) is not supported. Please install ${binary} manually and add "${binary}" to your PATH.`);
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* @description Checks if the ffmpeg binary is installed and if it is not, downloads it and puts it into your node_modules folder.
|
|
45
|
+
* @see [Documentation](https://www.remotion.dev/docs/renderer/ensure-ffmpeg)
|
|
46
|
+
*/
|
|
47
|
+
const ensureFfmpeg = (options) => {
|
|
48
|
+
return ensureFfmpegOrFfprobe('ffmpeg', options);
|
|
49
|
+
};
|
|
50
|
+
exports.ensureFfmpeg = ensureFfmpeg;
|
|
51
|
+
/**
|
|
52
|
+
* @description Checks if the ffprobe binary is installed and if it is not, downloads it and puts it into your node_modules folder.
|
|
53
|
+
* @see [Documentation](https://www.remotion.dev/docs/renderer/ensure-ffprobe)
|
|
54
|
+
*/
|
|
55
|
+
const ensureFfprobe = (options) => {
|
|
56
|
+
return ensureFfmpegOrFfprobe('ffprobe', options);
|
|
57
|
+
};
|
|
58
|
+
exports.ensureFfprobe = ensureFfprobe;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DownloadMap } from './assets/download-map';
|
|
2
|
+
import type { FfmpegExecutable } from './ffmpeg-executable';
|
|
3
|
+
export declare const ensurePresentationTimestampWithoutCache: ({ src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }: {
|
|
4
|
+
src: string;
|
|
5
|
+
remotionRoot: string;
|
|
6
|
+
ffmpegExecutable: FfmpegExecutable;
|
|
7
|
+
ffprobeExecutable: FfmpegExecutable;
|
|
8
|
+
}) => Promise<string>;
|
|
9
|
+
export declare const ensurePresentationTimestamps: ({ downloadMap, src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }: {
|
|
10
|
+
downloadMap: DownloadMap;
|
|
11
|
+
src: string;
|
|
12
|
+
remotionRoot: string;
|
|
13
|
+
ffmpegExecutable: FfmpegExecutable;
|
|
14
|
+
ffprobeExecutable: FfmpegExecutable;
|
|
15
|
+
}) => Promise<string>;
|