@remotion/renderer 4.0.0-preload.17 → 4.0.0-spawn.14
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/download-and-map-assets-to-file.d.ts +1 -1
- package/dist/assets/download-and-map-assets-to-file.js +30 -13
- package/dist/cycle-browser-tabs.d.ts +2 -1
- package/dist/cycle-browser-tabs.js +2 -2
- package/dist/extract-frame-from-video.d.ts +1 -0
- package/dist/get-compositions.d.ts +1 -1
- package/dist/get-compositions.js +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/merge-audio-track.js +2 -2
- package/dist/offthread-video-server.js +4 -3
- package/dist/open-browser.d.ts +5 -5
- package/dist/prespawn-ffmpeg.d.ts +1 -0
- package/dist/prespawn-ffmpeg.js +4 -1
- package/dist/puppeteer-screenshot.js +5 -1
- package/dist/render-frames.d.ts +4 -1
- package/dist/render-frames.js +69 -30
- package/dist/render-media.d.ts +5 -1
- package/dist/render-media.js +49 -3
- package/dist/render-still.js +6 -1
- package/dist/set-props-and-env.d.ts +2 -1
- package/dist/set-props-and-env.js +20 -1
- package/dist/tmp-dir.js +5 -1
- package/package.json +4 -4
|
@@ -2,7 +2,7 @@ import { TAsset } from 'remotion';
|
|
|
2
2
|
export declare type RenderMediaOnDownload = (src: string) => ((progress: {
|
|
3
3
|
percent: number;
|
|
4
4
|
}) => void) | undefined | void;
|
|
5
|
-
export declare const waitForAssetToBeDownloaded: (src: string) => Promise<
|
|
5
|
+
export declare const waitForAssetToBeDownloaded: (src: string, to: string) => Promise<void>;
|
|
6
6
|
export declare const markAllAssetsAsDownloaded: () => void;
|
|
7
7
|
export declare const getSanitizedFilenameForAssetUrl: ({ src, downloadDir, }: {
|
|
8
8
|
src: string;
|
|
@@ -13,25 +13,38 @@ const sanitize_filepath_1 = require("./sanitize-filepath");
|
|
|
13
13
|
const isDownloadingMap = {};
|
|
14
14
|
const hasBeenDownloadedMap = {};
|
|
15
15
|
const listeners = {};
|
|
16
|
-
const waitForAssetToBeDownloaded = (src) => {
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const waitForAssetToBeDownloaded = (src, to) => {
|
|
17
|
+
var _a;
|
|
18
|
+
if ((_a = hasBeenDownloadedMap[src]) === null || _a === void 0 ? void 0 : _a[to]) {
|
|
19
|
+
return Promise.resolve();
|
|
19
20
|
}
|
|
20
21
|
if (!listeners[src]) {
|
|
21
|
-
listeners[src] =
|
|
22
|
+
listeners[src] = {};
|
|
23
|
+
}
|
|
24
|
+
if (!listeners[src][to]) {
|
|
25
|
+
listeners[src][to] = [];
|
|
22
26
|
}
|
|
23
27
|
return new Promise((resolve) => {
|
|
24
|
-
listeners[src].push((
|
|
28
|
+
listeners[src][to].push(() => resolve());
|
|
25
29
|
});
|
|
26
30
|
};
|
|
27
31
|
exports.waitForAssetToBeDownloaded = waitForAssetToBeDownloaded;
|
|
28
32
|
const notifyAssetIsDownloaded = (src, to) => {
|
|
29
33
|
if (!listeners[src]) {
|
|
30
|
-
listeners[src] =
|
|
34
|
+
listeners[src] = {};
|
|
35
|
+
}
|
|
36
|
+
if (!listeners[src][to]) {
|
|
37
|
+
listeners[src][to] = [];
|
|
38
|
+
}
|
|
39
|
+
listeners[src][to].forEach((fn) => fn());
|
|
40
|
+
if (!isDownloadingMap[src]) {
|
|
41
|
+
isDownloadingMap[src] = {};
|
|
31
42
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
isDownloadingMap[src][to] = false;
|
|
44
|
+
if (!hasBeenDownloadedMap[src]) {
|
|
45
|
+
hasBeenDownloadedMap[src] = {};
|
|
46
|
+
}
|
|
47
|
+
hasBeenDownloadedMap[src][to] = true;
|
|
35
48
|
};
|
|
36
49
|
const validateMimeType = (mimeType, src) => {
|
|
37
50
|
if (!mimeType.includes('/')) {
|
|
@@ -73,13 +86,17 @@ function validateBufferEncoding(potentialEncoding, dataUrl) {
|
|
|
73
86
|
}
|
|
74
87
|
}
|
|
75
88
|
const downloadAsset = async (src, to, onDownload) => {
|
|
76
|
-
|
|
89
|
+
var _a, _b;
|
|
90
|
+
if ((_a = hasBeenDownloadedMap[src]) === null || _a === void 0 ? void 0 : _a[to]) {
|
|
77
91
|
return;
|
|
78
92
|
}
|
|
79
|
-
if (isDownloadingMap[src]) {
|
|
80
|
-
return (0, exports.waitForAssetToBeDownloaded)(src);
|
|
93
|
+
if ((_b = isDownloadingMap[src]) === null || _b === void 0 ? void 0 : _b[to]) {
|
|
94
|
+
return (0, exports.waitForAssetToBeDownloaded)(src, to);
|
|
95
|
+
}
|
|
96
|
+
if (!isDownloadingMap[src]) {
|
|
97
|
+
isDownloadingMap[src] = {};
|
|
81
98
|
}
|
|
82
|
-
isDownloadingMap[src] = true;
|
|
99
|
+
isDownloadingMap[src][to] = true;
|
|
83
100
|
const onProgress = onDownload(src);
|
|
84
101
|
(0, ensure_output_directory_1.ensureOutputDirectory)(to);
|
|
85
102
|
if (src.startsWith('data:')) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { openBrowser } from './open-browser';
|
|
2
2
|
declare type Await<T> = T extends PromiseLike<infer U> ? U : T;
|
|
3
|
-
|
|
3
|
+
declare type Browser = ReturnType<typeof openBrowser>;
|
|
4
|
+
export declare const cycleBrowserTabs: (puppeteerInstance: Browser | Await<Browser>, concurrency: number) => {
|
|
4
5
|
stopCycling: () => void;
|
|
5
6
|
};
|
|
6
7
|
export {};
|
|
@@ -11,8 +11,8 @@ const cycleBrowserTabs = (puppeteerInstance, concurrency) => {
|
|
|
11
11
|
let i = 0;
|
|
12
12
|
const set = () => {
|
|
13
13
|
interval = setTimeout(() => {
|
|
14
|
-
puppeteerInstance
|
|
15
|
-
.pages()
|
|
14
|
+
Promise.resolve(puppeteerInstance)
|
|
15
|
+
.then((instance) => instance.pages())
|
|
16
16
|
.then((pages) => {
|
|
17
17
|
var _a, _b;
|
|
18
18
|
const currentPage = pages[i % pages.length];
|
|
@@ -13,5 +13,5 @@ declare type GetCompositionsConfig = {
|
|
|
13
13
|
ffmpegExecutable?: FfmpegExecutable;
|
|
14
14
|
port?: number | null;
|
|
15
15
|
};
|
|
16
|
-
export declare const getCompositions: (serveUrlOrWebpackUrl: string, config?: GetCompositionsConfig
|
|
16
|
+
export declare const getCompositions: (serveUrlOrWebpackUrl: string, config?: GetCompositionsConfig) => Promise<TCompMetadata[]>;
|
|
17
17
|
export {};
|
package/dist/get-compositions.js
CHANGED
|
@@ -28,6 +28,7 @@ const innerGetCompositions = async (serveUrl, page, config, proxyPort) => {
|
|
|
28
28
|
initialFrame: 0,
|
|
29
29
|
timeoutInMilliseconds: config === null || config === void 0 ? void 0 : config.timeoutInMilliseconds,
|
|
30
30
|
proxyPort,
|
|
31
|
+
retriesRemaining: 2,
|
|
31
32
|
});
|
|
32
33
|
await (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({
|
|
33
34
|
page,
|
package/dist/index.d.ts
CHANGED
|
@@ -51,7 +51,6 @@ export declare const RenderInternals: {
|
|
|
51
51
|
getLogs: () => string;
|
|
52
52
|
}>;
|
|
53
53
|
getFileExtensionFromCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv", type: "chunk" | "final") => "mp3" | "aac" | "wav" | "mp4" | "mkv" | "mov" | "webm";
|
|
54
|
-
makeAssetsDownloadTmpDir: () => string;
|
|
55
54
|
tmpDir: (str: string) => string;
|
|
56
55
|
deleteDirectory: (directory: string) => Promise<void>;
|
|
57
56
|
isServeUrl: (potentialUrl: string) => boolean;
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,6 @@ const get_extension_of_filename_1 = require("./get-extension-of-filename");
|
|
|
14
14
|
const get_frame_to_render_1 = require("./get-frame-to-render");
|
|
15
15
|
const get_local_browser_executable_1 = require("./get-local-browser-executable");
|
|
16
16
|
const is_serve_url_1 = require("./is-serve-url");
|
|
17
|
-
const make_assets_download_dir_1 = require("./make-assets-download-dir");
|
|
18
17
|
const normalize_serve_url_1 = require("./normalize-serve-url");
|
|
19
18
|
const open_browser_1 = require("./open-browser");
|
|
20
19
|
const parse_browser_error_stack_1 = require("./parse-browser-error-stack");
|
|
@@ -54,7 +53,6 @@ exports.RenderInternals = {
|
|
|
54
53
|
normalizeServeUrl: normalize_serve_url_1.normalizeServeUrl,
|
|
55
54
|
spawnFfmpeg: stitch_frames_to_video_1.spawnFfmpeg,
|
|
56
55
|
getFileExtensionFromCodec: get_extension_from_codec_1.getFileExtensionFromCodec,
|
|
57
|
-
makeAssetsDownloadTmpDir: make_assets_download_dir_1.makeAssetsDownloadTmpDir,
|
|
58
56
|
tmpDir: tmp_dir_1.tmpDir,
|
|
59
57
|
deleteDirectory: delete_directory_1.deleteDirectory,
|
|
60
58
|
isServeUrl: is_serve_url_1.isServeUrl,
|
|
@@ -30,8 +30,8 @@ const mergeAudioTrackUnlimited = async ({ ffmpegExecutable, outName, files, numb
|
|
|
30
30
|
});
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
// FFMPEG
|
|
34
|
-
if (files.length
|
|
33
|
+
// In FFMPEG, the total number of left and right tracks that can be merged at one time is limited to 64
|
|
34
|
+
if (files.length >= 32) {
|
|
35
35
|
const chunked = (0, chunk_1.chunk)(files, 10);
|
|
36
36
|
const tempPath = (0, tmp_dir_1.tmpDir)('remotion-large-audio-mixing');
|
|
37
37
|
const chunkNames = await Promise.all(chunked.map(async (chunkFiles, i) => {
|
|
@@ -35,14 +35,15 @@ const startOffthreadVideoServer = ({ ffmpegExecutable, downloadDir, onDownload,
|
|
|
35
35
|
res.setHeader('access-control-allow-origin', '*');
|
|
36
36
|
res.setHeader('content-type', 'image/jpg');
|
|
37
37
|
const { src, time } = (0, exports.extractUrlAndSourceFromUrl)(req.url);
|
|
38
|
+
const to = (0, download_and_map_assets_to_file_1.getSanitizedFilenameForAssetUrl)({ downloadDir, src });
|
|
38
39
|
(0, download_and_map_assets_to_file_1.startDownloadForSrc)({ src, downloadDir, onDownload }).catch((err) => {
|
|
39
40
|
onError(new Error(`Error while downloading asset: ${err.stack}`));
|
|
40
41
|
});
|
|
41
|
-
(0, download_and_map_assets_to_file_1.waitForAssetToBeDownloaded)(src)
|
|
42
|
-
.then((
|
|
42
|
+
(0, download_and_map_assets_to_file_1.waitForAssetToBeDownloaded)(src, to)
|
|
43
|
+
.then(() => {
|
|
43
44
|
return (0, extract_frame_from_video_1.extractFrameFromVideo)({
|
|
44
45
|
time,
|
|
45
|
-
src:
|
|
46
|
+
src: to,
|
|
46
47
|
ffmpegExecutable,
|
|
47
48
|
});
|
|
48
49
|
})
|
package/dist/open-browser.d.ts
CHANGED
|
@@ -10,9 +10,9 @@ export declare type ChromiumOptions = {
|
|
|
10
10
|
};
|
|
11
11
|
export declare const killAllBrowsers: () => Promise<void>;
|
|
12
12
|
export declare const openBrowser: (browser: Browser, options?: {
|
|
13
|
-
shouldDumpIo?: boolean
|
|
14
|
-
browserExecutable?: string | null
|
|
15
|
-
chromiumOptions?: ChromiumOptions
|
|
16
|
-
forceDeviceScaleFactor?: number
|
|
17
|
-
}
|
|
13
|
+
shouldDumpIo?: boolean;
|
|
14
|
+
browserExecutable?: string | null;
|
|
15
|
+
chromiumOptions?: ChromiumOptions;
|
|
16
|
+
forceDeviceScaleFactor?: number;
|
|
17
|
+
}) => Promise<puppeteer.Browser>;
|
|
18
18
|
export {};
|
package/dist/prespawn-ffmpeg.js
CHANGED
|
@@ -73,6 +73,9 @@ const prespawnFfmpeg = async (options) => {
|
|
|
73
73
|
}
|
|
74
74
|
const ffmpegString = ffmpegArgs.flat(2).filter(Boolean);
|
|
75
75
|
const task = (0, execa_1.default)((_f = options.ffmpegExecutable) !== null && _f !== void 0 ? _f : 'ffmpeg', ffmpegString);
|
|
76
|
+
const waitForSpawn = new Promise((resolve) => {
|
|
77
|
+
task.on('spawn', () => resolve());
|
|
78
|
+
});
|
|
76
79
|
let ffmpegOutput = '';
|
|
77
80
|
(_g = task.stderr) === null || _g === void 0 ? void 0 : _g.on('data', (data) => {
|
|
78
81
|
const str = data.toString();
|
|
@@ -84,6 +87,6 @@ const prespawnFfmpeg = async (options) => {
|
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
89
|
});
|
|
87
|
-
return { task, getLogs: () => ffmpegOutput };
|
|
90
|
+
return { task, getLogs: () => ffmpegOutput, waitForSpawn };
|
|
88
91
|
};
|
|
89
92
|
exports.prespawnFfmpeg = prespawnFfmpeg;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
package/dist/render-frames.d.ts
CHANGED
|
@@ -36,5 +36,8 @@ declare type RenderFramesOptions = {
|
|
|
36
36
|
ffmpegExecutable?: FfmpegExecutable;
|
|
37
37
|
port?: number | null;
|
|
38
38
|
} & ConfigOrComposition & ServeUrlOrWebpackBundle;
|
|
39
|
-
|
|
39
|
+
declare type ReturnTypeWithCancel = Promise<RenderFramesOutput> & {
|
|
40
|
+
cancel: () => void;
|
|
41
|
+
};
|
|
42
|
+
export declare const renderFrames: (options: RenderFramesOptions) => ReturnTypeWithCancel;
|
|
40
43
|
export {};
|
package/dist/render-frames.js
CHANGED
|
@@ -33,7 +33,12 @@ const getComposition = (others) => {
|
|
|
33
33
|
}
|
|
34
34
|
return undefined;
|
|
35
35
|
};
|
|
36
|
-
const
|
|
36
|
+
const getPool = async (pages) => {
|
|
37
|
+
const puppeteerPages = await Promise.all(pages);
|
|
38
|
+
const pool = new pool_1.Pool(puppeteerPages);
|
|
39
|
+
return pool;
|
|
40
|
+
};
|
|
41
|
+
const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, quality, imageFormat = image_format_1.DEFAULT_IMAGE_FORMAT, frameRange, puppeteerInstance, onError, envVariables, onBrowserLog, onFrameBuffer, onDownload, pagesArray, serveUrl, composition, timeoutInMilliseconds, scale, actualParallelism, downloadDir, proxyPort, }) => {
|
|
37
42
|
if (!puppeteerInstance) {
|
|
38
43
|
throw new Error('weird');
|
|
39
44
|
}
|
|
@@ -77,6 +82,7 @@ const innerRenderFrames = async ({ onFrameUpdate, outputDir, onStart, inputProps
|
|
|
77
82
|
initialFrame,
|
|
78
83
|
timeoutInMilliseconds,
|
|
79
84
|
proxyPort,
|
|
85
|
+
retriesRemaining: 2,
|
|
80
86
|
});
|
|
81
87
|
await (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({
|
|
82
88
|
pageFunction: (id) => {
|
|
@@ -92,23 +98,27 @@ const innerRenderFrames = async ({ onFrameUpdate, outputDir, onStart, inputProps
|
|
|
92
98
|
page.off('console', logCallback);
|
|
93
99
|
return page;
|
|
94
100
|
});
|
|
95
|
-
const puppeteerPages = await Promise.all(pages);
|
|
96
|
-
const pool = new pool_1.Pool(puppeteerPages);
|
|
97
101
|
const [firstFrameIndex, lastFrameIndex] = realFrameRange;
|
|
98
102
|
// Substract one because 100 frames will be 00-99
|
|
99
103
|
// --> 2 digits
|
|
100
104
|
const filePadLength = String(lastFrameIndex).length;
|
|
101
105
|
let framesRendered = 0;
|
|
106
|
+
const poolPromise = getPool(pages);
|
|
102
107
|
onStart({
|
|
103
108
|
frameCount,
|
|
104
109
|
});
|
|
105
110
|
const assets = new Array(frameCount).fill(undefined);
|
|
106
|
-
|
|
111
|
+
let stopped = false;
|
|
112
|
+
const progress = Promise.all(new Array(frameCount)
|
|
107
113
|
.fill(Boolean)
|
|
108
|
-
.map((
|
|
114
|
+
.map((_x, i) => i)
|
|
109
115
|
.map(async (index) => {
|
|
110
116
|
const frame = realFrameRange[0] + index;
|
|
117
|
+
const pool = await poolPromise;
|
|
111
118
|
const freePage = await pool.acquire();
|
|
119
|
+
if (stopped) {
|
|
120
|
+
throw new Error('Render was stopped');
|
|
121
|
+
}
|
|
112
122
|
const paddedIndex = String(frame).padStart(filePadLength, '0');
|
|
113
123
|
const errorCallbackOnFrame = (err) => {
|
|
114
124
|
onError(err);
|
|
@@ -175,18 +185,29 @@ const innerRenderFrames = async ({ onFrameUpdate, outputDir, onStart, inputProps
|
|
|
175
185
|
freePage.off('error', errorCallbackOnFrame);
|
|
176
186
|
return compressedAssets;
|
|
177
187
|
}));
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
188
|
+
const prom = Object.assign(new Promise((res, rej) => {
|
|
189
|
+
progress
|
|
190
|
+
.then(() => {
|
|
191
|
+
const returnValue = {
|
|
192
|
+
assetsInfo: {
|
|
193
|
+
assets,
|
|
194
|
+
downloadDir,
|
|
195
|
+
firstFrameIndex,
|
|
196
|
+
imageSequenceName: `element-%0${filePadLength}d.${imageFormat}`,
|
|
197
|
+
},
|
|
198
|
+
frameCount,
|
|
199
|
+
};
|
|
200
|
+
res(returnValue);
|
|
201
|
+
})
|
|
202
|
+
.catch((err) => rej(err));
|
|
203
|
+
}), {
|
|
204
|
+
cancel: () => {
|
|
205
|
+
stopped = true;
|
|
184
206
|
},
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return returnValue;
|
|
207
|
+
});
|
|
208
|
+
return prom;
|
|
188
209
|
};
|
|
189
|
-
const renderFrames =
|
|
210
|
+
const renderFrames = (options) => {
|
|
190
211
|
var _a, _b, _c, _d;
|
|
191
212
|
const composition = getComposition(options);
|
|
192
213
|
if (!composition) {
|
|
@@ -202,34 +223,38 @@ const renderFrames = async (options) => {
|
|
|
202
223
|
const selectedServeUrl = (0, legacy_webpack_config_1.getServeUrlWithFallback)(options);
|
|
203
224
|
remotion_1.Internals.validateQuality(options.quality);
|
|
204
225
|
(0, validate_scale_1.validateScale)(options.scale);
|
|
205
|
-
const browserInstance = (_a = options.puppeteerInstance) !== null && _a !== void 0 ? _a : (
|
|
226
|
+
const browserInstance = (_a = options.puppeteerInstance) !== null && _a !== void 0 ? _a : (0, open_browser_1.openBrowser)(remotion_1.Internals.DEFAULT_BROWSER, {
|
|
206
227
|
shouldDumpIo: options.dumpBrowserLogs,
|
|
207
228
|
browserExecutable: options.browserExecutable,
|
|
208
229
|
chromiumOptions: options.chromiumOptions,
|
|
209
230
|
forceDeviceScaleFactor: (_b = options.scale) !== null && _b !== void 0 ? _b : 1,
|
|
210
|
-
})
|
|
231
|
+
});
|
|
211
232
|
const downloadDir = (0, make_assets_download_dir_1.makeAssetsDownloadTmpDir)();
|
|
212
233
|
const onDownload = (_c = options.onDownload) !== null && _c !== void 0 ? _c : (() => () => undefined);
|
|
213
234
|
const actualParallelism = (0, get_concurrency_1.getActualConcurrency)((_d = options.parallelism) !== null && _d !== void 0 ? _d : null);
|
|
214
235
|
const { stopCycling } = (0, cycle_browser_tabs_1.cycleBrowserTabs)(browserInstance, actualParallelism);
|
|
215
236
|
const openedPages = [];
|
|
216
|
-
|
|
237
|
+
let cancel = () => undefined;
|
|
238
|
+
const prom = new Promise((resolve, reject) => {
|
|
217
239
|
var _a, _b;
|
|
218
240
|
let cleanup = null;
|
|
219
241
|
const onError = (err) => reject(err);
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
242
|
+
Promise.all([
|
|
243
|
+
(0, prepare_server_1.prepareServer)({
|
|
244
|
+
webpackConfigOrServeUrl: selectedServeUrl,
|
|
245
|
+
downloadDir,
|
|
246
|
+
onDownload,
|
|
247
|
+
onError,
|
|
248
|
+
ffmpegExecutable: (_a = options.ffmpegExecutable) !== null && _a !== void 0 ? _a : null,
|
|
249
|
+
port: (_b = options.port) !== null && _b !== void 0 ? _b : null,
|
|
250
|
+
}),
|
|
251
|
+
browserInstance,
|
|
252
|
+
])
|
|
253
|
+
.then(([{ serveUrl, closeServer, offthreadPort }, puppeteerInstance]) => {
|
|
229
254
|
cleanup = closeServer;
|
|
230
|
-
|
|
255
|
+
const renderFramesProm = innerRenderFrames({
|
|
231
256
|
...options,
|
|
232
|
-
puppeteerInstance
|
|
257
|
+
puppeteerInstance,
|
|
233
258
|
onError,
|
|
234
259
|
pagesArray: openedPages,
|
|
235
260
|
serveUrl,
|
|
@@ -239,6 +264,10 @@ const renderFrames = async (options) => {
|
|
|
239
264
|
downloadDir,
|
|
240
265
|
proxyPort: offthreadPort,
|
|
241
266
|
});
|
|
267
|
+
cancel = () => {
|
|
268
|
+
renderFramesProm.cancel();
|
|
269
|
+
};
|
|
270
|
+
return renderFramesProm;
|
|
242
271
|
})
|
|
243
272
|
.then((res) => resolve(res))
|
|
244
273
|
.catch((err) => reject(err))
|
|
@@ -252,7 +281,11 @@ const renderFrames = async (options) => {
|
|
|
252
281
|
});
|
|
253
282
|
}
|
|
254
283
|
else {
|
|
255
|
-
|
|
284
|
+
Promise.resolve(browserInstance)
|
|
285
|
+
.then((puppeteerInstance) => {
|
|
286
|
+
return puppeteerInstance.close();
|
|
287
|
+
})
|
|
288
|
+
.catch((err) => {
|
|
256
289
|
console.log('Unable to close browser', err);
|
|
257
290
|
});
|
|
258
291
|
}
|
|
@@ -260,5 +293,11 @@ const renderFrames = async (options) => {
|
|
|
260
293
|
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
|
|
261
294
|
});
|
|
262
295
|
});
|
|
296
|
+
const returnType = Object.assign(prom, {
|
|
297
|
+
cancel: () => {
|
|
298
|
+
cancel();
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
return returnType;
|
|
263
302
|
};
|
|
264
303
|
exports.renderFrames = renderFrames;
|
package/dist/render-media.d.ts
CHANGED
|
@@ -40,4 +40,8 @@ export declare type RenderMediaOptions = {
|
|
|
40
40
|
port?: number | null;
|
|
41
41
|
browserExecutable?: BrowserExecutable;
|
|
42
42
|
} & ServeUrlOrWebpackBundle;
|
|
43
|
-
|
|
43
|
+
declare type RenderMediaReturnType = Promise<void> & {
|
|
44
|
+
cancel: () => void;
|
|
45
|
+
};
|
|
46
|
+
export declare const renderMedia: (options: RenderMediaOptions) => RenderMediaReturnType;
|
|
47
|
+
export {};
|
package/dist/render-media.js
CHANGED
|
@@ -23,7 +23,22 @@ const tmp_dir_1 = require("./tmp-dir");
|
|
|
23
23
|
const validate_even_dimensions_with_codec_1 = require("./validate-even-dimensions-with-codec");
|
|
24
24
|
const validate_output_filename_1 = require("./validate-output-filename");
|
|
25
25
|
const validate_scale_1 = require("./validate-scale");
|
|
26
|
-
const renderMedia =
|
|
26
|
+
const renderMedia = (options) => {
|
|
27
|
+
let resolve = () => undefined;
|
|
28
|
+
let reject = () => undefined;
|
|
29
|
+
const rejectIfCancel = new Promise((res, rej) => {
|
|
30
|
+
resolve = res;
|
|
31
|
+
reject = rej;
|
|
32
|
+
});
|
|
33
|
+
const prom = innerRenderMedia({ ...options, rejectIfCancel }).then(() => {
|
|
34
|
+
resolve();
|
|
35
|
+
});
|
|
36
|
+
return Object.assign(prom, {
|
|
37
|
+
cancel: () => reject(new Error('Render got cancelled')),
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
exports.renderMedia = renderMedia;
|
|
41
|
+
const innerRenderMedia = async ({ parallelism, proResProfile, crf, composition, imageFormat, ffmpegExecutable, inputProps, pixelFormat, codec, envVariables, quality, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, rejectIfCancel, ...options }) => {
|
|
27
42
|
var _a;
|
|
28
43
|
remotion_1.Internals.validateQuality(quality);
|
|
29
44
|
if (typeof crf !== 'undefined' && crf !== null) {
|
|
@@ -39,6 +54,14 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
|
|
|
39
54
|
let renderedFrames = 0;
|
|
40
55
|
let renderedDoneIn = null;
|
|
41
56
|
let encodedDoneIn = null;
|
|
57
|
+
let cancelRenderFrames = () => undefined;
|
|
58
|
+
rejectIfCancel
|
|
59
|
+
.then(() => undefined)
|
|
60
|
+
.catch((err) => {
|
|
61
|
+
preStitcher === null || preStitcher === void 0 ? void 0 : preStitcher.task.kill();
|
|
62
|
+
cancelRenderFrames();
|
|
63
|
+
throw err;
|
|
64
|
+
});
|
|
42
65
|
const renderStart = Date.now();
|
|
43
66
|
const tmpdir = (0, tmp_dir_1.tmpDir)('pre-encode');
|
|
44
67
|
const parallelEncoding = (0, can_use_parallel_encoding_1.canUseParallelEncoding)(codec);
|
|
@@ -87,7 +110,7 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
|
|
|
87
110
|
}
|
|
88
111
|
const realFrameRange = (0, get_frame_to_render_1.getRealFrameRange)(composition.durationInFrames, frameRange !== null && frameRange !== void 0 ? frameRange : null);
|
|
89
112
|
const { waitForRightTimeOfFrameToBeInserted, setFrameToStitch, waitForFinish, } = (0, ensure_frames_in_order_1.ensureFramesInOrder)(realFrameRange);
|
|
90
|
-
const
|
|
113
|
+
const renderFramesProc = (0, render_frames_1.renderFrames)({
|
|
91
114
|
config: composition,
|
|
92
115
|
onFrameUpdate: (frame) => {
|
|
93
116
|
renderedFrames = frame;
|
|
@@ -125,6 +148,10 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
|
|
|
125
148
|
browserExecutable,
|
|
126
149
|
port,
|
|
127
150
|
});
|
|
151
|
+
cancelRenderFrames = () => {
|
|
152
|
+
renderFramesProc.cancel();
|
|
153
|
+
};
|
|
154
|
+
const { assetsInfo } = await renderFramesProc;
|
|
128
155
|
if (stitcherFfmpeg) {
|
|
129
156
|
await waitForFinish();
|
|
130
157
|
(_a = stitcherFfmpeg === null || stitcherFfmpeg === void 0 ? void 0 : stitcherFfmpeg.stdin) === null || _a === void 0 ? void 0 : _a.end();
|
|
@@ -168,6 +195,26 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
|
|
|
168
195
|
encodedDoneIn = Date.now() - stitchStart;
|
|
169
196
|
callUpdate();
|
|
170
197
|
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
/**
|
|
200
|
+
* When an error is thrown in renderFrames(...) (e.g., when delayRender() is used incorrectly), fs.unlinkSync(...) throws an error that the file is locked because ffmpeg is still running, and renderMedia returns it.
|
|
201
|
+
* Therefore we first kill the FFMPEG process before deleting the file
|
|
202
|
+
*/
|
|
203
|
+
cancelRenderFrames();
|
|
204
|
+
if (stitcherFfmpeg !== undefined && stitcherFfmpeg.exitCode === null) {
|
|
205
|
+
const promise = new Promise((resolve) => {
|
|
206
|
+
setTimeout(() => {
|
|
207
|
+
resolve();
|
|
208
|
+
}, 2000);
|
|
209
|
+
stitcherFfmpeg.on('close', resolve);
|
|
210
|
+
});
|
|
211
|
+
// Can only kill the process once it has spawned, otherwise getting EPIPE error in Node.JS
|
|
212
|
+
await (preStitcher === null || preStitcher === void 0 ? void 0 : preStitcher.waitForSpawn);
|
|
213
|
+
stitcherFfmpeg.kill();
|
|
214
|
+
await promise;
|
|
215
|
+
}
|
|
216
|
+
throw err;
|
|
217
|
+
}
|
|
171
218
|
finally {
|
|
172
219
|
if (preEncodedFileLocation !== null &&
|
|
173
220
|
fs_1.default.existsSync(preEncodedFileLocation)) {
|
|
@@ -175,4 +222,3 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
|
|
|
175
222
|
}
|
|
176
223
|
}
|
|
177
224
|
};
|
|
178
|
-
exports.renderMedia = renderMedia;
|
package/dist/render-still.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -105,6 +109,7 @@ const innerRenderStill = async ({ composition, quality, imageFormat = 'png', ser
|
|
|
105
109
|
initialFrame: frame,
|
|
106
110
|
timeoutInMilliseconds,
|
|
107
111
|
proxyPort,
|
|
112
|
+
retriesRemaining: 2,
|
|
108
113
|
});
|
|
109
114
|
await (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({
|
|
110
115
|
pageFunction: (id) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Page } from 'puppeteer-core';
|
|
2
|
-
export declare const setPropsAndEnv: ({ inputProps, envVariables, page, serveUrl, initialFrame, timeoutInMilliseconds, proxyPort, }: {
|
|
2
|
+
export declare const setPropsAndEnv: ({ inputProps, envVariables, page, serveUrl, initialFrame, timeoutInMilliseconds, proxyPort, retriesRemaining, }: {
|
|
3
3
|
inputProps: unknown;
|
|
4
4
|
envVariables: Record<string, string> | undefined;
|
|
5
5
|
page: Page;
|
|
@@ -7,4 +7,5 @@ export declare const setPropsAndEnv: ({ inputProps, envVariables, page, serveUrl
|
|
|
7
7
|
initialFrame: number;
|
|
8
8
|
timeoutInMilliseconds: number | undefined;
|
|
9
9
|
proxyPort: number;
|
|
10
|
+
retriesRemaining: number;
|
|
10
11
|
}) => Promise<void>;
|
|
@@ -5,7 +5,7 @@ const remotion_1 = require("remotion");
|
|
|
5
5
|
const normalize_serve_url_1 = require("./normalize-serve-url");
|
|
6
6
|
const puppeteer_evaluate_1 = require("./puppeteer-evaluate");
|
|
7
7
|
const validate_puppeteer_timeout_1 = require("./validate-puppeteer-timeout");
|
|
8
|
-
const setPropsAndEnv = async ({ inputProps, envVariables, page, serveUrl, initialFrame, timeoutInMilliseconds, proxyPort, }) => {
|
|
8
|
+
const setPropsAndEnv = async ({ inputProps, envVariables, page, serveUrl, initialFrame, timeoutInMilliseconds, proxyPort, retriesRemaining, }) => {
|
|
9
9
|
(0, validate_puppeteer_timeout_1.validatePuppeteerTimeout)(timeoutInMilliseconds);
|
|
10
10
|
const actualTimeout = timeoutInMilliseconds !== null && timeoutInMilliseconds !== void 0 ? timeoutInMilliseconds : remotion_1.Internals.DEFAULT_PUPPETEER_TIMEOUT;
|
|
11
11
|
page.setDefaultTimeout(actualTimeout);
|
|
@@ -32,6 +32,25 @@ const setPropsAndEnv = async ({ inputProps, envVariables, page, serveUrl, initia
|
|
|
32
32
|
}, [proxyPort]);
|
|
33
33
|
const pageRes = await page.goto(urlToVisit);
|
|
34
34
|
const status = pageRes.status();
|
|
35
|
+
// S3 in rare occasions returns a 500 or 503 error code for GET operations.
|
|
36
|
+
// Usually it is fixed by retrying.
|
|
37
|
+
if (status >= 500 && status <= 504 && retriesRemaining > 0) {
|
|
38
|
+
await new Promise((resolve) => {
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
resolve();
|
|
41
|
+
}, 2000);
|
|
42
|
+
});
|
|
43
|
+
return (0, exports.setPropsAndEnv)({
|
|
44
|
+
envVariables,
|
|
45
|
+
initialFrame,
|
|
46
|
+
inputProps,
|
|
47
|
+
page,
|
|
48
|
+
proxyPort,
|
|
49
|
+
retriesRemaining: retriesRemaining - 1,
|
|
50
|
+
serveUrl,
|
|
51
|
+
timeoutInMilliseconds,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
35
54
|
if (status !== 200 &&
|
|
36
55
|
status !== 301 &&
|
|
37
56
|
status !== 302 &&
|
package/dist/tmp-dir.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/renderer",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-spawn.14+243a2f006",
|
|
4
4
|
"description": "Renderer for Remotion",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"execa": "5.1.1",
|
|
24
24
|
"puppeteer-core": "13.5.1",
|
|
25
|
-
"remotion": "4.0.0-
|
|
25
|
+
"remotion": "4.0.0-spawn.14+243a2f006",
|
|
26
26
|
"serve-handler": "6.1.3",
|
|
27
27
|
"source-map": "^0.8.0-beta.0"
|
|
28
28
|
},
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"react": "18.0.0",
|
|
47
47
|
"react-dom": "18.0.0",
|
|
48
48
|
"ts-jest": "^27.0.5",
|
|
49
|
-
"typescript": "^4.
|
|
49
|
+
"typescript": "^4.7.0"
|
|
50
50
|
},
|
|
51
51
|
"keywords": [
|
|
52
52
|
"remotion",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "243a2f0067d75e193a6a45f491987be53208f3e0"
|
|
63
63
|
}
|