X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fhelpers%2Fffmpeg-utils.ts;h=2d9ce2bfa0313aa90e7fe6318597407624b22803;hb=5c7d650827cc471a03e7fa18362bcbcbe5d30838;hp=c180da832135cc1c3bc4e4ea743d4efad53eb4bb;hpb=79ad1706f3cf009e04db9cd9e6a721801d93e64e;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index c180da832..2d9ce2bfa 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts @@ -14,11 +14,13 @@ function computeResolutionsToTranscode (videoFileHeight: number) { // Put in the order we want to proceed jobs const resolutions = [ + VideoResolution.H_NOVIDEO, VideoResolution.H_480P, VideoResolution.H_360P, VideoResolution.H_720P, VideoResolution.H_240P, - VideoResolution.H_1080P + VideoResolution.H_1080P, + VideoResolution.H_4K ] for (const resolution of resolutions) { @@ -33,10 +35,15 @@ function computeResolutionsToTranscode (videoFileHeight: number) { async function getVideoFileSize (path: string) { const videoStream = await getVideoStreamFromFile(path) - return { - width: videoStream.width, - height: videoStream.height - } + return videoStream == null + ? { + width: 0, + height: 0 + } + : { + width: videoStream.width, + height: videoStream.height + } } async function getVideoFileResolution (path: string) { @@ -51,6 +58,10 @@ async function getVideoFileResolution (path: string) { async function getVideoFileFPS (path: string) { const videoStream = await getVideoStreamFromFile(path) + if (videoStream == null) { + return 0 + } + for (const key of [ 'avg_frame_rate', 'r_frame_rate' ]) { const valuesText: string = videoStream[key] if (!valuesText) continue @@ -117,7 +128,7 @@ async function generateImageFromVideoFile (fromPath: string, folder: string, ima } } -type TranscodeOptionsType = 'hls' | 'quick-transcode' | 'video' | 'merge-audio' +type TranscodeOptionsType = 'hls' | 'quick-transcode' | 'video' | 'merge-audio' | 'split-audio' interface BaseTranscodeOptions { type: TranscodeOptionsType @@ -129,6 +140,7 @@ interface BaseTranscodeOptions { interface HLSTranscodeOptions extends BaseTranscodeOptions { type: 'hls' + copyCodecs: boolean hlsPlaylist: { videoFilename: string } @@ -147,7 +159,11 @@ interface MergeAudioTranscodeOptions extends BaseTranscodeOptions { audioPath: string } -type TranscodeOptions = HLSTranscodeOptions | VideoTranscodeOptions | MergeAudioTranscodeOptions | QuickTranscodeOptions +interface SplitAudioTranscodeOptions extends BaseTranscodeOptions { + type: 'split-audio' +} + +type TranscodeOptions = HLSTranscodeOptions | VideoTranscodeOptions | MergeAudioTranscodeOptions | SplitAudioTranscodeOptions | QuickTranscodeOptions function transcode (options: TranscodeOptions) { return new Promise(async (res, rej) => { @@ -161,6 +177,8 @@ function transcode (options: TranscodeOptions) { command = await buildHLSCommand(command, options) } else if (options.type === 'merge-audio') { command = await buildAudioMergeCommand(command, options) + } else if (options.type === 'split-audio') { + command = await buildAudioSplitCommand(command, options) } else { command = await buildx264Command(command, options) } @@ -196,7 +214,9 @@ async function canDoQuickTranscode (path: string): Promise { const resolution = await getVideoFileResolution(path) // check video params + if (videoStream == null) return false if (videoStream[ 'codec_name' ] !== 'h264') return false + if (videoStream[ 'pix_fmt' ] !== 'yuv420p') return false if (fps < VIDEO_TRANSCODING_FPS.MIN || fps > VIDEO_TRANSCODING_FPS.MAX) return false if (bitRate > getMaxBitrate(resolution.videoFileResolution, fps, VIDEO_TRANSCODING_FPS)) return false @@ -230,7 +250,7 @@ export { // --------------------------------------------------------------------------- -async function buildx264Command (command: ffmpeg.FfmpegCommand, options: VideoTranscodeOptions) { +async function buildx264Command (command: ffmpeg.FfmpegCommand, options: TranscodeOptions) { let fps = await getVideoFileFPS(options.inputPath) // On small/medium resolutions, limit FPS if ( @@ -273,6 +293,12 @@ async function buildAudioMergeCommand (command: ffmpeg.FfmpegCommand, options: M return command } +async function buildAudioSplitCommand (command: ffmpeg.FfmpegCommand, options: SplitAudioTranscodeOptions) { + command = await presetAudioSplit(command) + + return command +} + async function buildQuickTranscodeCommand (command: ffmpeg.FfmpegCommand) { command = await presetCopy(command) @@ -285,7 +311,8 @@ async function buildQuickTranscodeCommand (command: ffmpeg.FfmpegCommand) { async function buildHLSCommand (command: ffmpeg.FfmpegCommand, options: HLSTranscodeOptions) { const videoPath = getHLSVideoPath(options) - command = await presetCopy(command) + if (options.copyCodecs) command = await presetCopy(command) + else command = await buildx264Command(command, options) command = command.outputOption('-hls_time 4') .outputOption('-hls_list_size 0') @@ -323,7 +350,7 @@ function getVideoStreamFromFile (path: string) { if (err) return rej(err) const videoStream = metadata.streams.find(s => s.codec_type === 'video') - if (!videoStream) return rej(new Error('Cannot find video stream of ' + path)) + //if (!videoStream) return rej(new Error('Cannot find video stream of ' + path)) return res(videoStream) }) @@ -386,14 +413,15 @@ namespace audio { export namespace bitrate { const baseKbitrate = 384 - const toBits = (kbits: number): number => { return kbits * 8000 } + const toBits = (kbits: number) => kbits * 8000 export const aac = (bitrate: number): number => { switch (true) { - case bitrate > toBits(baseKbitrate): - return baseKbitrate - default: - return -1 // we interpret it as a signal to copy the audio stream as is + case bitrate > toBits(baseKbitrate): + return baseKbitrate + + default: + return -1 // we interpret it as a signal to copy the audio stream as is } } @@ -404,12 +432,14 @@ namespace audio { made here are not made to be accurate, especially with good mp3 encoders. */ switch (true) { - case bitrate <= toBits(192): - return 128 - case bitrate <= toBits(384): - return 256 - default: - return baseKbitrate + case bitrate <= toBits(192): + return 128 + + case bitrate <= toBits(384): + return 256 + + default: + return baseKbitrate } } } @@ -475,3 +505,11 @@ async function presetCopy (command: ffmpeg.FfmpegCommand): Promise { + return command + .format('mp4') + .audioCodec('copy') + .noVideo() +}