]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/helpers/ffmpeg-utils.ts
Use a single file instead of segments for HLS
[github/Chocobozzz/PeerTube.git] / server / helpers / ffmpeg-utils.ts
index 8b9045038dba412f4dbb54187d1f7c4c9e88accd..133b1b03b0ac75e82afa0e648491b9d01d8c4cb4 100644 (file)
@@ -1,7 +1,7 @@
 import * as ffmpeg from 'fluent-ffmpeg'
-import { join } from 'path'
+import { dirname, join } from 'path'
 import { getTargetBitrate, VideoResolution } from '../../shared/models/videos'
-import { CONFIG, FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers'
+import { CONFIG, FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers/constants'
 import { processImage } from './image-utils'
 import { logger } from './logger'
 import { checkFFmpegEncoders } from '../initializers/checker-before-init'
@@ -29,19 +29,28 @@ function computeResolutionsToTranscode (videoFileHeight: number) {
   return resolutionsEnabled
 }
 
-async function getVideoFileResolution (path: string) {
+async function getVideoFileSize (path: string) {
   const videoStream = await getVideoFileStream(path)
 
   return {
-    videoFileResolution: Math.min(videoStream.height, videoStream.width),
-    isPortraitMode: videoStream.height > videoStream.width
+    width: videoStream.width,
+    height: videoStream.height
+  }
+}
+
+async function getVideoFileResolution (path: string) {
+  const size = await getVideoFileSize(path)
+
+  return {
+    videoFileResolution: Math.min(size.height, size.width),
+    isPortraitMode: size.height > size.width
   }
 }
 
 async function getVideoFileFPS (path: string) {
   const videoStream = await getVideoFileStream(path)
 
-  for (const key of [ 'r_frame_rate' , 'avg_frame_rate' ]) {
+  for (const key of [ 'avg_frame_rate', 'r_frame_rate' ]) {
     const valuesText: string = videoStream[key]
     if (!valuesText) continue
 
@@ -110,8 +119,12 @@ async function generateImageFromVideoFile (fromPath: string, folder: string, ima
 type TranscodeOptions = {
   inputPath: string
   outputPath: string
-  resolution?: VideoResolution
+  resolution: VideoResolution
   isPortraitMode?: boolean
+
+  hlsPlaylist?: {
+    videoFilename: string
+  }
 }
 
 function transcode (options: TranscodeOptions) {
@@ -150,6 +163,18 @@ function transcode (options: TranscodeOptions) {
         command = command.withFPS(fps)
       }
 
+      if (options.hlsPlaylist) {
+        const videoPath = `${dirname(options.outputPath)}/${options.hlsPlaylist.videoFilename}`
+
+        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 })
@@ -166,6 +191,7 @@ function transcode (options: TranscodeOptions) {
 // ---------------------------------------------------------------------------
 
 export {
+  getVideoFileSize,
   getVideoFileResolution,
   getDurationFromVideoFile,
   generateImageFromVideoFile,
@@ -184,7 +210,7 @@ function getVideoFileStream (path: string) {
       if (err) return rej(err)
 
       const videoStream = metadata.streams.find(s => s.codec_type === 'video')
-      if (!videoStream) throw new Error('Cannot find video stream of ' + path)
+      if (!videoStream) return rej(new Error('Cannot find video stream of ' + path))
 
       return res(videoStream)
     })
@@ -328,10 +354,10 @@ async function presetH264 (command: ffmpeg.FfmpegCommand, resolution: VideoResol
     const audioCodecName = parsedAudio.audioStream[ 'codec_name' ]
     let bitrate: number
     if (audio.bitrate[ audioCodecName ]) {
-      bitrate = audio.bitrate[ audioCodecName ](parsedAudio.audioStream[ 'bit_rate' ])
+      localCommand = localCommand.audioCodec('aac')
 
-      if (bitrate === -1) localCommand = localCommand.audioCodec('copy')
-      else if (bitrate !== undefined) localCommand = localCommand.audioBitrate(bitrate)
+      bitrate = audio.bitrate[ audioCodecName ](parsedAudio.audioStream[ 'bit_rate' ])
+      if (bitrate !== undefined && bitrate !== -1) localCommand = localCommand.audioBitrate(bitrate)
     }
   }