@remotion/renderer 4.0.16 → 4.0.18
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/dist/assets/get-video-stream-duration.d.ts +9 -0
- package/dist/assets/get-video-stream-duration.js +71 -0
- package/dist/browser/BrowserFetcher.d.ts +2 -19
- package/dist/browser/BrowserFetcher.js +73 -263
- package/dist/browser/LaunchOptions.d.ts +0 -2
- package/dist/browser/Launcher.d.ts +0 -5
- package/dist/browser/Launcher.js +5 -14
- package/dist/browser/PuppeteerNode.d.ts +1 -8
- package/dist/browser/PuppeteerNode.js +10 -27
- package/dist/browser/node.js +1 -5
- package/dist/browser.d.ts +1 -1
- package/dist/calculate-sar-dar-pixels.d.ts +9 -0
- package/dist/calculate-sar-dar-pixels.js +19 -0
- package/dist/client.d.ts +48 -48
- package/dist/compositor/payloads.d.ts +18 -0
- 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/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-extension-from-codec.d.ts +2 -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-local-browser-executable.d.ts +2 -3
- package/dist/get-local-browser-executable.js +45 -53
- package/dist/get-silent-parts.d.ts +8 -0
- package/dist/get-silent-parts.js +56 -0
- package/dist/get-video-info.d.ts +8 -0
- package/dist/get-video-info.js +59 -0
- package/dist/index.d.ts +45 -42
- package/dist/index.js +4 -1
- 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/open-browser.js +3 -3
- package/dist/quality.d.ts +1 -0
- package/dist/quality.js +21 -0
- package/dist/render-media.js +5 -2
- package/dist/set-props-and-env.js +6 -3
- package/dist/stitch-frames-to-video.d.ts +1 -0
- 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 +2 -3
- package/dist/validate-opengl-renderer.js +9 -4
- package/dist/validate-output-filename.d.ts +1 -1
- package/dist/warn-about-ffmpeg-version.d.ts +5 -0
- package/dist/warn-about-ffmpeg-version.js +37 -0
- package/package.json +9 -10
|
@@ -0,0 +1,72 @@
|
|
|
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.getFrameOfVideoSlow = void 0;
|
|
7
|
+
// Uses no seeking, therefore the whole video has to be decoded. This is a last resort and should only happen
|
|
8
|
+
// if the video is corrupted
|
|
9
|
+
const execa_1 = __importDefault(require("execa"));
|
|
10
|
+
const determine_resize_params_1 = require("./determine-resize-params");
|
|
11
|
+
const determine_vcodec_ffmpeg_flags_1 = require("./determine-vcodec-ffmpeg-flags");
|
|
12
|
+
const ffmpeg_flags_1 = require("./ffmpeg-flags");
|
|
13
|
+
const truthy_1 = require("./truthy");
|
|
14
|
+
const getFrameOfVideoSlow = async ({ src, duration, ffmpegExecutable, imageFormat, specialVCodecForTransparency, needsResize, offset, fps, remotionRoot, }) => {
|
|
15
|
+
console.warn(`\nUsing a slow method to extract the frame at ${duration}ms of ${src}. See https://remotion.dev/docs/slow-method-to-extract-frame for advice`);
|
|
16
|
+
const actualOffset = `-${duration * 1000 - offset}ms`;
|
|
17
|
+
const command = [
|
|
18
|
+
'-itsoffset',
|
|
19
|
+
actualOffset,
|
|
20
|
+
...(0, determine_vcodec_ffmpeg_flags_1.determineVcodecFfmpegFlags)(specialVCodecForTransparency),
|
|
21
|
+
'-i',
|
|
22
|
+
src,
|
|
23
|
+
'-frames:v',
|
|
24
|
+
'1',
|
|
25
|
+
'-c:v',
|
|
26
|
+
imageFormat === 'jpeg' ? 'mjpeg' : 'png',
|
|
27
|
+
'-f',
|
|
28
|
+
'image2pipe',
|
|
29
|
+
...(0, determine_resize_params_1.determineResizeParams)(needsResize),
|
|
30
|
+
'-',
|
|
31
|
+
].filter(truthy_1.truthy);
|
|
32
|
+
const { stdout, stderr } = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffmpegExecutable, remotionRoot, 'ffmpeg'), command);
|
|
33
|
+
if (!stderr) {
|
|
34
|
+
throw new Error('unexpectedly did not get stderr');
|
|
35
|
+
}
|
|
36
|
+
if (!stdout) {
|
|
37
|
+
throw new Error('unexpectedly did not get stdout');
|
|
38
|
+
}
|
|
39
|
+
const stderrChunks = [];
|
|
40
|
+
const stdoutChunks = [];
|
|
41
|
+
const stdErrString = new Promise((resolve, reject) => {
|
|
42
|
+
stderr.on('data', (d) => stderrChunks.push(d));
|
|
43
|
+
stderr.on('error', (err) => reject(err));
|
|
44
|
+
stderr.on('end', () => resolve(Buffer.concat(stderrChunks).toString('utf-8')));
|
|
45
|
+
});
|
|
46
|
+
const stdoutChunk = new Promise((resolve, reject) => {
|
|
47
|
+
stdout.on('data', (d) => stdoutChunks.push(d));
|
|
48
|
+
stdout.on('error', (err) => reject(err));
|
|
49
|
+
stdout.on('end', () => resolve(Buffer.concat(stdoutChunks)));
|
|
50
|
+
});
|
|
51
|
+
const [stdErr, stdoutBuffer] = await Promise.all([stdErrString, stdoutChunk]);
|
|
52
|
+
const isEmpty = stdErr.includes('Output file is empty');
|
|
53
|
+
if (isEmpty) {
|
|
54
|
+
if (offset > 70) {
|
|
55
|
+
throw new Error(`Could not get last frame of ${src}. Tried to seek to the end using the command "ffmpeg ${command.join(' ')}" but got no frame. Most likely this video is corrupted.`);
|
|
56
|
+
}
|
|
57
|
+
return (0, exports.getFrameOfVideoSlow)({
|
|
58
|
+
ffmpegExecutable,
|
|
59
|
+
duration,
|
|
60
|
+
// Decrement in 10ms increments, or 1 frame (e.g. fps = 25 --> 40ms)
|
|
61
|
+
offset: offset + (fps === null ? 10 : 1000 / fps),
|
|
62
|
+
src,
|
|
63
|
+
imageFormat,
|
|
64
|
+
specialVCodecForTransparency,
|
|
65
|
+
needsResize,
|
|
66
|
+
fps,
|
|
67
|
+
remotionRoot,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return stdoutBuffer;
|
|
71
|
+
};
|
|
72
|
+
exports.getFrameOfVideoSlow = getFrameOfVideoSlow;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Browser } from './browser';
|
|
2
1
|
import type { BrowserExecutable } from './browser-executable';
|
|
3
|
-
export declare const ensureLocalBrowser: (
|
|
4
|
-
export declare const getLocalBrowserExecutable: (
|
|
2
|
+
export declare const ensureLocalBrowser: (preferredBrowserExecutable: BrowserExecutable) => Promise<void>;
|
|
3
|
+
export declare const getLocalBrowserExecutable: (preferredBrowserExecutable: BrowserExecutable) => string;
|
|
@@ -7,85 +7,77 @@ exports.getLocalBrowserExecutable = exports.ensureLocalBrowser = void 0;
|
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_os_1 = __importDefault(require("node:os"));
|
|
9
9
|
const BrowserFetcher_1 = require("./browser/BrowserFetcher");
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const getSearchPathsForProduct = (product) => {
|
|
10
|
+
const logger_1 = require("./logger");
|
|
11
|
+
const getSearchPathsForProduct = () => {
|
|
13
12
|
var _a;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
].filter(Boolean);
|
|
47
|
-
}
|
|
48
|
-
if (product === 'firefox') {
|
|
49
|
-
return [].filter(Boolean);
|
|
50
|
-
}
|
|
51
|
-
throw new TypeError(`Unknown browser product: ${product}`);
|
|
13
|
+
return [
|
|
14
|
+
(_a = process.env.PUPPETEER_EXECUTABLE_PATH) !== null && _a !== void 0 ? _a : null,
|
|
15
|
+
process.platform === 'darwin'
|
|
16
|
+
? '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
|
|
17
|
+
: null,
|
|
18
|
+
process.platform === 'linux' ? '/usr/bin/google-chrome' : null,
|
|
19
|
+
process.platform === 'linux' ? '/usr/bin/chromium-browser' : null,
|
|
20
|
+
process.platform === 'linux' ? '/usr/bin/chromium' : null,
|
|
21
|
+
process.platform === 'linux'
|
|
22
|
+
? '/app/.apt/usr/bin/google-chrome-stable'
|
|
23
|
+
: null,
|
|
24
|
+
process.platform === 'win32'
|
|
25
|
+
? 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'
|
|
26
|
+
: null,
|
|
27
|
+
process.platform === 'win32'
|
|
28
|
+
? 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'
|
|
29
|
+
: null,
|
|
30
|
+
process.platform === 'win32'
|
|
31
|
+
? node_os_1.default.homedir() +
|
|
32
|
+
'\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe'
|
|
33
|
+
: null,
|
|
34
|
+
process.platform === 'win32'
|
|
35
|
+
? 'C:\\Program Files\\Google\\Chrome SxS\\Application\\chrome.exe'
|
|
36
|
+
: null,
|
|
37
|
+
process.platform === 'win32'
|
|
38
|
+
? 'C:\\Program Files (x86)\\Google\\Chrome SxS\\Application\\chrome.exe'
|
|
39
|
+
: null,
|
|
40
|
+
process.platform === 'win32'
|
|
41
|
+
? node_os_1.default.homedir() +
|
|
42
|
+
'\\AppData\\Local\\Google\\Chrome SxS\\Application\\chrome.exe'
|
|
43
|
+
: null,
|
|
44
|
+
].filter(Boolean);
|
|
52
45
|
};
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
for (const p of getSearchPathsForProduct(product)) {
|
|
46
|
+
const getLocalBrowser = () => {
|
|
47
|
+
for (const p of getSearchPathsForProduct()) {
|
|
56
48
|
if (node_fs_1.default.existsSync(p)) {
|
|
57
49
|
return p;
|
|
58
50
|
}
|
|
59
51
|
}
|
|
60
52
|
return null;
|
|
61
53
|
};
|
|
62
|
-
const getBrowserStatus = (
|
|
54
|
+
const getBrowserStatus = (browserExecutablePath) => {
|
|
63
55
|
if (browserExecutablePath) {
|
|
64
56
|
if (!node_fs_1.default.existsSync(browserExecutablePath)) {
|
|
65
57
|
console.warn(`Browser executable was specified as '${browserExecutablePath}' but the path doesn't exist.`);
|
|
66
58
|
}
|
|
67
59
|
return { path: browserExecutablePath, type: 'user-defined-path' };
|
|
68
60
|
}
|
|
69
|
-
const localBrowser = getLocalBrowser(
|
|
61
|
+
const localBrowser = getLocalBrowser();
|
|
70
62
|
if (localBrowser !== null) {
|
|
71
63
|
return { path: localBrowser, type: 'local-browser' };
|
|
72
64
|
}
|
|
73
|
-
const revision = (0, BrowserFetcher_1.getRevisionInfo)(
|
|
65
|
+
const revision = (0, BrowserFetcher_1.getRevisionInfo)();
|
|
74
66
|
if (revision.local && node_fs_1.default.existsSync(revision.executablePath)) {
|
|
75
67
|
return { path: revision.executablePath, type: 'local-puppeteer-browser' };
|
|
76
68
|
}
|
|
77
69
|
return { type: 'no-browser' };
|
|
78
70
|
};
|
|
79
|
-
const ensureLocalBrowser = async (
|
|
80
|
-
const status = getBrowserStatus(
|
|
71
|
+
const ensureLocalBrowser = async (preferredBrowserExecutable) => {
|
|
72
|
+
const status = getBrowserStatus(preferredBrowserExecutable);
|
|
81
73
|
if (status.type === 'no-browser') {
|
|
82
|
-
|
|
83
|
-
await (0,
|
|
74
|
+
logger_1.Log.info('No local browser could be found. Downloading Thorium https://www.remotion.dev/docs/thorium-browser');
|
|
75
|
+
await (0, BrowserFetcher_1.downloadBrowser)();
|
|
84
76
|
}
|
|
85
77
|
};
|
|
86
78
|
exports.ensureLocalBrowser = ensureLocalBrowser;
|
|
87
|
-
const getLocalBrowserExecutable = (
|
|
88
|
-
const status = getBrowserStatus(
|
|
79
|
+
const getLocalBrowserExecutable = (preferredBrowserExecutable) => {
|
|
80
|
+
const status = getBrowserStatus(preferredBrowserExecutable);
|
|
89
81
|
if (status.type === 'no-browser') {
|
|
90
82
|
throw new TypeError('No browser found for rendering frames! Please open a GitHub issue and describe ' +
|
|
91
83
|
'how you reached this error: https://github.com/remotion-dev/remotion/issues');
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GetSilentPartsResponse } from './compositor/payloads';
|
|
2
|
+
import type { LogLevel } from './log-level';
|
|
3
|
+
export declare const getSilentParts: ({ src, noiseThresholdInDecibels: passedNoiseThresholdInDecibels, minDurationInSeconds: passedMinDuration, logLevel, }: {
|
|
4
|
+
src: string;
|
|
5
|
+
minDurationInSeconds?: number | undefined;
|
|
6
|
+
logLevel?: "verbose" | "info" | "warn" | "error" | undefined;
|
|
7
|
+
noiseThresholdInDecibels?: number | undefined;
|
|
8
|
+
}) => Promise<GetSilentPartsResponse>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSilentParts = void 0;
|
|
4
|
+
const compositor_1 = require("./compositor/compositor");
|
|
5
|
+
const getSilentParts = async ({ src, noiseThresholdInDecibels: passedNoiseThresholdInDecibels, minDurationInSeconds: passedMinDuration, logLevel, }) => {
|
|
6
|
+
const compositor = (0, compositor_1.startLongRunningCompositor)((0, compositor_1.getIdealMaximumFrameCacheItems)(), logLevel !== null && logLevel !== void 0 ? logLevel : 'info', false);
|
|
7
|
+
const minDurationInSeconds = passedMinDuration !== null && passedMinDuration !== void 0 ? passedMinDuration : 1;
|
|
8
|
+
if (typeof minDurationInSeconds !== 'number') {
|
|
9
|
+
throw new Error(`minDurationInSeconds must be a number, but was ${minDurationInSeconds}`);
|
|
10
|
+
}
|
|
11
|
+
if (minDurationInSeconds <= 0) {
|
|
12
|
+
throw new Error(`minDurationInSeconds must be greater than 0, but was ${minDurationInSeconds}`);
|
|
13
|
+
}
|
|
14
|
+
const noiseThresholdInDecibels = passedNoiseThresholdInDecibels !== null && passedNoiseThresholdInDecibels !== void 0 ? passedNoiseThresholdInDecibels : -20;
|
|
15
|
+
if (typeof noiseThresholdInDecibels !== 'number') {
|
|
16
|
+
throw new Error(`noiseThresholdInDecibels must be a number, but was ${noiseThresholdInDecibels}`);
|
|
17
|
+
}
|
|
18
|
+
if (noiseThresholdInDecibels >= 30) {
|
|
19
|
+
throw new Error(`noiseThresholdInDecibels must be less than 30, but was ${noiseThresholdInDecibels}`);
|
|
20
|
+
}
|
|
21
|
+
const res = await compositor.executeCommand('GetSilences', {
|
|
22
|
+
src,
|
|
23
|
+
minDurationInSeconds,
|
|
24
|
+
noiseThresholdInDecibels,
|
|
25
|
+
});
|
|
26
|
+
const response = JSON.parse(res.toString('utf-8'));
|
|
27
|
+
compositor.finishCommands();
|
|
28
|
+
await compositor.waitForDone();
|
|
29
|
+
const { silentParts, durationInSeconds } = response;
|
|
30
|
+
return {
|
|
31
|
+
silentParts,
|
|
32
|
+
audibleParts: getAudibleParts({ silentParts, durationInSeconds }),
|
|
33
|
+
durationInSeconds,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
exports.getSilentParts = getSilentParts;
|
|
37
|
+
const getAudibleParts = ({ silentParts, durationInSeconds, }) => {
|
|
38
|
+
const audibleParts = [];
|
|
39
|
+
let lastEnd = 0;
|
|
40
|
+
for (const silentPart of silentParts) {
|
|
41
|
+
if (silentPart.startInSeconds - lastEnd > 0) {
|
|
42
|
+
audibleParts.push({
|
|
43
|
+
startInSeconds: lastEnd,
|
|
44
|
+
endInSeconds: silentPart.startInSeconds,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
lastEnd = silentPart.endInSeconds;
|
|
48
|
+
}
|
|
49
|
+
if (durationInSeconds - lastEnd > 0) {
|
|
50
|
+
audibleParts.push({
|
|
51
|
+
startInSeconds: lastEnd,
|
|
52
|
+
endInSeconds: durationInSeconds,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return audibleParts;
|
|
56
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DownloadMap, Vp9Result } from './assets/download-map';
|
|
2
|
+
import type { FfmpegExecutable } from './ffmpeg-executable';
|
|
3
|
+
export declare function getVideoInfoUncached({ src, ffprobeExecutable, remotionRoot, }: {
|
|
4
|
+
src: string;
|
|
5
|
+
ffprobeExecutable: FfmpegExecutable;
|
|
6
|
+
remotionRoot: string;
|
|
7
|
+
}): Promise<Vp9Result>;
|
|
8
|
+
export declare const getVideoInfo: (downloadMap: DownloadMap, src: string, ffprobeExecutable: FfmpegExecutable, remotionRoot: string) => Promise<Vp9Result>;
|
|
@@ -0,0 +1,59 @@
|
|
|
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.getVideoInfo = exports.getVideoInfoUncached = void 0;
|
|
7
|
+
const execa_1 = __importDefault(require("execa"));
|
|
8
|
+
const calculate_sar_dar_pixels_1 = require("./calculate-sar-dar-pixels");
|
|
9
|
+
const ffmpeg_flags_1 = require("./ffmpeg-flags");
|
|
10
|
+
const p_limit_1 = require("./p-limit");
|
|
11
|
+
const limit = (0, p_limit_1.pLimit)(1);
|
|
12
|
+
async function getVideoInfoUncached({ src, ffprobeExecutable, remotionRoot, }) {
|
|
13
|
+
var _a;
|
|
14
|
+
const task = await (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffprobeExecutable, remotionRoot, 'ffprobe'), [src]);
|
|
15
|
+
const isVp9 = task.stderr.includes('Video: vp9');
|
|
16
|
+
const isVp8 = task.stderr.includes('Video: vp8');
|
|
17
|
+
const dimensions = (_a = task.stderr
|
|
18
|
+
.split('\n')
|
|
19
|
+
.find((n) => n.trim().startsWith('Stream #'))) === null || _a === void 0 ? void 0 : _a.match(/([0-9]{2,6})x([0-9]{2,6})/);
|
|
20
|
+
const dar = task.stderr.match(/DAR\s([0-9]+):([0-9]+)/);
|
|
21
|
+
let needsResize = null;
|
|
22
|
+
if (dimensions && dar) {
|
|
23
|
+
const width = parseInt(dimensions[1], 10);
|
|
24
|
+
const height = parseInt(dimensions[2], 10);
|
|
25
|
+
const darWidth = parseInt(dar[1], 10);
|
|
26
|
+
const darHeight = parseInt(dar[2], 10);
|
|
27
|
+
const { width: actualWidth, height: actualHeight } = (0, calculate_sar_dar_pixels_1.calculateDisplayVideoSize)({
|
|
28
|
+
darX: darWidth,
|
|
29
|
+
darY: darHeight,
|
|
30
|
+
x: width,
|
|
31
|
+
y: height,
|
|
32
|
+
});
|
|
33
|
+
if (actualWidth !== width || actualHeight !== height) {
|
|
34
|
+
needsResize = [actualWidth, actualHeight];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const result = {
|
|
38
|
+
specialVcodecForTransparency: isVp9 ? 'vp9' : isVp8 ? 'vp8' : 'none',
|
|
39
|
+
needsResize,
|
|
40
|
+
};
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
exports.getVideoInfoUncached = getVideoInfoUncached;
|
|
44
|
+
async function getVideoInfoUnlimited(downloadMap, src, ffprobeExecutable, remotionRoot) {
|
|
45
|
+
if (typeof downloadMap.isVp9VideoCache[src] !== 'undefined') {
|
|
46
|
+
return downloadMap.isVp9VideoCache[src];
|
|
47
|
+
}
|
|
48
|
+
const result = await getVideoInfoUncached({
|
|
49
|
+
ffprobeExecutable,
|
|
50
|
+
remotionRoot,
|
|
51
|
+
src,
|
|
52
|
+
});
|
|
53
|
+
downloadMap.isVp9VideoCache[src] = result;
|
|
54
|
+
return downloadMap.isVp9VideoCache[src];
|
|
55
|
+
}
|
|
56
|
+
const getVideoInfo = (downloadMap, src, ffprobeExecutable, remotionRoot) => {
|
|
57
|
+
return limit(() => getVideoInfoUnlimited(downloadMap, src, ffprobeExecutable, remotionRoot));
|
|
58
|
+
};
|
|
59
|
+
exports.getVideoInfo = getVideoInfo;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import execa from 'execa';
|
|
2
3
|
import { HeadlessBrowser } from './browser/Browser';
|
|
3
4
|
import { SymbolicateableError } from './error-handling/symbolicateable-error';
|
|
@@ -16,6 +17,7 @@ export type { FfmpegOverrideFn } from './ffmpeg-override';
|
|
|
16
17
|
export { FileExtension } from './file-extensions';
|
|
17
18
|
export { FrameRange } from './frame-range';
|
|
18
19
|
export { getCompositions, GetCompositionsOptions } from './get-compositions';
|
|
20
|
+
export { getSilentParts } from './get-silent-parts';
|
|
19
21
|
export { getVideoMetadata } from './get-video-metadata';
|
|
20
22
|
export { ImageFormat, StillImageFormat, validateSelectedPixelFormatAndImageFormatCombination, VideoImageFormat, } from './image-format';
|
|
21
23
|
export type { LogLevel } from './log-level';
|
|
@@ -36,7 +38,7 @@ export { OnStartData, RenderFramesOutput } from './types';
|
|
|
36
38
|
export { OpenGlRenderer } from './validate-opengl-renderer';
|
|
37
39
|
export { validateOutputFilename } from './validate-output-filename';
|
|
38
40
|
export declare const RenderInternals: {
|
|
39
|
-
ensureLocalBrowser: (
|
|
41
|
+
ensureLocalBrowser: (preferredBrowserExecutable: import("./browser-executable").BrowserExecutable) => Promise<void>;
|
|
40
42
|
getActualConcurrency: (userPreference: string | number | null) => number;
|
|
41
43
|
serveStatic: (path: string | null, options: {
|
|
42
44
|
port: number | null;
|
|
@@ -54,9 +56,9 @@ export declare const RenderInternals: {
|
|
|
54
56
|
width: number;
|
|
55
57
|
height: number;
|
|
56
58
|
scale: number;
|
|
57
|
-
codec: "
|
|
59
|
+
codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
58
60
|
}) => void;
|
|
59
|
-
getFileExtensionFromCodec: <T extends "
|
|
61
|
+
getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">(codec: T, audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null) => import("./file-extensions").FileExtension;
|
|
60
62
|
tmpDir: (str: string) => string;
|
|
61
63
|
deleteDirectory: (directory: string) => void;
|
|
62
64
|
isServeUrl: (potentialUrl: string) => boolean;
|
|
@@ -106,21 +108,21 @@ export declare const RenderInternals: {
|
|
|
106
108
|
};
|
|
107
109
|
registerErrorSymbolicationLock: () => number;
|
|
108
110
|
unlockErrorSymbolicationLock: (id: number) => void;
|
|
109
|
-
canUseParallelEncoding: (codec: "
|
|
111
|
+
canUseParallelEncoding: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
|
|
110
112
|
mimeContentType: typeof mimeContentType;
|
|
111
113
|
mimeLookup: typeof mimeLookup;
|
|
112
114
|
validateConcurrency: (value: unknown, setting: string) => void;
|
|
113
115
|
validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
|
|
114
|
-
DEFAULT_BROWSER:
|
|
116
|
+
DEFAULT_BROWSER: "chrome";
|
|
115
117
|
validateFrameRange: (frameRange: import("./frame-range").FrameRange | null) => void;
|
|
116
|
-
DEFAULT_OPENGL_RENDERER: "
|
|
117
|
-
validateOpenGlRenderer: (option: "
|
|
118
|
+
DEFAULT_OPENGL_RENDERER: "angle" | "swangle" | "egl" | "swiftshader" | null;
|
|
119
|
+
validateOpenGlRenderer: (option: "angle" | "swangle" | "egl" | "swiftshader" | null) => "angle" | "swangle" | "egl" | "swiftshader" | null;
|
|
118
120
|
validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
|
|
119
121
|
DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
|
|
120
122
|
validateJpegQuality: (q: number | undefined) => void;
|
|
121
123
|
DEFAULT_TIMEOUT: number;
|
|
122
|
-
DEFAULT_CODEC: "
|
|
123
|
-
isAudioCodec: (codec: "
|
|
124
|
+
DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
125
|
+
isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
|
|
124
126
|
logLevels: readonly ["verbose", "info", "warn", "error"];
|
|
125
127
|
isEqualOrBelowLogLevel: (currentLevel: "verbose" | "info" | "warn" | "error", level: "verbose" | "info" | "warn" | "error") => boolean;
|
|
126
128
|
isValidLogLevel: (level: string) => boolean;
|
|
@@ -137,23 +139,23 @@ export declare const RenderInternals: {
|
|
|
137
139
|
output: string;
|
|
138
140
|
onProgress: (p: number) => void;
|
|
139
141
|
numberOfFrames: number;
|
|
140
|
-
codec: "
|
|
142
|
+
codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
141
143
|
fps: number;
|
|
142
144
|
numberOfGifLoops: number | null;
|
|
143
|
-
audioCodec: "
|
|
145
|
+
audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null;
|
|
144
146
|
}) => Promise<void>;
|
|
145
147
|
getMinConcurrency: () => number;
|
|
146
148
|
getMaxConcurrency: () => any;
|
|
147
149
|
getDefaultAudioCodec: ({ codec, preferLossless, }: {
|
|
148
|
-
codec: "
|
|
150
|
+
codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
149
151
|
preferLossless: boolean;
|
|
150
|
-
}) => "
|
|
152
|
+
}) => "mp3" | "aac" | "pcm-16" | "opus" | null;
|
|
151
153
|
validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
|
|
152
154
|
defaultFileExtensionMap: {
|
|
153
|
-
|
|
155
|
+
h264: {
|
|
154
156
|
default: import("./file-extensions").FileExtension;
|
|
155
157
|
forAudioCodec: {
|
|
156
|
-
|
|
158
|
+
mp3: {
|
|
157
159
|
possible: import("./file-extensions").FileExtension[];
|
|
158
160
|
default: import("./file-extensions").FileExtension;
|
|
159
161
|
};
|
|
@@ -161,72 +163,72 @@ export declare const RenderInternals: {
|
|
|
161
163
|
possible: import("./file-extensions").FileExtension[];
|
|
162
164
|
default: import("./file-extensions").FileExtension;
|
|
163
165
|
};
|
|
166
|
+
"pcm-16": {
|
|
167
|
+
possible: import("./file-extensions").FileExtension[];
|
|
168
|
+
default: import("./file-extensions").FileExtension;
|
|
169
|
+
};
|
|
164
170
|
};
|
|
165
171
|
};
|
|
166
|
-
|
|
172
|
+
h265: {
|
|
167
173
|
default: import("./file-extensions").FileExtension;
|
|
168
174
|
forAudioCodec: {
|
|
169
|
-
|
|
175
|
+
aac: {
|
|
170
176
|
possible: import("./file-extensions").FileExtension[];
|
|
171
177
|
default: import("./file-extensions").FileExtension;
|
|
172
178
|
};
|
|
173
|
-
|
|
179
|
+
"pcm-16": {
|
|
174
180
|
possible: import("./file-extensions").FileExtension[];
|
|
175
181
|
default: import("./file-extensions").FileExtension;
|
|
176
182
|
};
|
|
177
183
|
};
|
|
178
184
|
};
|
|
179
|
-
|
|
185
|
+
vp8: {
|
|
180
186
|
default: import("./file-extensions").FileExtension;
|
|
181
187
|
forAudioCodec: {
|
|
182
188
|
"pcm-16": {
|
|
183
189
|
possible: import("./file-extensions").FileExtension[];
|
|
184
190
|
default: import("./file-extensions").FileExtension;
|
|
185
191
|
};
|
|
186
|
-
|
|
187
|
-
possible: import("./file-extensions").FileExtension[];
|
|
188
|
-
default: import("./file-extensions").FileExtension;
|
|
189
|
-
};
|
|
190
|
-
mp3: {
|
|
192
|
+
opus: {
|
|
191
193
|
possible: import("./file-extensions").FileExtension[];
|
|
192
194
|
default: import("./file-extensions").FileExtension;
|
|
193
195
|
};
|
|
194
196
|
};
|
|
195
197
|
};
|
|
196
|
-
|
|
198
|
+
vp9: {
|
|
197
199
|
default: import("./file-extensions").FileExtension;
|
|
198
200
|
forAudioCodec: {
|
|
199
201
|
"pcm-16": {
|
|
200
202
|
possible: import("./file-extensions").FileExtension[];
|
|
201
203
|
default: import("./file-extensions").FileExtension;
|
|
202
204
|
};
|
|
203
|
-
|
|
205
|
+
opus: {
|
|
204
206
|
possible: import("./file-extensions").FileExtension[];
|
|
205
207
|
default: import("./file-extensions").FileExtension;
|
|
206
208
|
};
|
|
207
209
|
};
|
|
208
210
|
};
|
|
209
|
-
|
|
211
|
+
mp3: {
|
|
210
212
|
default: import("./file-extensions").FileExtension;
|
|
211
213
|
forAudioCodec: {
|
|
212
|
-
|
|
214
|
+
mp3: {
|
|
213
215
|
possible: import("./file-extensions").FileExtension[];
|
|
214
216
|
default: import("./file-extensions").FileExtension;
|
|
215
217
|
};
|
|
216
|
-
|
|
218
|
+
"pcm-16": {
|
|
217
219
|
possible: import("./file-extensions").FileExtension[];
|
|
218
220
|
default: import("./file-extensions").FileExtension;
|
|
219
221
|
};
|
|
220
222
|
};
|
|
221
223
|
};
|
|
222
|
-
|
|
224
|
+
aac: {
|
|
223
225
|
default: import("./file-extensions").FileExtension;
|
|
224
226
|
forAudioCodec: {
|
|
225
|
-
|
|
227
|
+
aac: {
|
|
226
228
|
possible: import("./file-extensions").FileExtension[];
|
|
227
229
|
default: import("./file-extensions").FileExtension;
|
|
228
230
|
};
|
|
229
|
-
|
|
231
|
+
"pcm-16": {
|
|
230
232
|
possible: import("./file-extensions").FileExtension[];
|
|
231
233
|
default: import("./file-extensions").FileExtension;
|
|
232
234
|
};
|
|
@@ -244,11 +246,11 @@ export declare const RenderInternals: {
|
|
|
244
246
|
prores: {
|
|
245
247
|
default: import("./file-extensions").FileExtension;
|
|
246
248
|
forAudioCodec: {
|
|
247
|
-
|
|
249
|
+
aac: {
|
|
248
250
|
possible: import("./file-extensions").FileExtension[];
|
|
249
251
|
default: import("./file-extensions").FileExtension;
|
|
250
252
|
};
|
|
251
|
-
|
|
253
|
+
"pcm-16": {
|
|
252
254
|
possible: import("./file-extensions").FileExtension[];
|
|
253
255
|
default: import("./file-extensions").FileExtension;
|
|
254
256
|
};
|
|
@@ -257,11 +259,11 @@ export declare const RenderInternals: {
|
|
|
257
259
|
"h264-mkv": {
|
|
258
260
|
default: import("./file-extensions").FileExtension;
|
|
259
261
|
forAudioCodec: {
|
|
260
|
-
|
|
262
|
+
mp3: {
|
|
261
263
|
possible: import("./file-extensions").FileExtension[];
|
|
262
264
|
default: import("./file-extensions").FileExtension;
|
|
263
265
|
};
|
|
264
|
-
|
|
266
|
+
"pcm-16": {
|
|
265
267
|
possible: import("./file-extensions").FileExtension[];
|
|
266
268
|
default: import("./file-extensions").FileExtension;
|
|
267
269
|
};
|
|
@@ -284,8 +286,8 @@ export declare const RenderInternals: {
|
|
|
284
286
|
readonly vp9: readonly ["opus", "pcm-16"];
|
|
285
287
|
readonly wav: readonly ["pcm-16"];
|
|
286
288
|
};
|
|
287
|
-
makeFileExtensionMap: () => Record<string, ("
|
|
288
|
-
defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "
|
|
289
|
+
makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif")[]>;
|
|
290
|
+
defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">;
|
|
289
291
|
getExecutablePath: (type: "compositor" | "ffmpeg" | "ffprobe" | "ffmpeg-cwd") => string;
|
|
290
292
|
callFf: (bin: "ffmpeg" | "ffprobe", args: (string | null)[], options?: execa.Options<string> | undefined) => execa.ExecaChildProcess<string>;
|
|
291
293
|
dynamicLibraryPathOptions: () => {
|
|
@@ -302,8 +304,8 @@ export declare const RenderInternals: {
|
|
|
302
304
|
};
|
|
303
305
|
validStillImageFormats: readonly ["png", "jpeg", "pdf", "webp"];
|
|
304
306
|
validVideoImageFormats: readonly ["png", "jpeg", "none"];
|
|
305
|
-
DEFAULT_STILL_IMAGE_FORMAT: "
|
|
306
|
-
DEFAULT_VIDEO_IMAGE_FORMAT: "
|
|
307
|
+
DEFAULT_STILL_IMAGE_FORMAT: "jpeg" | "png" | "webp" | "pdf";
|
|
308
|
+
DEFAULT_VIDEO_IMAGE_FORMAT: "jpeg" | "png" | "none";
|
|
307
309
|
DEFAULT_JPEG_QUALITY: number;
|
|
308
310
|
chalk: {
|
|
309
311
|
enabled: () => boolean;
|
|
@@ -414,7 +416,7 @@ export declare const RenderInternals: {
|
|
|
414
416
|
frame: number;
|
|
415
417
|
serializedInputPropsWithCustomSchema: string;
|
|
416
418
|
serializedResolvedPropsWithCustomSchema: string;
|
|
417
|
-
imageFormat: "
|
|
419
|
+
imageFormat: "jpeg" | "png" | "webp" | "pdf";
|
|
418
420
|
jpegQuality: number;
|
|
419
421
|
puppeteerInstance: HeadlessBrowser | null;
|
|
420
422
|
envVariables: Record<string, string>;
|
|
@@ -440,7 +442,7 @@ export declare const RenderInternals: {
|
|
|
440
442
|
forceDeviceScaleFactor: number | undefined;
|
|
441
443
|
viewport: import("./browser/PuppeteerViewport").Viewport | null;
|
|
442
444
|
indent: boolean;
|
|
443
|
-
browser:
|
|
445
|
+
browser: "chrome";
|
|
444
446
|
logLevel: "verbose" | "info" | "warn" | "error";
|
|
445
447
|
}) => Promise<HeadlessBrowser>;
|
|
446
448
|
internalSelectComposition: (options: {
|
|
@@ -480,4 +482,5 @@ export declare const RenderInternals: {
|
|
|
480
482
|
buffer: Buffer | null;
|
|
481
483
|
slowestFrames: import("./render-media").SlowFrame[];
|
|
482
484
|
}>;
|
|
485
|
+
validOpenGlRenderers: readonly ["swangle", "angle", "egl", "swiftshader"];
|
|
483
486
|
};
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.RenderInternals = exports.validateOutputFilename = exports.stitchFramesToVideo = exports.selectComposition = exports.renderStill = exports.renderMedia = exports.renderFrames = exports.openBrowser = exports.makeCancelSignal = exports.validateSelectedPixelFormatAndImageFormatCombination = exports.getVideoMetadata = exports.getCompositions = exports.ErrorWithStackFrame = void 0;
|
|
29
|
+
exports.RenderInternals = exports.validateOutputFilename = exports.stitchFramesToVideo = exports.selectComposition = exports.renderStill = exports.renderMedia = exports.renderFrames = exports.openBrowser = exports.makeCancelSignal = exports.validateSelectedPixelFormatAndImageFormatCombination = exports.getVideoMetadata = exports.getSilentParts = exports.getCompositions = exports.ErrorWithStackFrame = void 0;
|
|
30
30
|
const execa_1 = __importDefault(require("execa"));
|
|
31
31
|
const download_file_1 = require("./assets/download-file");
|
|
32
32
|
const audio_codec_1 = require("./audio-codec");
|
|
@@ -86,6 +86,8 @@ var handle_javascript_exception_1 = require("./error-handling/handle-javascript-
|
|
|
86
86
|
Object.defineProperty(exports, "ErrorWithStackFrame", { enumerable: true, get: function () { return handle_javascript_exception_1.ErrorWithStackFrame; } });
|
|
87
87
|
var get_compositions_2 = require("./get-compositions");
|
|
88
88
|
Object.defineProperty(exports, "getCompositions", { enumerable: true, get: function () { return get_compositions_2.getCompositions; } });
|
|
89
|
+
var get_silent_parts_1 = require("./get-silent-parts");
|
|
90
|
+
Object.defineProperty(exports, "getSilentParts", { enumerable: true, get: function () { return get_silent_parts_1.getSilentParts; } });
|
|
89
91
|
var get_video_metadata_1 = require("./get-video-metadata");
|
|
90
92
|
Object.defineProperty(exports, "getVideoMetadata", { enumerable: true, get: function () { return get_video_metadata_1.getVideoMetadata; } });
|
|
91
93
|
var image_format_2 = require("./image-format");
|
|
@@ -184,6 +186,7 @@ exports.RenderInternals = {
|
|
|
184
186
|
internalGetCompositions: get_compositions_1.internalGetCompositions,
|
|
185
187
|
internalRenderFrames: render_frames_1.internalRenderFrames,
|
|
186
188
|
internalRenderMedia: render_media_1.internalRenderMedia,
|
|
189
|
+
validOpenGlRenderers: validate_opengl_renderer_1.validOpenGlRenderers,
|
|
187
190
|
};
|
|
188
191
|
// Warn of potential performance issues with Apple Silicon (M1 chip under Rosetta)
|
|
189
192
|
(0, check_apple_silicon_1.checkNodeVersionAndWarnAboutRosetta)();
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DownloadMap } from './assets/download-map';
|
|
2
|
+
export declare const isBeyondLastFrame: (downloadMap: DownloadMap, src: string, time: number) => boolean | 0;
|
|
3
|
+
export declare const markAsBeyondLastFrame: (downloadMap: DownloadMap, src: string, time: number) => void;
|