Copy video/audio codec for HLS
authorChocobozzz <me@florianbigard.com>
Mon, 8 Apr 2019 08:03:23 +0000 (10:03 +0200)
committerChocobozzz <me@florianbigard.com>
Mon, 8 Apr 2019 08:03:23 +0000 (10:03 +0200)
server/helpers/ffmpeg-utils.ts

index b6b64de3f604ba8240499cd650068325ee12f213..c477e2e89fb763a772d7b81537607fcd1d76bcc0 100644 (file)
@@ -130,51 +130,20 @@ type TranscodeOptions = {
 function transcode (options: TranscodeOptions) {
   return new Promise<void>(async (res, rej) => {
     try {
-      let fps = await getVideoFileFPS(options.inputPath)
-      // On small/medium resolutions, limit FPS
-      if (
-        options.resolution !== undefined &&
-        options.resolution < VIDEO_TRANSCODING_FPS.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
-        fps > VIDEO_TRANSCODING_FPS.AVERAGE
-      ) {
-        fps = VIDEO_TRANSCODING_FPS.AVERAGE
-      }
-
       let command = ffmpeg(options.inputPath, { niceness: FFMPEG_NICE.TRANSCODING })
         .output(options.outputPath)
-      command = await presetH264(command, options.resolution, fps)
+
+      if (options.hlsPlaylist) {
+        command = await buildHLSCommand(command, options)
+      } else {
+        command = await buildx264Command(command, options)
+      }
 
       if (CONFIG.TRANSCODING.THREADS > 0) {
         // if we don't set any threads ffmpeg will chose automatically
         command = command.outputOption('-threads ' + CONFIG.TRANSCODING.THREADS)
       }
 
-      if (options.resolution !== undefined) {
-        // '?x720' or '720x?' for example
-        const size = options.isPortraitMode === true ? `${options.resolution}x?` : `?x${options.resolution}`
-        command = command.size(size)
-      }
-
-      if (fps) {
-        // Hard FPS limits
-        if (fps > VIDEO_TRANSCODING_FPS.MAX) fps = VIDEO_TRANSCODING_FPS.MAX
-        else if (fps < VIDEO_TRANSCODING_FPS.MIN) fps = VIDEO_TRANSCODING_FPS.MIN
-
-        command = command.withFPS(fps)
-      }
-
-      if (options.hlsPlaylist) {
-        const videoPath = getHLSVideoPath(options)
-
-        command = command.outputOption('-hls_time 4')
-                         .outputOption('-hls_list_size 0')
-                         .outputOption('-hls_playlist_type vod')
-                         .outputOption('-hls_segment_filename ' + videoPath)
-                         .outputOption('-hls_segment_type fmp4')
-                         .outputOption('-f hls')
-                         .outputOption('-hls_flags single_file')
-      }
-
       command
         .on('error', (err, stdout, stderr) => {
           logger.error('Error in transcoding job.', { stdout, stderr })
@@ -208,6 +177,52 @@ export {
 
 // ---------------------------------------------------------------------------
 
+async function buildx264Command (command: ffmpeg.FfmpegCommand, options: TranscodeOptions) {
+  let fps = await getVideoFileFPS(options.inputPath)
+  // On small/medium resolutions, limit FPS
+  if (
+    options.resolution !== undefined &&
+    options.resolution < VIDEO_TRANSCODING_FPS.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
+    fps > VIDEO_TRANSCODING_FPS.AVERAGE
+  ) {
+    fps = VIDEO_TRANSCODING_FPS.AVERAGE
+  }
+
+  command = await presetH264(command, options.resolution, fps)
+
+  if (options.resolution !== undefined) {
+    // '?x720' or '720x?' for example
+    const size = options.isPortraitMode === true ? `${options.resolution}x?` : `?x${options.resolution}`
+    command = command.size(size)
+  }
+
+  if (fps) {
+    // Hard FPS limits
+    if (fps > VIDEO_TRANSCODING_FPS.MAX) fps = VIDEO_TRANSCODING_FPS.MAX
+    else if (fps < VIDEO_TRANSCODING_FPS.MIN) fps = VIDEO_TRANSCODING_FPS.MIN
+
+    command = command.withFPS(fps)
+  }
+
+  return command
+}
+
+async function buildHLSCommand (command: ffmpeg.FfmpegCommand, options: TranscodeOptions) {
+  const videoPath = getHLSVideoPath(options)
+
+  command = await presetCopy(command)
+
+  command = command.outputOption('-hls_time 4')
+                   .outputOption('-hls_list_size 0')
+                   .outputOption('-hls_playlist_type vod')
+                   .outputOption('-hls_segment_filename ' + videoPath)
+                   .outputOption('-hls_segment_type fmp4')
+                   .outputOption('-f hls')
+                   .outputOption('-hls_flags single_file')
+
+  return command
+}
+
 function getHLSVideoPath (options: TranscodeOptions) {
   return `${dirname(options.outputPath)}/${options.hlsPlaylist.videoFilename}`
 }
@@ -397,3 +412,10 @@ async function presetH264 (command: ffmpeg.FfmpegCommand, resolution: VideoResol
 
   return localCommand
 }
+
+async function presetCopy (command: ffmpeg.FfmpegCommand): Promise<ffmpeg.FfmpegCommand> {
+  return command
+    .format('mp4')
+    .videoCodec('copy')
+    .audioCodec('copy')
+}