@remotion/renderer 3.0.16 → 3.0.19
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/cleanup-assets.d.ts +2 -0
- package/dist/assets/cleanup-assets.js +2 -0
- package/dist/assets/get-audio-channels.d.ts +2 -1
- package/dist/assets/get-audio-channels.js +2 -2
- package/dist/calculate-ffmpeg-filters.js +2 -2
- package/dist/combine-videos.js +3 -0
- package/dist/ensure-faststart.d.ts +1 -0
- package/dist/ensure-faststart.js +14 -0
- package/dist/extract-frame-from-video.d.ts +4 -6
- package/dist/extract-frame-from-video.js +104 -31
- package/dist/faststart/atom.d.ts +35 -0
- package/dist/faststart/atom.js +138 -0
- package/dist/faststart/index.d.ts +0 -0
- package/dist/faststart/index.js +1 -0
- package/dist/faststart/options.d.ts +6 -0
- package/dist/faststart/options.js +2 -0
- package/dist/faststart/qt-faststart.d.ts +18 -0
- package/dist/faststart/qt-faststart.js +66 -0
- package/dist/faststart/update-chunk-offsets.d.ts +10 -0
- package/dist/faststart/update-chunk-offsets.js +114 -0
- package/dist/faststart/util.d.ts +9 -0
- package/dist/faststart/util.js +34 -0
- package/dist/get-compositions.d.ts +1 -0
- package/dist/get-compositions.js +3 -2
- package/dist/get-duration-of-asset.d.ts +7 -0
- package/dist/get-duration-of-asset.js +36 -0
- package/dist/get-port.js +26 -24
- package/dist/index.d.ts +1 -0
- package/dist/is-beyond-last-frame.d.ts +2 -0
- package/dist/is-beyond-last-frame.js +12 -0
- package/dist/last-frame-from-video-cache.d.ts +13 -0
- package/dist/last-frame-from-video-cache.js +52 -0
- package/dist/make-assets-download-dir.js +6 -1
- package/dist/offthread-video-server.d.ts +2 -1
- package/dist/offthread-video-server.js +3 -1
- package/dist/prepare-server.d.ts +2 -1
- package/dist/prepare-server.js +3 -1
- package/dist/preprocess-audio-track.d.ts +1 -0
- package/dist/preprocess-audio-track.js +2 -2
- package/dist/provide-screenshot.js +1 -1
- package/dist/render-frames.d.ts +1 -0
- package/dist/render-frames.js +6 -3
- package/dist/render-gif.d.ts +2 -0
- package/dist/render-gif.js +242 -0
- package/dist/render-media.d.ts +7 -1
- package/dist/render-media.js +10 -1
- package/dist/render-still.d.ts +4 -1
- package/dist/render-still.js +7 -4
- package/dist/serve-handler/glob-slash.d.ts +1 -0
- package/dist/serve-handler/glob-slash.js +12 -0
- package/dist/serve-handler/index.d.ts +4 -0
- package/dist/serve-handler/index.js +212 -0
- package/dist/serve-handler/is-path-inside.d.ts +1 -0
- package/dist/serve-handler/is-path-inside.js +27 -0
- package/dist/serve-handler/range-parser.d.ts +13 -0
- package/dist/serve-handler/range-parser.js +57 -0
- package/dist/serve-static.d.ts +1 -0
- package/dist/serve-static.js +3 -4
- package/dist/stitch-frames-to-gif.d.ts +8 -0
- package/dist/stitch-frames-to-gif.js +128 -0
- package/dist/stitch-frames-to-video.d.ts +1 -0
- package/dist/stitch-frames-to-video.js +17 -10
- package/dist/validate-fps-for-gif.d.ts +2 -0
- package/dist/validate-fps-for-gif.js +9 -0
- package/package.json +5 -5
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* range-parser
|
|
4
|
+
* Copyright(c) 2012-2014 TJ Holowaychuk
|
|
5
|
+
* Copyright(c) 2015-2016 Douglas Christopher Wilson
|
|
6
|
+
* MIT Licensed
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.rangeParser = void 0;
|
|
10
|
+
const rangeParser = (size, str) => {
|
|
11
|
+
if (typeof str !== 'string') {
|
|
12
|
+
throw new TypeError('argument str must be a string');
|
|
13
|
+
}
|
|
14
|
+
const index = str.indexOf('=');
|
|
15
|
+
if (index === -1) {
|
|
16
|
+
return -2;
|
|
17
|
+
}
|
|
18
|
+
// split the range string
|
|
19
|
+
const arr = str.slice(index + 1).split(',');
|
|
20
|
+
const ranges = [];
|
|
21
|
+
// add ranges type
|
|
22
|
+
const type = str.slice(0, index);
|
|
23
|
+
// parse all ranges
|
|
24
|
+
for (let i = 0; i < arr.length; i++) {
|
|
25
|
+
const range = arr[i].split('-');
|
|
26
|
+
let start = parseInt(range[0], 10);
|
|
27
|
+
let end = parseInt(range[1], 10);
|
|
28
|
+
// -nnn
|
|
29
|
+
if (isNaN(start)) {
|
|
30
|
+
start = size - end;
|
|
31
|
+
end = size - 1;
|
|
32
|
+
// nnn-
|
|
33
|
+
}
|
|
34
|
+
else if (isNaN(end)) {
|
|
35
|
+
end = size - 1;
|
|
36
|
+
}
|
|
37
|
+
// limit last-byte-pos to current length
|
|
38
|
+
if (end > size - 1) {
|
|
39
|
+
end = size - 1;
|
|
40
|
+
}
|
|
41
|
+
// invalid or unsatisifiable
|
|
42
|
+
if (isNaN(start) || isNaN(end) || start > end || start < 0) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// add range
|
|
46
|
+
ranges.push({
|
|
47
|
+
start,
|
|
48
|
+
end,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (ranges.length < 1) {
|
|
52
|
+
// unsatisifiable
|
|
53
|
+
return -1;
|
|
54
|
+
}
|
|
55
|
+
return { ranges, type };
|
|
56
|
+
};
|
|
57
|
+
exports.rangeParser = rangeParser;
|
package/dist/serve-static.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file'
|
|
|
3
3
|
export declare const serveStatic: (path: string | null, options: {
|
|
4
4
|
port: number | null;
|
|
5
5
|
ffmpegExecutable: FfmpegExecutable;
|
|
6
|
+
ffprobeExecutable: FfmpegExecutable;
|
|
6
7
|
downloadDir: string;
|
|
7
8
|
onDownload: RenderMediaOnDownload;
|
|
8
9
|
onError: (err: Error) => void;
|
package/dist/serve-static.js
CHANGED
|
@@ -6,14 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.serveStatic = void 0;
|
|
7
7
|
const http_1 = __importDefault(require("http"));
|
|
8
8
|
const remotion_1 = require("remotion");
|
|
9
|
-
const serve_handler_1 = __importDefault(require("serve-handler"));
|
|
10
9
|
const get_port_1 = require("./get-port");
|
|
11
10
|
const offthread_video_server_1 = require("./offthread-video-server");
|
|
11
|
+
const serve_handler_1 = require("./serve-handler");
|
|
12
12
|
const serveStatic = async (path, options) => {
|
|
13
13
|
var _a, _b;
|
|
14
14
|
const port = await (0, get_port_1.getDesiredPort)((_b = (_a = options === null || options === void 0 ? void 0 : options.port) !== null && _a !== void 0 ? _a : remotion_1.Internals.getServerPort()) !== null && _b !== void 0 ? _b : undefined, 3000, 3100);
|
|
15
15
|
const offthreadRequest = (0, offthread_video_server_1.startOffthreadVideoServer)({
|
|
16
16
|
ffmpegExecutable: options.ffmpegExecutable,
|
|
17
|
+
ffprobeExecutable: options.ffprobeExecutable,
|
|
17
18
|
downloadDir: options.downloadDir,
|
|
18
19
|
onDownload: options.onDownload,
|
|
19
20
|
onError: options.onError,
|
|
@@ -30,10 +31,8 @@ const serveStatic = async (path, options) => {
|
|
|
30
31
|
response.end('Server only supports /proxy');
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
|
-
(0, serve_handler_1.
|
|
34
|
+
(0, serve_handler_1.serveHandler)(request, response, {
|
|
34
35
|
public: path,
|
|
35
|
-
directoryListing: false,
|
|
36
|
-
cleanUrls: false,
|
|
37
36
|
}).catch(() => {
|
|
38
37
|
response.statusCode = 500;
|
|
39
38
|
response.end('Error serving file');
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { StitcherOptions } from './stitch-frames-to-video';
|
|
2
|
+
declare type ReturnType = {
|
|
3
|
+
task: Promise<unknown>;
|
|
4
|
+
getLogs: () => string;
|
|
5
|
+
};
|
|
6
|
+
export declare const spawnFfmpeg: (options: StitcherOptions) => Promise<ReturnType>;
|
|
7
|
+
export declare const stitchFramesToGif: (options: StitcherOptions) => Promise<void>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,128 @@
|
|
|
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.stitchFramesToGif = exports.spawnFfmpeg = void 0;
|
|
7
|
+
const execa_1 = __importDefault(require("execa"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const remotion_1 = require("remotion");
|
|
11
|
+
const get_codec_name_1 = require("./get-codec-name");
|
|
12
|
+
const get_prores_profile_name_1 = require("./get-prores-profile-name");
|
|
13
|
+
const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
|
|
14
|
+
const validate_even_dimensions_with_codec_1 = require("./validate-even-dimensions-with-codec");
|
|
15
|
+
const validate_ffmpeg_1 = require("./validate-ffmpeg");
|
|
16
|
+
const packageJsonPath = path_1.default.join(__dirname, '..', 'package.json');
|
|
17
|
+
const packageJson = fs_1.default.existsSync(packageJsonPath)
|
|
18
|
+
? JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'))
|
|
19
|
+
: null;
|
|
20
|
+
const spawnFfmpeg = async (options) => {
|
|
21
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
22
|
+
remotion_1.Internals.validateDimension(options.height, 'height', 'passed to `stitchFramesToVideo()`');
|
|
23
|
+
remotion_1.Internals.validateDimension(options.width, 'width', 'passed to `stitchFramesToVideo()`');
|
|
24
|
+
remotion_1.Internals.validateFps(options.fps, 'passed to `stitchFramesToVideo()`');
|
|
25
|
+
const codec = (_a = options.codec) !== null && _a !== void 0 ? _a : remotion_1.Internals.DEFAULT_CODEC;
|
|
26
|
+
(0, validate_even_dimensions_with_codec_1.validateEvenDimensionsWithCodec)({
|
|
27
|
+
width: options.width,
|
|
28
|
+
height: options.height,
|
|
29
|
+
codec,
|
|
30
|
+
scale: 1,
|
|
31
|
+
});
|
|
32
|
+
const crf = (_b = options.crf) !== null && _b !== void 0 ? _b : remotion_1.Internals.getDefaultCrfForCodec(codec);
|
|
33
|
+
const pixelFormat = (_c = options.pixelFormat) !== null && _c !== void 0 ? _c : remotion_1.Internals.DEFAULT_PIXEL_FORMAT;
|
|
34
|
+
await (0, validate_ffmpeg_1.validateFfmpeg)((_d = options.ffmpegExecutable) !== null && _d !== void 0 ? _d : null);
|
|
35
|
+
const encoderName = (0, get_codec_name_1.getCodecName)(codec);
|
|
36
|
+
const proResProfileName = (0, get_prores_profile_name_1.getProResProfileName)(codec, options.proResProfile);
|
|
37
|
+
const supportsCrf = encoderName && codec !== 'prores';
|
|
38
|
+
if (options.verbose) {
|
|
39
|
+
console.log('[verbose] ffmpeg', (_e = options.ffmpegExecutable) !== null && _e !== void 0 ? _e : 'ffmpeg in PATH');
|
|
40
|
+
console.log('[verbose] encoder', encoderName);
|
|
41
|
+
console.log('[verbose] pixelFormat', pixelFormat);
|
|
42
|
+
if (supportsCrf) {
|
|
43
|
+
console.log('[verbose] crf', crf);
|
|
44
|
+
}
|
|
45
|
+
console.log('[verbose] codec', codec);
|
|
46
|
+
console.log('[verbose] proResProfileName', proResProfileName);
|
|
47
|
+
}
|
|
48
|
+
remotion_1.Internals.validateSelectedCrfAndCodecCombination(crf, codec);
|
|
49
|
+
remotion_1.Internals.validateSelectedPixelFormatAndCodecCombination(pixelFormat, codec);
|
|
50
|
+
const expectedFrames = options.assetsInfo.assets.length;
|
|
51
|
+
const updateProgress = (preStitchProgress, muxProgress) => {
|
|
52
|
+
var _a;
|
|
53
|
+
const totalFrameProgress = 0.5 * preStitchProgress * expectedFrames + muxProgress * 0.5;
|
|
54
|
+
(_a = options.onProgress) === null || _a === void 0 ? void 0 : _a.call(options, Math.round(totalFrameProgress));
|
|
55
|
+
};
|
|
56
|
+
const ffmpegArgs = [
|
|
57
|
+
['-r', String(options.fps)],
|
|
58
|
+
...(((_f = options.internalOptions) === null || _f === void 0 ? void 0 : _f.preEncodedFileLocation)
|
|
59
|
+
? [['-i', (_g = options.internalOptions) === null || _g === void 0 ? void 0 : _g.preEncodedFileLocation]]
|
|
60
|
+
: [
|
|
61
|
+
['-f', 'image2'],
|
|
62
|
+
['-s', `${options.width}x${options.height}`],
|
|
63
|
+
['-start_number', String(options.assetsInfo.firstFrameIndex)],
|
|
64
|
+
['-i', options.assetsInfo.imageSequenceName],
|
|
65
|
+
]),
|
|
66
|
+
// -c:v is the same as -vcodec as -codec:video
|
|
67
|
+
// and specified the video codec.
|
|
68
|
+
options.loop === null
|
|
69
|
+
? null
|
|
70
|
+
: ['-loop', typeof options.loop === 'number' ? options.loop : '-1'],
|
|
71
|
+
// Ignore metadata that may come from remote media
|
|
72
|
+
['-map_metadata', '-1'],
|
|
73
|
+
[
|
|
74
|
+
'-metadata',
|
|
75
|
+
`comment=` +
|
|
76
|
+
[`Made with Remotion`, packageJson ? packageJson.version : null].join(' '),
|
|
77
|
+
],
|
|
78
|
+
options.force ? '-y' : null,
|
|
79
|
+
options.outputLocation,
|
|
80
|
+
];
|
|
81
|
+
if (options.verbose) {
|
|
82
|
+
console.log('Generated FFMPEG command:');
|
|
83
|
+
console.log(ffmpegArgs);
|
|
84
|
+
}
|
|
85
|
+
const ffmpegString = ffmpegArgs.flat(2).filter(Boolean);
|
|
86
|
+
const task = (0, execa_1.default)((_h = options.ffmpegExecutable) !== null && _h !== void 0 ? _h : 'ffmpeg', ffmpegString, {
|
|
87
|
+
cwd: options.dir,
|
|
88
|
+
});
|
|
89
|
+
(_j = options.cancelSignal) === null || _j === void 0 ? void 0 : _j.call(options, () => {
|
|
90
|
+
task.kill();
|
|
91
|
+
});
|
|
92
|
+
let ffmpegOutput = '';
|
|
93
|
+
let isFinished = false;
|
|
94
|
+
(_k = task.stderr) === null || _k === void 0 ? void 0 : _k.on('data', (data) => {
|
|
95
|
+
var _a;
|
|
96
|
+
const str = data.toString();
|
|
97
|
+
ffmpegOutput += str;
|
|
98
|
+
if (options.onProgress) {
|
|
99
|
+
const parsed = (0, parse_ffmpeg_progress_1.parseFfmpegProgress)(str);
|
|
100
|
+
// FFMPEG bug: In some cases, FFMPEG does hang after it is finished with it's job
|
|
101
|
+
// Example repo: https://github.com/JonnyBurger/ffmpeg-repro (access can be given upon request)
|
|
102
|
+
if (parsed !== undefined) {
|
|
103
|
+
// If two times in a row the finishing frame is logged, we quit the render
|
|
104
|
+
if (parsed === expectedFrames) {
|
|
105
|
+
if (isFinished) {
|
|
106
|
+
(_a = task.stdin) === null || _a === void 0 ? void 0 : _a.write('q');
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
isFinished = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
updateProgress(1, parsed);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return { task, getLogs: () => ffmpegOutput };
|
|
117
|
+
};
|
|
118
|
+
exports.spawnFfmpeg = spawnFfmpeg;
|
|
119
|
+
const stitchFramesToGif = async (options) => {
|
|
120
|
+
const { task, getLogs } = await (0, exports.spawnFfmpeg)(options);
|
|
121
|
+
try {
|
|
122
|
+
await task;
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
throw new Error(getLogs());
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
exports.stitchFramesToGif = stitchFramesToGif;
|
|
@@ -25,7 +25,7 @@ const packageJsonPath = path_1.default.join(__dirname, '..', 'package.json');
|
|
|
25
25
|
const packageJson = fs_1.default.existsSync(packageJsonPath)
|
|
26
26
|
? JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'))
|
|
27
27
|
: null;
|
|
28
|
-
const getAssetsData = async ({ assets, downloadDir, onDownload, fps, expectedFrames, verbose, ffmpegExecutable, onProgress, }) => {
|
|
28
|
+
const getAssetsData = async ({ assets, downloadDir, onDownload, fps, expectedFrames, verbose, ffmpegExecutable, ffprobeExecutable, onProgress, }) => {
|
|
29
29
|
const fileUrlAssets = await (0, convert_assets_to_file_urls_1.convertAssetsToFileUrls)({
|
|
30
30
|
assets,
|
|
31
31
|
downloadDir,
|
|
@@ -45,6 +45,7 @@ const getAssetsData = async ({ assets, downloadDir, onDownload, fps, expectedFra
|
|
|
45
45
|
const filterFile = path_1.default.join(tempPath, `${index}.wav`);
|
|
46
46
|
const result = await (0, preprocess_audio_track_1.preprocessAudioTrack)({
|
|
47
47
|
ffmpegExecutable: ffmpegExecutable !== null && ffmpegExecutable !== void 0 ? ffmpegExecutable : null,
|
|
48
|
+
ffprobeExecutable: ffprobeExecutable !== null && ffprobeExecutable !== void 0 ? ffprobeExecutable : null,
|
|
48
49
|
outName: filterFile,
|
|
49
50
|
asset,
|
|
50
51
|
expectedFrames,
|
|
@@ -68,7 +69,7 @@ const getAssetsData = async ({ assets, downloadDir, onDownload, fps, expectedFra
|
|
|
68
69
|
return outName;
|
|
69
70
|
};
|
|
70
71
|
const spawnFfmpeg = async (options) => {
|
|
71
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
72
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
72
73
|
remotion_1.Internals.validateDimension(options.height, 'height', 'passed to `stitchFramesToVideo()`');
|
|
73
74
|
remotion_1.Internals.validateDimension(options.width, 'width', 'passed to `stitchFramesToVideo()`');
|
|
74
75
|
remotion_1.Internals.validateFps(options.fps, 'passed to `stitchFramesToVideo()`');
|
|
@@ -115,6 +116,7 @@ const spawnFfmpeg = async (options) => {
|
|
|
115
116
|
expectedFrames,
|
|
116
117
|
verbose: (_f = options.verbose) !== null && _f !== void 0 ? _f : false,
|
|
117
118
|
ffmpegExecutable: (_g = options.ffmpegExecutable) !== null && _g !== void 0 ? _g : null,
|
|
119
|
+
ffprobeExecutable: (_h = options.ffprobeExecutable) !== null && _h !== void 0 ? _h : null,
|
|
118
120
|
onProgress: (prog) => updateProgress(prog, 0),
|
|
119
121
|
});
|
|
120
122
|
if (isAudioOnly) {
|
|
@@ -126,14 +128,17 @@ const spawnFfmpeg = async (options) => {
|
|
|
126
128
|
audio,
|
|
127
129
|
'-c:a',
|
|
128
130
|
audioCodecName,
|
|
131
|
+
// Set bitrate up to 320k, for aac it might effectively be lower
|
|
132
|
+
'-b:a',
|
|
133
|
+
'320k',
|
|
129
134
|
options.force ? '-y' : null,
|
|
130
135
|
options.outputLocation,
|
|
131
136
|
].filter(remotion_1.Internals.truthy));
|
|
132
|
-
(
|
|
137
|
+
(_j = options.cancelSignal) === null || _j === void 0 ? void 0 : _j.call(options, () => {
|
|
133
138
|
ffmpegTask.kill();
|
|
134
139
|
});
|
|
135
140
|
await ffmpegTask;
|
|
136
|
-
(
|
|
141
|
+
(_k = options.onProgress) === null || _k === void 0 ? void 0 : _k.call(options, expectedFrames);
|
|
137
142
|
return {
|
|
138
143
|
getLogs: () => '',
|
|
139
144
|
task: Promise.resolve(),
|
|
@@ -141,8 +146,8 @@ const spawnFfmpeg = async (options) => {
|
|
|
141
146
|
}
|
|
142
147
|
const ffmpegArgs = [
|
|
143
148
|
['-r', String(options.fps)],
|
|
144
|
-
...(((
|
|
145
|
-
? [['-i', (
|
|
149
|
+
...(((_l = options.internalOptions) === null || _l === void 0 ? void 0 : _l.preEncodedFileLocation)
|
|
150
|
+
? [['-i', (_m = options.internalOptions) === null || _m === void 0 ? void 0 : _m.preEncodedFileLocation]]
|
|
146
151
|
: [
|
|
147
152
|
['-f', 'image2'],
|
|
148
153
|
['-s', `${options.width}x${options.height}`],
|
|
@@ -153,7 +158,7 @@ const spawnFfmpeg = async (options) => {
|
|
|
153
158
|
// -c:v is the same as -vcodec as -codec:video
|
|
154
159
|
// and specified the video codec.
|
|
155
160
|
['-c:v', encoderName],
|
|
156
|
-
...(((
|
|
161
|
+
...(((_o = options.internalOptions) === null || _o === void 0 ? void 0 : _o.preEncodedFileLocation)
|
|
157
162
|
? []
|
|
158
163
|
: [
|
|
159
164
|
proResProfileName ? ['-profile:v', proResProfileName] : null,
|
|
@@ -166,6 +171,8 @@ const spawnFfmpeg = async (options) => {
|
|
|
166
171
|
]),
|
|
167
172
|
codec === 'h264' ? ['-movflags', 'faststart'] : null,
|
|
168
173
|
audioCodecName ? ['-c:a', audioCodecName] : null,
|
|
174
|
+
// Set max bitrate up to 1024kbps, will choose lower if that's too much
|
|
175
|
+
audioCodecName ? ['-b:a', '512K'] : null,
|
|
169
176
|
// Ignore metadata that may come from remote media
|
|
170
177
|
['-map_metadata', '-1'],
|
|
171
178
|
[
|
|
@@ -181,15 +188,15 @@ const spawnFfmpeg = async (options) => {
|
|
|
181
188
|
console.log(ffmpegArgs);
|
|
182
189
|
}
|
|
183
190
|
const ffmpegString = ffmpegArgs.flat(2).filter(Boolean);
|
|
184
|
-
const task = (0, execa_1.default)((
|
|
191
|
+
const task = (0, execa_1.default)((_p = options.ffmpegExecutable) !== null && _p !== void 0 ? _p : 'ffmpeg', ffmpegString, {
|
|
185
192
|
cwd: options.dir,
|
|
186
193
|
});
|
|
187
|
-
(
|
|
194
|
+
(_q = options.cancelSignal) === null || _q === void 0 ? void 0 : _q.call(options, () => {
|
|
188
195
|
task.kill();
|
|
189
196
|
});
|
|
190
197
|
let ffmpegOutput = '';
|
|
191
198
|
let isFinished = false;
|
|
192
|
-
(
|
|
199
|
+
(_r = task.stderr) === null || _r === void 0 ? void 0 : _r.on('data', (data) => {
|
|
193
200
|
var _a;
|
|
194
201
|
const str = data.toString();
|
|
195
202
|
ffmpegOutput += str;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateFpsForGif = void 0;
|
|
4
|
+
const validateFpsForGif = (codec, fps) => {
|
|
5
|
+
if (codec === 'gif' && (fps > 50 || fps < 1)) {
|
|
6
|
+
throw new Error(`To render a GIF, the FPS must be less than or equal to 50 and greater than 0 but got ${fps} instead`);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
exports.validateFpsForGif = validateFpsForGif;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/renderer",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.19",
|
|
4
4
|
"description": "Renderer for Remotion",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"execa": "5.1.1",
|
|
24
|
+
"mime-types": "2.1.35",
|
|
24
25
|
"puppeteer-core": "13.5.1",
|
|
25
|
-
"remotion": "3.0.
|
|
26
|
-
"serve-handler": "6.1.3",
|
|
26
|
+
"remotion": "3.0.19",
|
|
27
27
|
"source-map": "^0.8.0-beta.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"@testing-library/dom": "^8.7.2",
|
|
36
36
|
"@testing-library/react": "13.1.1",
|
|
37
37
|
"@types/jest": "^27.4.0",
|
|
38
|
+
"@types/mime-types": "2.1.1",
|
|
38
39
|
"@types/node": "^16.7.5",
|
|
39
40
|
"@types/react": "18.0.1",
|
|
40
41
|
"@types/react-dom": "18.0.0",
|
|
41
|
-
"@types/serve-handler": "^6.1.0",
|
|
42
42
|
"eslint": "8.13.0",
|
|
43
43
|
"jest": "^27.2.4",
|
|
44
44
|
"prettier": "^2.0.5",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "388ef0a2eacf9dbadbc860fdb8d6b3e32acb10f3"
|
|
63
63
|
}
|