UNPKG

@remotion/renderer

Version:

Render Remotion videos using Node.js or Bun

189 lines (188 loc) • 6.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.audioCodecOption = exports.getDefaultAudioCodec = exports.resolveAudioCodec = exports.getExtensionFromAudioCodec = exports.defaultAudioCodecs = exports.mapAudioCodecToFfmpegAudioCodecName = exports.supportedAudioCodecs = exports.validAudioCodecs = void 0; const separate_audio_1 = require("./separate-audio"); exports.validAudioCodecs = ['pcm-16', 'aac', 'mp3', 'opus']; exports.supportedAudioCodecs = { h264: ['aac', 'pcm-16', 'mp3'], 'h264-mkv': ['pcm-16', 'mp3'], 'h264-ts': ['pcm-16', 'aac'], aac: ['aac', 'pcm-16'], avi: [], gif: [], h265: ['aac', 'pcm-16'], mp3: ['mp3', 'pcm-16'], prores: ['aac', 'pcm-16'], vp8: ['opus', 'pcm-16'], vp9: ['opus', 'pcm-16'], wav: ['pcm-16'], }; const _satisfies = exports.supportedAudioCodecs; if (_satisfies) { // Just for type checking } // eslint-disable-next-line @typescript-eslint/no-unused-vars const audioCodecNames = [ 'pcm_s16le', 'libfdk_aac', 'libmp3lame', 'libopus', ]; const mapAudioCodecToFfmpegAudioCodecName = (audioCodec) => { if (audioCodec === 'aac') { return 'libfdk_aac'; } if (audioCodec === 'mp3') { return 'libmp3lame'; } if (audioCodec === 'opus') { return 'libopus'; } if (audioCodec === 'pcm-16') { return 'pcm_s16le'; } throw new Error('unknown audio codec: ' + audioCodec); }; exports.mapAudioCodecToFfmpegAudioCodecName = mapAudioCodecToFfmpegAudioCodecName; const cliFlag = 'audio-codec'; const ssrName = 'audioCodec'; exports.defaultAudioCodecs = { 'h264-mkv': { lossless: 'pcm-16', compressed: 'pcm-16', }, 'h264-ts': { lossless: 'pcm-16', compressed: 'aac', }, aac: { lossless: 'pcm-16', compressed: 'aac', }, gif: { lossless: null, compressed: null, }, h264: { lossless: 'pcm-16', compressed: 'aac', }, h265: { lossless: 'pcm-16', compressed: 'aac', }, mp3: { lossless: 'pcm-16', compressed: 'mp3', }, prores: { lossless: 'pcm-16', compressed: 'pcm-16', }, vp8: { lossless: 'pcm-16', compressed: 'opus', }, vp9: { lossless: 'pcm-16', compressed: 'opus', }, wav: { lossless: 'pcm-16', compressed: 'pcm-16', }, }; const extensionMap = { aac: 'aac', mp3: 'mp3', opus: 'opus', 'pcm-16': 'wav', }; const getExtensionFromAudioCodec = (audioCodec) => { if (extensionMap[audioCodec]) { return extensionMap[audioCodec]; } throw new Error(`Unsupported audio codec: ${audioCodec}`); }; exports.getExtensionFromAudioCodec = getExtensionFromAudioCodec; const resolveAudioCodec = ({ codec, setting, preferLossless, separateAudioTo, }) => { let derivedFromSeparateAudioToExtension = null; if (separateAudioTo) { const extension = separateAudioTo.split('.').pop(); for (const [key, value] of Object.entries(extensionMap)) { if (value === extension) { derivedFromSeparateAudioToExtension = key; if (!exports.supportedAudioCodecs[codec].includes(derivedFromSeparateAudioToExtension) && derivedFromSeparateAudioToExtension) { throw new Error(`The codec is ${codec} but the audio codec derived from --${separate_audio_1.separateAudioOption.cliFlag} is ${derivedFromSeparateAudioToExtension}. The only supported codecs are: ${exports.supportedAudioCodecs[codec].join(', ')}`); } } } } // Explanation: https://github.com/remotion-dev/remotion/issues/1647 if (preferLossless) { const selected = (0, exports.getDefaultAudioCodec)({ codec, preferLossless }); if (derivedFromSeparateAudioToExtension && selected !== derivedFromSeparateAudioToExtension) { throw new Error(`The audio codec derived from --${separate_audio_1.separateAudioOption.cliFlag} is ${derivedFromSeparateAudioToExtension}, but does not match the audio codec derived from the "Prefer lossless" option (${selected}). Remove any conflicting options.`); } return selected; } if (setting === null) { if (derivedFromSeparateAudioToExtension) { return derivedFromSeparateAudioToExtension; } return (0, exports.getDefaultAudioCodec)({ codec, preferLossless }); } if (derivedFromSeparateAudioToExtension !== setting && derivedFromSeparateAudioToExtension) { throw new Error(`The audio codec derived from --${separate_audio_1.separateAudioOption.cliFlag} is ${derivedFromSeparateAudioToExtension}, but does not match the audio codec derived from your ${exports.audioCodecOption.name} setting (${setting}). Remove any conflicting options.`); } return setting; }; exports.resolveAudioCodec = resolveAudioCodec; const getDefaultAudioCodec = ({ codec, preferLossless, }) => { return exports.defaultAudioCodecs[codec][preferLossless ? 'lossless' : 'compressed']; }; exports.getDefaultAudioCodec = getDefaultAudioCodec; let _audioCodec = null; exports.audioCodecOption = { cliFlag, setConfig: (audioCodec) => { if (audioCodec === null) { _audioCodec = null; return; } if (!exports.validAudioCodecs.includes(audioCodec)) { throw new Error(`Audio codec must be one of the following: ${exports.validAudioCodecs.join(', ')}, but got ${audioCodec}`); } _audioCodec = audioCodec; }, getValue: ({ commandLine }) => { if (commandLine[cliFlag]) { const codec = commandLine[cliFlag]; if (!exports.validAudioCodecs.includes(commandLine[cliFlag])) { throw new Error(`Audio codec must be one of the following: ${exports.validAudioCodecs.join(', ')}, but got ${codec}`); } return { source: 'cli', value: commandLine[cliFlag], }; } if (_audioCodec !== null) { return { source: 'config', value: _audioCodec, }; } return { source: 'default', value: null, }; }, description: () => `Set the format of the audio that is embedded in the video. Not all codec and audio codec combinations are supported and certain combinations require a certain file extension and container format. See the table in the docs to see possible combinations.`, docLink: 'https://www.remotion.dev/docs/encoding/#audio-codec', name: 'Audio Codec', ssrName, type: 'aac', };