@remotion/renderer 4.0.0-alpha.217 → 4.0.0-alpha10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -37
- package/dist/assets/download-and-map-assets-to-file.js +6 -6
- package/dist/assets/download-file.d.ts +3 -2
- package/dist/assets/download-file.js +18 -3
- package/dist/assets/download-map.d.ts +0 -26
- package/dist/assets/download-map.js +7 -12
- package/dist/assets/get-video-stream-duration.d.ts +5 -2
- package/dist/assets/get-video-stream-duration.js +12 -6
- package/dist/assets/read-file.d.ts +1 -1
- package/dist/assets/read-file.js +2 -2
- package/dist/assets/sanitize-filepath.js +2 -2
- package/dist/browser/Browser.d.ts +4 -4
- package/dist/browser/Browser.js +38 -38
- package/dist/browser/BrowserFetcher.d.ts +15 -63
- package/dist/browser/BrowserFetcher.js +138 -226
- package/dist/browser/BrowserPage.d.ts +4 -4
- package/dist/browser/BrowserRunner.d.ts +1 -1
- package/dist/browser/BrowserRunner.js +9 -22
- package/dist/browser/DOMWorld.d.ts +3 -3
- package/dist/browser/LaunchOptions.d.ts +1 -2
- package/dist/browser/Launcher.d.ts +3 -3
- package/dist/browser/Launcher.js +10 -23
- package/dist/browser/NodeWebSocketTransport.js +4 -4
- package/dist/browser/PuppeteerNode.d.ts +2 -5
- package/dist/browser/PuppeteerNode.js +0 -5
- package/dist/browser/Target.d.ts +2 -2
- package/dist/browser/create-browser-fetcher.js +34 -48
- package/dist/browser/get-download-destination.js +8 -8
- package/dist/browser/util.d.ts +2 -2
- package/dist/call-ffmpeg.d.ts +4 -7
- package/dist/call-ffmpeg.js +24 -16
- package/dist/chalk/index.d.ts +54 -0
- package/dist/chalk/index.js +135 -0
- package/dist/chalk/is-color-supported.d.ts +1 -0
- package/dist/chalk/is-color-supported.js +37 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +1 -0
- package/dist/codec-supports-media.d.ts +1 -0
- package/dist/codec-supports-media.js +20 -5
- package/dist/combine-videos.js +6 -6
- package/dist/compositor/compose.d.ts +6 -2
- package/dist/compositor/compose.js +43 -20
- package/dist/compositor/compositor.d.ts +4 -8
- package/dist/compositor/compositor.js +67 -53
- package/dist/compositor/get-executable-path.js +3 -0
- package/dist/compositor/payloads.d.ts +34 -7
- package/dist/crf.js +8 -2
- package/dist/delete-directory.js +3 -3
- package/dist/does-have-m2-bug.js +2 -2
- package/dist/ensure-output-directory.js +5 -5
- package/dist/ensure-presentation-timestamp.d.ts +9 -2
- package/dist/ensure-presentation-timestamp.js +13 -5
- package/dist/extract-frame-from-video.d.ts +3 -1
- package/dist/extract-frame-from-video.js +29 -7
- package/dist/ffmpeg-filter-file.js +7 -7
- package/dist/find-closest-package-json.js +6 -6
- package/dist/get-browser-instance.d.ts +2 -2
- package/dist/get-can-extract-frames-fast.d.ts +4 -1
- package/dist/get-can-extract-frames-fast.js +12 -1
- package/dist/get-compositions.d.ts +8 -3
- package/dist/get-compositions.js +6 -2
- package/dist/get-concurrency.js +3 -3
- package/dist/get-extension-of-filename.js +2 -2
- package/dist/get-frame-of-video-slow.d.ts +8 -3
- package/dist/get-frame-of-video-slow.js +11 -3
- package/dist/get-local-browser-executable.js +6 -15
- package/dist/get-video-info.d.ts +5 -2
- package/dist/get-video-info.js +12 -6
- package/dist/get-video-threads-flag.js +3 -3
- package/dist/index.d.ts +92 -16
- package/dist/index.js +15 -6
- package/dist/last-frame-from-video-cache.d.ts +4 -1
- package/dist/last-frame-from-video-cache.js +1 -0
- package/dist/logger.d.ts +22 -0
- package/dist/logger.js +61 -0
- package/dist/merge-audio-track.js +2 -2
- package/dist/mime-types.js +2 -2
- package/dist/offthread-video-server.d.ts +12 -6
- package/dist/offthread-video-server.js +66 -56
- package/dist/open-browser.d.ts +3 -3
- package/dist/open-browser.js +1 -1
- package/dist/options/jpeg-quality.js +1 -1
- package/dist/options/video-codec.js +1 -1
- package/dist/prepare-server.d.ts +6 -1
- package/dist/prepare-server.js +15 -7
- package/dist/prespawn-ffmpeg.d.ts +1 -0
- package/dist/prespawn-ffmpeg.js +37 -14
- package/dist/prestitcher-memory-usage.js +2 -2
- package/dist/puppeteer-evaluate.js +2 -2
- package/dist/puppeteer-screenshot.js +1 -1
- package/dist/render-frames.d.ts +9 -4
- package/dist/render-frames.js +28 -12
- package/dist/render-media.d.ts +7 -4
- package/dist/render-media.js +49 -26
- package/dist/render-still.d.ts +10 -3
- package/dist/render-still.js +26 -9
- package/dist/replace-browser.d.ts +4 -4
- package/dist/resolve-asset-src.js +2 -2
- package/dist/screenshot-task.js +2 -2
- package/dist/select-composition.d.ts +33 -0
- package/dist/select-composition.js +119 -0
- package/dist/serve-handler/index.d.ts +1 -1
- package/dist/serve-handler/index.js +15 -15
- package/dist/serve-handler/is-path-inside.js +3 -3
- package/dist/serve-static.d.ts +5 -0
- package/dist/serve-static.js +25 -20
- package/dist/set-props-and-env.d.ts +5 -3
- package/dist/set-props-and-env.js +13 -3
- package/dist/stitch-frames-to-video.d.ts +1 -0
- package/dist/stitch-frames-to-video.js +76 -53
- package/dist/take-frame-and-compose.d.ts +3 -1
- package/dist/take-frame-and-compose.js +8 -7
- package/dist/tmp-dir.js +7 -7
- package/dist/try-to-extract-frame-of-video-fast.d.ts +4 -2
- package/dist/try-to-extract-frame-of-video-fast.js +7 -3
- package/install-toolchain.mjs +3 -9
- package/package.json +70 -71
- package/types/ws/index.d.ts +5 -5
- package/ffmpeg/SOURCE.md +0 -1
- package/ffmpeg/linux-arm-musl.gz +0 -0
- package/ffmpeg/linux-arm.gz +0 -0
- package/ffmpeg/linux-x64-musl.gz +0 -0
- package/ffmpeg/linux-x64.gz +0 -0
- package/ffmpeg/macos-arm.gz +0 -0
- package/ffmpeg/macos-x64.gz +0 -0
- package/ffmpeg/windows.gz +0 -0
package/dist/combine-videos.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Combine multiple video chunks, useful for decentralized rendering
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.combineVideos = void 0;
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
7
|
const audio_codec_1 = require("./audio-codec");
|
|
8
8
|
const call_ffmpeg_1 = require("./call-ffmpeg");
|
|
9
9
|
const is_audio_codec_1 = require("./is-audio-codec");
|
|
@@ -13,8 +13,8 @@ const combineVideos = async (options) => {
|
|
|
13
13
|
var _a;
|
|
14
14
|
const { files, filelistDir, output, onProgress, numberOfFrames, codec, fps, numberOfGifLoops, audioCodec, } = options;
|
|
15
15
|
const fileList = files.map((p) => `file '${p}'`).join('\n');
|
|
16
|
-
const fileListTxt = (0,
|
|
17
|
-
(0,
|
|
16
|
+
const fileListTxt = (0, node_path_1.join)(filelistDir, 'files.txt');
|
|
17
|
+
(0, node_fs_1.writeFileSync)(fileListTxt, fileList);
|
|
18
18
|
const resolvedAudioCodec = audioCodec !== null && audioCodec !== void 0 ? audioCodec : (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: false });
|
|
19
19
|
try {
|
|
20
20
|
const task = (0, call_ffmpeg_1.callFf)('ffmpeg', [
|
|
@@ -56,10 +56,10 @@ const combineVideos = async (options) => {
|
|
|
56
56
|
});
|
|
57
57
|
await task;
|
|
58
58
|
onProgress(numberOfFrames);
|
|
59
|
-
(0,
|
|
59
|
+
(0, node_fs_1.rmSync)(filelistDir, { recursive: true });
|
|
60
60
|
}
|
|
61
61
|
catch (err) {
|
|
62
|
-
(0,
|
|
62
|
+
(0, node_fs_1.rmSync)(filelistDir, { recursive: true });
|
|
63
63
|
throw err;
|
|
64
64
|
}
|
|
65
65
|
};
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import type { DownloadMap } from '../assets/download-map';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Compositor } from './compositor';
|
|
3
|
+
import type { CompositorCommand, CompositorCommandSerialized, CompositorImageFormat, Layer } from './payloads';
|
|
3
4
|
declare type CompositorInput = {
|
|
4
5
|
height: number;
|
|
5
6
|
width: number;
|
|
6
7
|
layers: Layer[];
|
|
7
8
|
imageFormat: CompositorImageFormat;
|
|
8
9
|
};
|
|
9
|
-
export declare const
|
|
10
|
+
export declare const serializeCommand: <Type extends keyof CompositorCommand>(command: Type, params: CompositorCommand[Type]) => CompositorCommandSerialized<Type>;
|
|
11
|
+
export declare const compose: ({ height, width, layers, output, downloadMap, imageFormat, compositor, }: CompositorInput & {
|
|
10
12
|
downloadMap: DownloadMap;
|
|
11
13
|
output: string;
|
|
14
|
+
compositor: Compositor;
|
|
12
15
|
}) => Promise<void>;
|
|
16
|
+
export declare const callCompositor: (payload: string) => Promise<void>;
|
|
13
17
|
export {};
|
|
@@ -1,33 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.compose = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
3
|
+
exports.callCompositor = exports.compose = exports.serializeCommand = void 0;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
const node_fs_1 = require("node:fs");
|
|
7
|
+
const promises_1 = require("node:fs/promises");
|
|
7
8
|
const call_ffmpeg_1 = require("../call-ffmpeg");
|
|
8
9
|
const get_executable_path_1 = require("./get-executable-path");
|
|
10
|
+
const make_nonce_1 = require("./make-nonce");
|
|
9
11
|
const getCompositorHash = ({ ...input }) => {
|
|
10
|
-
return (0,
|
|
12
|
+
return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(input)).digest('base64');
|
|
11
13
|
};
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
+
const serializeCommand = (command, params) => {
|
|
15
|
+
return {
|
|
16
|
+
nonce: (0, make_nonce_1.makeNonce)(),
|
|
17
|
+
payload: {
|
|
18
|
+
type: command,
|
|
19
|
+
params,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
exports.serializeCommand = serializeCommand;
|
|
24
|
+
const compose = async ({ height, width, layers, output, downloadMap, imageFormat, compositor, }) => {
|
|
14
25
|
const hash = getCompositorHash({ height, width, layers, imageFormat });
|
|
15
26
|
if (downloadMap.compositorCache[hash]) {
|
|
16
27
|
await (0, promises_1.copyFile)(downloadMap.compositorCache[hash], output);
|
|
17
28
|
return;
|
|
18
29
|
}
|
|
19
|
-
|
|
20
|
-
v: 1,
|
|
30
|
+
await compositor.executeCommand('Compose', {
|
|
21
31
|
height,
|
|
22
32
|
width,
|
|
23
33
|
layers,
|
|
24
34
|
output,
|
|
25
35
|
output_format: imageFormat,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
});
|
|
37
|
+
downloadMap.compositorCache[hash] = output;
|
|
38
|
+
};
|
|
39
|
+
exports.compose = compose;
|
|
40
|
+
const callCompositor = (payload) => {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const execPath = (0, get_executable_path_1.getExecutablePath)('compositor');
|
|
43
|
+
if (!process.env.READ_ONLY_FS) {
|
|
44
|
+
(0, node_fs_1.chmodSync)(execPath, 0o755);
|
|
45
|
+
}
|
|
46
|
+
const child = (0, node_child_process_1.spawn)(execPath, [payload], (0, call_ffmpeg_1.dynamicLibraryPathOptions)());
|
|
31
47
|
const stderrChunks = [];
|
|
32
48
|
child.stderr.on('data', (d) => stderrChunks.push(d));
|
|
33
49
|
child.on('close', (code) => {
|
|
@@ -36,13 +52,20 @@ const compose = async ({ height, width, layers, output, downloadMap, imageFormat
|
|
|
36
52
|
}
|
|
37
53
|
else {
|
|
38
54
|
const message = Buffer.concat(stderrChunks).toString('utf-8');
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
try {
|
|
56
|
+
// Try to see if the error is a JSON
|
|
57
|
+
const parsed = JSON.parse(message);
|
|
58
|
+
const msg = `Compositor error: ${parsed.error}`;
|
|
59
|
+
const err = new Error(`${msg}\n${parsed.backtrace}`);
|
|
60
|
+
reject(err);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
reject(new Error(`Compositor panicked: ${message}`));
|
|
64
|
+
}
|
|
43
65
|
}
|
|
44
66
|
});
|
|
67
|
+
child.stdin.write(payload);
|
|
68
|
+
child.stdin.end();
|
|
45
69
|
});
|
|
46
|
-
downloadMap.compositorCache[hash] = output;
|
|
47
70
|
};
|
|
48
|
-
exports.
|
|
71
|
+
exports.callCompositor = callCompositor;
|
|
@@ -4,12 +4,8 @@ export declare type Compositor = {
|
|
|
4
4
|
finishCommands: () => void;
|
|
5
5
|
executeCommand: <T extends keyof CompositorCommand>(type: T, payload: CompositorCommand[T]) => Promise<Buffer>;
|
|
6
6
|
waitForDone: () => Promise<void>;
|
|
7
|
+
pid: number | null;
|
|
7
8
|
};
|
|
8
|
-
export declare const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
renderId: string;
|
|
12
|
-
}) => Compositor;
|
|
13
|
-
export declare const releaseCompositorWithId: (renderId: string) => void;
|
|
14
|
-
export declare const waitForCompositorWithIdToQuit: (renderId: string) => Promise<void>;
|
|
15
|
-
export declare const startCompositor: <T extends keyof CompositorCommand>(type: T, payload: CompositorCommand[T]) => Compositor;
|
|
9
|
+
export declare const getIdealMaximumFrameCacheItems: () => number;
|
|
10
|
+
export declare const startLongRunningCompositor: (maximumFrameCacheItems: number, verbose: boolean, indent: boolean) => Compositor;
|
|
11
|
+
export declare const startCompositor: <T extends keyof CompositorCommand>(type: T, payload: CompositorCommand[T], indent: boolean) => Compositor;
|
|
@@ -1,54 +1,57 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.startCompositor = exports.
|
|
4
|
-
const
|
|
6
|
+
exports.startCompositor = exports.startLongRunningCompositor = exports.getIdealMaximumFrameCacheItems = void 0;
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
5
10
|
const call_ffmpeg_1 = require("../call-ffmpeg");
|
|
11
|
+
const get_concurrency_1 = require("../get-concurrency");
|
|
12
|
+
const logger_1 = require("../logger");
|
|
13
|
+
const compose_1 = require("./compose");
|
|
6
14
|
const get_executable_path_1 = require("./get-executable-path");
|
|
7
15
|
const make_nonce_1 = require("./make-nonce");
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const releaseCompositorWithId = (renderId) => {
|
|
17
|
-
if (compositorMap[renderId]) {
|
|
18
|
-
compositorMap[renderId].finishCommands();
|
|
19
|
-
}
|
|
16
|
+
const getIdealMaximumFrameCacheItems = () => {
|
|
17
|
+
const freeMemory = node_os_1.default.freemem();
|
|
18
|
+
// Assuming 1 frame is approximately 6MB
|
|
19
|
+
// Assuming only half the available memory should be used
|
|
20
|
+
const max = Math.floor(freeMemory / (1024 * 1024 * 6));
|
|
21
|
+
// Never store more than 1000 frames
|
|
22
|
+
// But 100 is needed even if it's going to swap
|
|
23
|
+
return Math.max(100, Math.min(max, 1000));
|
|
20
24
|
};
|
|
21
|
-
exports.
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
exports.getIdealMaximumFrameCacheItems = getIdealMaximumFrameCacheItems;
|
|
26
|
+
const startLongRunningCompositor = (maximumFrameCacheItems, verbose, indent) => {
|
|
27
|
+
return (0, exports.startCompositor)('StartLongRunningProcess', {
|
|
28
|
+
concurrency: (0, get_concurrency_1.getActualConcurrency)(null),
|
|
29
|
+
maximum_frame_cache_items: maximumFrameCacheItems,
|
|
30
|
+
verbose,
|
|
31
|
+
}, indent);
|
|
27
32
|
};
|
|
28
|
-
exports.
|
|
29
|
-
const startCompositor = (type, payload) => {
|
|
33
|
+
exports.startLongRunningCompositor = startLongRunningCompositor;
|
|
34
|
+
const startCompositor = (type, payload, indent) => {
|
|
35
|
+
var _a;
|
|
30
36
|
const bin = (0, get_executable_path_1.getExecutablePath)('compositor');
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
const child = (0, child_process_1.spawn)(bin, [JSON.stringify(fullCommand)], (0, call_ffmpeg_1.dynamicLibraryPathOptions)());
|
|
37
|
+
if (!process.env.READ_ONLY_FS) {
|
|
38
|
+
(0, node_fs_1.chmodSync)(bin, 0o755);
|
|
39
|
+
}
|
|
40
|
+
const fullCommand = (0, compose_1.serializeCommand)(type, payload);
|
|
41
|
+
const child = (0, node_child_process_1.spawn)(bin, [JSON.stringify(fullCommand)], (0, call_ffmpeg_1.dynamicLibraryPathOptions)());
|
|
39
42
|
const stderrChunks = [];
|
|
40
43
|
let outputBuffer = Buffer.from('');
|
|
41
44
|
const separator = Buffer.from('remotion_buffer:');
|
|
42
45
|
const waiters = new Map();
|
|
43
46
|
const onMessage = (statusType, nonce, data) => {
|
|
44
47
|
if (nonce === '0') {
|
|
45
|
-
|
|
48
|
+
logger_1.Log.verboseAdvanced({ indent, logLevel: (0, logger_1.getLogLevel)(), tag: 'COMPOSITOR' }, data.toString('utf8'));
|
|
46
49
|
}
|
|
47
50
|
if (waiters.has(nonce)) {
|
|
48
51
|
if (statusType === 'error') {
|
|
49
52
|
try {
|
|
50
53
|
const parsed = JSON.parse(data.toString('utf8'));
|
|
51
|
-
waiters.get(nonce).reject(new Error(`Compositor error: ${parsed.error}`));
|
|
54
|
+
waiters.get(nonce).reject(new Error(`Compositor error: ${parsed.error}\n${parsed.backtrace}`));
|
|
52
55
|
}
|
|
53
56
|
catch (err) {
|
|
54
57
|
waiters.get(nonce).reject(new Error(data.toString('utf8')));
|
|
@@ -137,28 +140,38 @@ const startCompositor = (type, payload) => {
|
|
|
137
140
|
processInput();
|
|
138
141
|
});
|
|
139
142
|
child.stderr.on('data', (data) => {
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
stderrChunks.push(data);
|
|
144
|
+
});
|
|
145
|
+
let resolve = null;
|
|
146
|
+
let reject = null;
|
|
147
|
+
child.on('close', (code) => {
|
|
148
|
+
quit = true;
|
|
149
|
+
const waitersToKill = Array.from(waiters.values());
|
|
150
|
+
if (code === 0) {
|
|
151
|
+
resolve === null || resolve === void 0 ? void 0 : resolve();
|
|
152
|
+
for (const waiter of waitersToKill) {
|
|
153
|
+
waiter.reject(new Error(`Compositor already quit`));
|
|
154
|
+
}
|
|
155
|
+
waiters.clear();
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
const error = new Error(`Compositor panicked: ${Buffer.concat(stderrChunks).toString('utf-8')}`);
|
|
159
|
+
for (const waiter of waitersToKill) {
|
|
160
|
+
waiter.reject(error);
|
|
161
|
+
}
|
|
162
|
+
waiters.clear();
|
|
163
|
+
reject === null || reject === void 0 ? void 0 : reject(error);
|
|
142
164
|
}
|
|
143
|
-
console.log(data.toString('utf-8'));
|
|
144
165
|
});
|
|
145
166
|
return {
|
|
146
167
|
waitForDone: () => {
|
|
147
|
-
return new Promise((
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
waiters.clear();
|
|
155
|
-
if (code === 0) {
|
|
156
|
-
resolve();
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
reject(Buffer.concat(stderrChunks).toString('utf-8'));
|
|
160
|
-
}
|
|
161
|
-
});
|
|
168
|
+
return new Promise((res, rej) => {
|
|
169
|
+
if (quit) {
|
|
170
|
+
rej(new Error('Compositor already quit'));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
resolve = res;
|
|
174
|
+
reject = rej;
|
|
162
175
|
});
|
|
163
176
|
},
|
|
164
177
|
finishCommands: () => {
|
|
@@ -171,7 +184,7 @@ const startCompositor = (type, payload) => {
|
|
|
171
184
|
if (quit) {
|
|
172
185
|
throw new Error('Compositor already quit');
|
|
173
186
|
}
|
|
174
|
-
return new Promise((
|
|
187
|
+
return new Promise((_resolve, _reject) => {
|
|
175
188
|
const nonce = (0, make_nonce_1.makeNonce)();
|
|
176
189
|
const composed = {
|
|
177
190
|
nonce,
|
|
@@ -183,11 +196,12 @@ const startCompositor = (type, payload) => {
|
|
|
183
196
|
// TODO: Should have a way to error out a single task
|
|
184
197
|
child.stdin.write(JSON.stringify(composed) + '\n');
|
|
185
198
|
waiters.set(nonce, {
|
|
186
|
-
resolve,
|
|
187
|
-
reject,
|
|
199
|
+
resolve: _resolve,
|
|
200
|
+
reject: _reject,
|
|
188
201
|
});
|
|
189
202
|
});
|
|
190
203
|
},
|
|
204
|
+
pid: (_a = child.pid) !== null && _a !== void 0 ? _a : null,
|
|
191
205
|
};
|
|
192
206
|
};
|
|
193
207
|
exports.startCompositor = startCompositor;
|
|
@@ -8,6 +8,9 @@ function isMusl() {
|
|
|
8
8
|
return !glibcVersionRuntime;
|
|
9
9
|
}
|
|
10
10
|
const getExecutablePath = (type) => {
|
|
11
|
+
if (type === 'compositor' && process.env.COMPOSITOR_PATH) {
|
|
12
|
+
return process.env.COMPOSITOR_PATH;
|
|
13
|
+
}
|
|
11
14
|
const key = type === 'compositor'
|
|
12
15
|
? 'binaryPath'
|
|
13
16
|
: type === 'ffmpeg'
|
|
@@ -27,13 +27,40 @@ export declare type Layer = {
|
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
29
|
export declare type CompositorImageFormat = 'Png' | 'Jpeg';
|
|
30
|
-
export declare type
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
export declare type CompositorCommand = {
|
|
31
|
+
Compose: {
|
|
32
|
+
output: string;
|
|
33
|
+
width: number;
|
|
34
|
+
height: number;
|
|
35
|
+
layers: Layer[];
|
|
36
|
+
output_format: CompositorImageFormat;
|
|
37
|
+
};
|
|
38
|
+
ExtractFrame: {
|
|
39
|
+
input: string;
|
|
40
|
+
time: number;
|
|
41
|
+
transparent: boolean;
|
|
42
|
+
};
|
|
43
|
+
Echo: {
|
|
44
|
+
message: string;
|
|
45
|
+
};
|
|
46
|
+
StartLongRunningProcess: {
|
|
47
|
+
concurrency: number;
|
|
48
|
+
maximum_frame_cache_items: number;
|
|
49
|
+
verbose: boolean;
|
|
50
|
+
};
|
|
51
|
+
GetOpenVideoStats: {};
|
|
52
|
+
DeliberatePanic: {};
|
|
53
|
+
CloseAllVideos: {};
|
|
54
|
+
FreeUpMemory: {
|
|
55
|
+
percent_of_memory: number;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export declare type CompositorCommandSerialized<T extends keyof CompositorCommand> = {
|
|
59
|
+
nonce: string;
|
|
60
|
+
payload: {
|
|
61
|
+
type: T;
|
|
62
|
+
params: CompositorCommand[T];
|
|
63
|
+
};
|
|
37
64
|
};
|
|
38
65
|
export declare type ErrorPayload = {
|
|
39
66
|
error: string;
|
package/dist/crf.js
CHANGED
|
@@ -9,7 +9,7 @@ const getDefaultCrfForCodec = (codec) => {
|
|
|
9
9
|
if (codec === 'h264' || codec === 'h264-mkv') {
|
|
10
10
|
return 18; // FFMPEG default 23
|
|
11
11
|
}
|
|
12
|
-
if (codec === 'h265'
|
|
12
|
+
if (codec === 'h265') {
|
|
13
13
|
return 23; // FFMPEG default 28
|
|
14
14
|
}
|
|
15
15
|
if (codec === 'vp8') {
|
|
@@ -21,6 +21,9 @@ const getDefaultCrfForCodec = (codec) => {
|
|
|
21
21
|
if (codec === 'prores') {
|
|
22
22
|
return 0;
|
|
23
23
|
}
|
|
24
|
+
if (codec === 'gif') {
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
24
27
|
throw new TypeError(`Got unexpected codec "${codec}"`);
|
|
25
28
|
};
|
|
26
29
|
exports.getDefaultCrfForCodec = getDefaultCrfForCodec;
|
|
@@ -31,10 +34,13 @@ const getValidCrfRanges = (codec) => {
|
|
|
31
34
|
if (codec === 'prores') {
|
|
32
35
|
return [0, 0];
|
|
33
36
|
}
|
|
37
|
+
if (codec === 'gif') {
|
|
38
|
+
return [0, 0];
|
|
39
|
+
}
|
|
34
40
|
if (codec === 'h264' || codec === 'h264-mkv') {
|
|
35
41
|
return [1, 51];
|
|
36
42
|
}
|
|
37
|
-
if (codec === 'h265'
|
|
43
|
+
if (codec === 'h265') {
|
|
38
44
|
return [0, 51];
|
|
39
45
|
}
|
|
40
46
|
if (codec === 'vp8') {
|
package/dist/delete-directory.js
CHANGED
|
@@ -24,13 +24,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.deleteDirectory = void 0;
|
|
27
|
-
const
|
|
27
|
+
const node_fs_1 = __importStar(require("node:fs"));
|
|
28
28
|
const is_serve_url_1 = require("./is-serve-url");
|
|
29
29
|
const deleteDirectory = (directory) => {
|
|
30
30
|
if ((0, is_serve_url_1.isServeUrl)(directory)) {
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
if (!(0,
|
|
33
|
+
if (!(0, node_fs_1.existsSync)(directory)) {
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
// Working around a bug with NodeJS 16 on Windows:
|
|
@@ -41,7 +41,7 @@ const deleteDirectory = (directory) => {
|
|
|
41
41
|
let retries = 2;
|
|
42
42
|
while (retries >= 0) {
|
|
43
43
|
try {
|
|
44
|
-
|
|
44
|
+
node_fs_1.default.rmSync(directory, {
|
|
45
45
|
maxRetries: 2,
|
|
46
46
|
recursive: true,
|
|
47
47
|
force: true,
|
package/dist/does-have-m2-bug.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.warnAboutM2Bug = void 0;
|
|
4
|
-
const
|
|
4
|
+
const node_os_1 = require("node:os");
|
|
5
5
|
const warnAboutM2Bug = (codec, pixelFormat) => {
|
|
6
|
-
const isM2 = (0,
|
|
6
|
+
const isM2 = (0, node_os_1.cpus)().find((c) => c.model.includes('Apple M2'));
|
|
7
7
|
if (codec === 'prores' && pixelFormat === 'yuv422p10le' && isM2) {
|
|
8
8
|
console.warn();
|
|
9
9
|
console.warn('⚠️ Known issue: Apple M2 CPUs currently suffer from a bug where transparent ProRes videos have flickering. https://github.com/remotion-dev/remotion/issues/1929');
|
|
@@ -4,12 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ensureOutputDirectory = void 0;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const ensureOutputDirectory = (outputLocation) => {
|
|
10
|
-
const dirName =
|
|
11
|
-
if (!
|
|
12
|
-
|
|
10
|
+
const dirName = node_path_1.default.dirname(outputLocation);
|
|
11
|
+
if (!node_fs_1.default.existsSync(dirName)) {
|
|
12
|
+
node_fs_1.default.mkdirSync(dirName, {
|
|
13
13
|
recursive: true,
|
|
14
14
|
});
|
|
15
15
|
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import type { DownloadMap } from './assets/download-map';
|
|
2
|
-
|
|
2
|
+
import type { FfmpegExecutable } from './ffmpeg-executable';
|
|
3
|
+
export declare const ensurePresentationTimestampWithoutCache: ({ src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }: {
|
|
3
4
|
src: string;
|
|
5
|
+
remotionRoot: string;
|
|
6
|
+
ffmpegExecutable: FfmpegExecutable;
|
|
7
|
+
ffprobeExecutable: FfmpegExecutable;
|
|
4
8
|
}) => Promise<string>;
|
|
5
|
-
export declare const ensurePresentationTimestamps: ({ downloadMap, src, }: {
|
|
9
|
+
export declare const ensurePresentationTimestamps: ({ downloadMap, src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }: {
|
|
6
10
|
downloadMap: DownloadMap;
|
|
7
11
|
src: string;
|
|
12
|
+
remotionRoot: string;
|
|
13
|
+
ffmpegExecutable: FfmpegExecutable;
|
|
14
|
+
ffprobeExecutable: FfmpegExecutable;
|
|
8
15
|
}) => Promise<string>;
|
|
@@ -4,12 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ensurePresentationTimestamps = exports.ensurePresentationTimestampWithoutCache = void 0;
|
|
7
|
+
const execa_1 = __importDefault(require("execa"));
|
|
7
8
|
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const
|
|
9
|
+
const ffmpeg_flags_1 = require("./ffmpeg-flags");
|
|
9
10
|
const guess_extension_for_media_1 = require("./guess-extension-for-media");
|
|
10
11
|
const truthy_1 = require("./truthy");
|
|
11
12
|
let callbacks = [];
|
|
12
|
-
const getTemporaryOutputName = async ({ src }) => {
|
|
13
|
+
const getTemporaryOutputName = async ({ src, remotionRoot, ffprobeBinary, }) => {
|
|
13
14
|
const parts = src.split(path_1.default.sep);
|
|
14
15
|
// If there is no file extension for the video, then we need to temporarily add an extension
|
|
15
16
|
const lastPart = parts[parts.length - 1];
|
|
@@ -17,6 +18,8 @@ const getTemporaryOutputName = async ({ src }) => {
|
|
|
17
18
|
? null
|
|
18
19
|
: await (0, guess_extension_for_media_1.guessExtensionForVideo)({
|
|
19
20
|
src,
|
|
21
|
+
remotionRoot,
|
|
22
|
+
ffprobeBinary,
|
|
20
23
|
});
|
|
21
24
|
return parts
|
|
22
25
|
.map((p, i) => {
|
|
@@ -27,12 +30,14 @@ const getTemporaryOutputName = async ({ src }) => {
|
|
|
27
30
|
})
|
|
28
31
|
.join(path_1.default.sep);
|
|
29
32
|
};
|
|
30
|
-
const ensurePresentationTimestampWithoutCache = async ({ src, }) => {
|
|
33
|
+
const ensurePresentationTimestampWithoutCache = async ({ src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }) => {
|
|
31
34
|
// If there is no file extension for the video, then we need to tempoa
|
|
32
35
|
const output = await getTemporaryOutputName({
|
|
33
36
|
src,
|
|
37
|
+
remotionRoot,
|
|
38
|
+
ffprobeBinary: ffprobeExecutable,
|
|
34
39
|
});
|
|
35
|
-
await (0,
|
|
40
|
+
await (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffmpegExecutable, remotionRoot, 'ffmpeg'), [
|
|
36
41
|
'-i',
|
|
37
42
|
src,
|
|
38
43
|
'-fflags',
|
|
@@ -47,7 +52,7 @@ const ensurePresentationTimestampWithoutCache = async ({ src, }) => {
|
|
|
47
52
|
return output;
|
|
48
53
|
};
|
|
49
54
|
exports.ensurePresentationTimestampWithoutCache = ensurePresentationTimestampWithoutCache;
|
|
50
|
-
const ensurePresentationTimestamps = async ({ downloadMap, src, }) => {
|
|
55
|
+
const ensurePresentationTimestamps = async ({ downloadMap, src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }) => {
|
|
51
56
|
const elem = downloadMap.ensureFileHasPresentationTimestamp[src];
|
|
52
57
|
if ((elem === null || elem === void 0 ? void 0 : elem.type) === 'encoding') {
|
|
53
58
|
return new Promise((resolve) => {
|
|
@@ -62,6 +67,9 @@ const ensurePresentationTimestamps = async ({ downloadMap, src, }) => {
|
|
|
62
67
|
}
|
|
63
68
|
downloadMap.ensureFileHasPresentationTimestamp[src] = { type: 'encoding' };
|
|
64
69
|
const output = await (0, exports.ensurePresentationTimestampWithoutCache)({
|
|
70
|
+
ffmpegExecutable,
|
|
71
|
+
ffprobeExecutable,
|
|
72
|
+
remotionRoot,
|
|
65
73
|
src,
|
|
66
74
|
});
|
|
67
75
|
callbacks = callbacks.filter((c) => {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import type { OffthreadVideoImageFormat } from 'remotion';
|
|
3
2
|
import type { DownloadMap } from './assets/download-map';
|
|
3
|
+
import type { FfmpegExecutable } from './ffmpeg-executable';
|
|
4
4
|
import type { LastFrameOptions } from './last-frame-from-video-cache';
|
|
5
5
|
export declare const getLastFrameOfVideo: (options: LastFrameOptions) => Promise<Buffer>;
|
|
6
6
|
declare type Options = {
|
|
7
7
|
time: number;
|
|
8
8
|
src: string;
|
|
9
|
+
ffmpegExecutable: FfmpegExecutable;
|
|
10
|
+
ffprobeExecutable: FfmpegExecutable;
|
|
9
11
|
imageFormat: OffthreadVideoImageFormat;
|
|
10
12
|
downloadMap: DownloadMap;
|
|
11
13
|
remotionRoot: string;
|