HLS is only supported by ffmpeg 4
authorChocobozzz <me@florianbigard.com>
Mon, 11 Feb 2019 16:20:28 +0000 (17:20 +0100)
committerChocobozzz <me@florianbigard.com>
Tue, 12 Feb 2019 10:14:36 +0000 (11:14 +0100)
Because of https://github.com/FFmpeg/FFmpeg/commit/c8f625f52998faa9bf0fe22701f1684e51edfc07

.gitignore
config/default.yaml
config/production.yaml.example
server/helpers/ffmpeg-utils.ts

index a31da70a965534b13e252db166f8c9b95fd85e30..6810045270dff15cf1e1ca0b0250f94f2e9323f8 100644 (file)
@@ -17,6 +17,7 @@
 /config/local*
 /ffmpeg/
 /ffmpeg-4/
+/ffmpeg-3/
 /thumbnails/
 /torrents/
 /videos/
index 5a83b271e32252d151ab83ed0c2bbe5a7d09fe29..7af615a8206e95208814580b5beea2be199bf1b8 100644 (file)
@@ -140,12 +140,12 @@ transcoding:
     720p: false
     1080p: false
   # /!\ EXPERIMENTAL /!\
-  # /!\ Requires ffmpeg >= 3.4
-  # Generate HLS playlist/segments. Better playback than with WebTorrent:
+  # /!\ Requires ffmpeg >= 4
+  # Generate HLS playlists and fragmented MP4 files. Better playback than with WebTorrent:
   #     * Resolution change is smoother
   #     * Faster playback in particular with long videos
   #     * More stable playback (less bugs/infinite loading)
-  # /!\ Multiply videos storage by two /!\
+  # /!\ Multiply videos storage by 2 /!\
   hls:
     enabled: false
 
index c54e1a516d71cfecdaf8fa0242862721961df6dc..413e3c478f9ad53d39dbb96b2344d2bcbb252bf3 100644 (file)
@@ -153,12 +153,12 @@ transcoding:
     720p: false
     1080p: false
   # /!\ EXPERIMENTAL /!\
-  # /!\ Requires ffmpeg >= 3.4
-  # Generate HLS playlist/segments. Better playback than with WebTorrent:
+  # /!\ Requires ffmpeg >= 4
+  # Generate HLS playlists and fragmented MP4 files. Better playback than with WebTorrent:
   #     * Resolution change is smoother
   #     * Faster playback in particular with long videos
   #     * More stable playback (less bugs/infinite loading)
-  # /!\ Multiply videos storage by two /!\
+  # /!\ Multiply videos storage by 2 /!\
   hls:
     enabled: false
 
index 133b1b03b0ac75e82afa0e648491b9d01d8c4cb4..b6b64de3f604ba8240499cd650068325ee12f213 100644 (file)
@@ -5,7 +5,7 @@ import { CONFIG, FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers/cons
 import { processImage } from './image-utils'
 import { logger } from './logger'
 import { checkFFmpegEncoders } from '../initializers/checker-before-init'
-import { remove } from 'fs-extra'
+import { remove, readFile, writeFile } from 'fs-extra'
 
 function computeResolutionsToTranscode (videoFileHeight: number) {
   const resolutionsEnabled: number[] = []
@@ -164,7 +164,7 @@ function transcode (options: TranscodeOptions) {
       }
 
       if (options.hlsPlaylist) {
-        const videoPath = `${dirname(options.outputPath)}/${options.hlsPlaylist.videoFilename}`
+        const videoPath = getHLSVideoPath(options)
 
         command = command.outputOption('-hls_time 4')
                          .outputOption('-hls_list_size 0')
@@ -180,7 +180,11 @@ function transcode (options: TranscodeOptions) {
           logger.error('Error in transcoding job.', { stdout, stderr })
           return rej(err)
         })
-        .on('end', res)
+        .on('end', () => {
+          return onTranscodingSuccess(options)
+            .then(() => res())
+            .catch(err => rej(err))
+        })
         .run()
     } catch (err) {
       return rej(err)
@@ -204,6 +208,25 @@ export {
 
 // ---------------------------------------------------------------------------
 
+function getHLSVideoPath (options: TranscodeOptions) {
+  return `${dirname(options.outputPath)}/${options.hlsPlaylist.videoFilename}`
+}
+
+async function onTranscodingSuccess (options: TranscodeOptions) {
+  if (!options.hlsPlaylist) return
+
+  // Fix wrong mapping with some ffmpeg versions
+  const fileContent = await readFile(options.outputPath)
+
+  const videoFileName = options.hlsPlaylist.videoFilename
+  const videoFilePath = getHLSVideoPath(options)
+
+  const newContent = fileContent.toString()
+                                .replace(`#EXT-X-MAP:URI="${videoFilePath}",`, `#EXT-X-MAP:URI="${videoFileName}",`)
+
+  await writeFile(options.outputPath, newContent)
+}
+
 function getVideoFileStream (path: string) {
   return new Promise<any>((res, rej) => {
     ffmpeg.ffprobe(path, (err, metadata) => {