X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fhelpers%2Fffmpeg-utils.ts;h=69564a1a3b4c068b4aaad19987c5b3b0a7b0d74a;hb=9e2b2e76ba5f7f570dcf59fc03bfec98ea5ffab8;hp=2f167a5803505a88ca41ca8b2a061207b2f309be;hpb=b5b687550d8ef8beafdf706e45d6556fb5f4c876;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index 2f167a580..69564a1a3 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts @@ -271,6 +271,8 @@ type TranscodeOptions = | QuickTranscodeOptions function transcode (options: TranscodeOptions) { + logger.debug('Will run transcode.', { options }) + return new Promise(async (res, rej) => { try { let command = getFFmpeg(options.inputPath) @@ -353,7 +355,7 @@ function convertWebPToJPG (path: string, destination: string): Promise { }) } -function runLiveTranscoding (rtmpUrl: string, outPath: string, resolutions: number[], deleteSegments: boolean) { +function runLiveTranscoding (rtmpUrl: string, outPath: string, resolutions: number[], fps, deleteSegments: boolean) { const command = getFFmpeg(rtmpUrl) command.inputOption('-fflags nobuffer') @@ -375,23 +377,21 @@ function runLiveTranscoding (rtmpUrl: string, outPath: string, resolutions: numb })) ]) - const liveFPS = VIDEO_TRANSCODING_FPS.AVERAGE - - command.withFps(liveFPS) - command.outputOption('-b_strategy 1') command.outputOption('-bf 16') command.outputOption('-preset superfast') command.outputOption('-level 3.1') command.outputOption('-map_metadata -1') command.outputOption('-pix_fmt yuv420p') + command.outputOption('-max_muxing_queue_size 1024') + command.outputOption('-g ' + (fps * 2)) for (let i = 0; i < resolutions.length; i++) { const resolution = resolutions[i] command.outputOption(`-map [vout${resolution}]`) command.outputOption(`-c:v:${i} libx264`) - command.outputOption(`-b:v:${i} ${getTargetBitrate(resolution, liveFPS, VIDEO_TRANSCODING_FPS)}`) + command.outputOption(`-b:v:${i} ${getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS)}`) command.outputOption(`-map a:0`) command.outputOption(`-c:a:${i} aac`) @@ -424,17 +424,46 @@ function runLiveMuxing (rtmpUrl: string, outPath: string, deleteSegments: boolea return command } -function hlsPlaylistToFragmentedMP4 (playlistPath: string, outputPath: string) { - const command = getFFmpeg(playlistPath) +async function hlsPlaylistToFragmentedMP4 (hlsDirectory: string, segmentFiles: string[], outputPath: string) { + const concatFilePath = join(hlsDirectory, 'concat.txt') + + function cleaner () { + remove(concatFilePath) + .catch(err => logger.error('Cannot remove concat file in %s.', hlsDirectory, { err })) + } + + // First concat the ts files to a mp4 file + const content = segmentFiles.map(f => 'file ' + f) + .join('\n') + + await writeFile(concatFilePath, content + '\n') + + const command = getFFmpeg(concatFilePath) + command.inputOption('-safe 0') + command.inputOption('-f concat') - command.outputOption('-c copy') + command.outputOption('-c:v copy') + command.audioFilter('aresample=async=1:first_pts=0') command.output(outputPath) + return runCommand(command, cleaner) +} + +async function runCommand (command: ffmpeg.FfmpegCommand, onEnd?: Function) { command.run() return new Promise((res, rej) => { - command.on('error', err => rej(err)) - command.on('end', () => res()) + command.on('error', err => { + if (onEnd) onEnd() + + rej(err) + }) + + command.on('end', () => { + if (onEnd) onEnd() + + res() + }) }) } @@ -473,14 +502,14 @@ function addDefaultX264Params (command: ffmpeg.FfmpegCommand) { } function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string, deleteSegments: boolean) { - command.outputOption('-hls_time ' + VIDEO_LIVE.SEGMENT_TIME) + command.outputOption('-hls_time ' + VIDEO_LIVE.SEGMENT_TIME_SECONDS) command.outputOption('-hls_list_size ' + VIDEO_LIVE.SEGMENTS_LIST_SIZE) if (deleteSegments === true) { command.outputOption('-hls_flags delete_segments') } - command.outputOption(`-hls_segment_filename ${join(outPath, '%v-%d.ts')}`) + command.outputOption(`-hls_segment_filename ${join(outPath, '%v-%04d.ts')}`) command.outputOption('-master_pl_name master.m3u8') command.outputOption(`-f hls`)