UNPKG

@remotion/renderer

Version:

Render Remotion videos using Node.js or Bun

113 lines (112 loc) 4.54 kB
"use strict"; 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;