@remotion/renderer
Version:
Render Remotion videos using Node.js or Bun
113 lines (112 loc) • 4.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.prespawnFfmpeg = void 0;
const call_ffmpeg_1 = require("./call-ffmpeg");
const codec_1 = require("./codec");
const ffmpeg_args_1 = require("./ffmpeg-args");
const get_prores_profile_name_1 = require("./get-prores-profile-name");
const logger_1 = require("./logger");
const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
const pixel_format_1 = require("./pixel-format");
const validate_1 = require("./validate");
const validate_even_dimensions_with_codec_1 = require("./validate-even-dimensions-with-codec");
const prespawnFfmpeg = (options) => {
var _a, _b, _c;
(0, validate_1.validateDimension)(options.height, 'height', 'passed to `stitchFramesToVideo()`');
(0, validate_1.validateDimension)(options.width, 'width', 'passed to `stitchFramesToVideo()`');
const codec = (_a = options.codec) !== null && _a !== void 0 ? _a : codec_1.DEFAULT_CODEC;
(0, validate_1.validateFps)(options.fps, 'in `stitchFramesToVideo()`', codec === 'gif');
(0, validate_even_dimensions_with_codec_1.validateEvenDimensionsWithCodec)({
width: options.width,
height: options.height,
codec,
scale: 1,
wantsImageSequence: false,
indent: options.indent,
logLevel: options.logLevel,
});
const pixelFormat = (_b = options.pixelFormat) !== null && _b !== void 0 ? _b : pixel_format_1.DEFAULT_PIXEL_FORMAT;
const proResProfileName = (0, get_prores_profile_name_1.getProResProfileName)(codec, options.proResProfile);
(0, pixel_format_1.validateSelectedPixelFormatAndCodecCombination)(pixelFormat, codec);
const ffmpegArgs = [
['-r', options.fps],
...[
['-f', 'image2pipe'],
['-s', `${options.width}x${options.height}`],
// If scale is very small (like 0.1), FFMPEG cannot figure out the image
// format on it's own and we need to hint the format
['-vcodec', options.imageFormat === 'jpeg' ? 'mjpeg' : 'png'],
['-i', '-'],
],
...(0, ffmpeg_args_1.generateFfmpegArgs)({
hasPreencoded: false,
proResProfileName,
pixelFormat,
x264Preset: options.x264Preset,
codec,
crf: options.crf,
videoBitrate: options.videoBitrate,
encodingMaxRate: options.encodingMaxRate,
encodingBufferSize: options.encodingBufferSize,
colorSpace: options.colorSpace,
hardwareAcceleration: options.hardwareAcceleration,
indent: options.indent,
logLevel: options.logLevel,
}),
'-y',
options.outputLocation,
];
logger_1.Log.verbose({
indent: options.indent,
logLevel: options.logLevel,
tag: 'prespawnFfmpeg()',
}, 'Generated FFMPEG command:');
logger_1.Log.verbose({
indent: options.indent,
logLevel: options.logLevel,
tag: 'prespawnFfmpeg()',
}, ffmpegArgs.join(' '));
const ffmpegString = ffmpegArgs.flat(2).filter(Boolean);
const finalFfmpegString = options.ffmpegOverride
? options.ffmpegOverride({ type: 'pre-stitcher', args: ffmpegString })
: ffmpegString;
const task = (0, call_ffmpeg_1.callFf)({
bin: 'ffmpeg',
args: finalFfmpegString,
indent: options.indent,
logLevel: options.logLevel,
binariesDirectory: options.binariesDirectory,
cancelSignal: options.signal,
});
let ffmpegOutput = '';
(_c = task.stderr) === null || _c === void 0 ? void 0 : _c.on('data', (data) => {
const str = data.toString();
ffmpegOutput += str;
if (options.onProgress) {
const parsed = (0, parse_ffmpeg_progress_1.parseFfmpegProgress)(str, options.fps);
if (parsed !== undefined) {
options.onProgress(parsed);
}
}
});
let exitCode = {
type: 'running',
};
task.on('exit', (code) => {
if (typeof code === 'number' && code > 0) {
exitCode = {
type: 'quit-with-error',
exitCode: code,
stderr: ffmpegOutput,
};
}
else {
exitCode = {
type: 'quit-successfully',
stderr: ffmpegOutput,
};
}
});
return { task, getLogs: () => ffmpegOutput, getExitStatus: () => exitCode };
};
exports.prespawnFfmpeg = prespawnFfmpeg;