]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Fix audio sync after saving replay
authorChocobozzz <me@florianbigard.com>
Fri, 6 Nov 2020 08:09:36 +0000 (09:09 +0100)
committerChocobozzz <chocobozzz@cpy.re>
Mon, 9 Nov 2020 14:33:04 +0000 (15:33 +0100)
hls.js seems to not correctly handle audio gaps with fragmented mp4
(but can with a ts playlist)

client/package.json
client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts
client/yarn.lock
server.ts
server/helpers/ffmpeg-utils.ts
server/lib/job-queue/handlers/video-live-ending.ts

index cb6f77166c0f52f16723ec16974d1bd4fe439eb5..152f8445fc7284cb29e0b26770f6e9ac202d4430 100644 (file)
@@ -80,7 +80,7 @@
     "extract-text-webpack-plugin": "4.0.0-beta.0",
     "file-loader": "^6.0.0",
     "focus-visible": "^5.0.2",
-    "hls.js": "^0.14.9",
+    "hls.js": "^0.14.16",
     "html-loader": "^1.0.0",
     "html-webpack-plugin": "^4.0.3",
     "https-browserify": "^1.0.0",
index 18b4a2f3c2e112b38e125b061ed1a02ece256de7..321f7b09f109ad22899b5fd5b3b18f495168e21b 100644 (file)
@@ -93,7 +93,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
   ngOnChanges () {
     if (this.loaded) {
       this.loaded = false
-      this.playlistAdd.reload()
+      if (this.playlistAdd) this.playlistAdd.reload()
     }
 
     this.buildActions()
@@ -277,7 +277,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
         {
           label: $localize`Display live information`,
           handler: ({ video }) => this.showLiveInfoModal(video),
-          isDisplayed: () => this.isVideoLiveInfoAvailable(),
+          isDisplayed: () => this.displayOptions.liveInfo && this.isVideoLiveInfoAvailable(),
           iconName: 'live'
         },
         {
index cdafe14580dae7924f33c6ecb4e10be123e9b682..d3603a4a9101578b5cd255e8779d87394b2a9adb 100644 (file)
@@ -5586,10 +5586,10 @@ hex-color-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
   integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
 
-hls.js@^0.14.9:
-  version "0.14.9"
-  resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-0.14.9.tgz#e85be87d94385ed9947155716578f7c568957d15"
-  integrity sha512-5j1ONTvIzcIxCtg2eafikFbZ3b/9fDhR6u871LmK7jZ44/Qdc2G4xaSBCwcVK61gz7kTyiobaAhB++2M4J58rQ==
+hls.js@^0.14.16:
+  version "0.14.16"
+  resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-0.14.16.tgz#4ff68a1fa7260a43d316270e9bc7f7bdf93c5731"
+  integrity sha512-VACiO99DQFBpflR4fI+6GVHUZn35R0SGGQo0XTDZOm2BUXbeuDHTghTC/k2/3wGln6KBmG8/bXIcDIzDsY2UEg==
   dependencies:
     eventemitter3 "^4.0.3"
     url-toolkit "^2.1.6"
index e2ff6327b517061e906b285d0c98ae7f6f9f71bc..6963bbf235a5b5958d442bbcbff57a7b186f4d80 100644 (file)
--- a/server.ts
+++ b/server.ts
@@ -142,14 +142,14 @@ if (isTestInstance()) {
 }
 
 // For the logger
-morgan.token('remote-addr', req => {
+morgan.token('remote-addr', (req: express.Request) => {
   if (CONFIG.LOG.ANONYMIZE_IP === true || req.get('DNT') === '1') {
     return anonymize(req.ip, 16, 16)
   }
 
   return req.ip
 })
-morgan.token('user-agent', req => {
+morgan.token('user-agent', (req: express.Request) => {
   if (req.get('DNT') === '1') {
     return useragent.parse(req.get('user-agent')).family
   }
index 3b794b8a29144167f996ea4b237536d6b5633dc6..7a54b4642e23fd87d708125b27605b825613f45c 100644 (file)
@@ -1,5 +1,5 @@
 import * as ffmpeg from 'fluent-ffmpeg'
-import { readFile, remove, writeFile } from 'fs-extra'
+import { outputFile, readFile, remove, writeFile } from 'fs-extra'
 import { dirname, join } from 'path'
 import { VideoFileMetadata } from '@shared/models/videos/video-file-metadata'
 import { getMaxBitrate, getTargetBitrate, VideoResolution } from '../../shared/models/videos'
@@ -423,8 +423,14 @@ function runLiveMuxing (rtmpUrl: string, outPath: string, deleteSegments: boolea
 }
 
 async function hlsPlaylistToFragmentedMP4 (hlsDirectory: string, segmentFiles: string[], outputPath: string) {
-  const concatFile = 'concat.txt'
-  const concatFilePath = join(hlsDirectory, concatFile)
+  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')
 
@@ -434,25 +440,25 @@ async function hlsPlaylistToFragmentedMP4 (hlsDirectory: string, segmentFiles: s
   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)
 
-  command.run()
+  return runCommand(command, cleaner)
+}
 
-  function cleaner () {
-    remove(concatFilePath)
-      .catch(err => logger.error('Cannot remove concat file in %s.', hlsDirectory, { err }))
-  }
+async function runCommand (command: ffmpeg.FfmpegCommand, onEnd?: Function) {
+  command.run()
 
   return new Promise<string>((res, rej) => {
     command.on('error', err => {
-      cleaner()
+      if (onEnd) onEnd()
 
       rej(err)
     })
 
     command.on('end', () => {
-      cleaner()
+      if (onEnd) onEnd()
 
       res()
     })
@@ -501,7 +507,7 @@ function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string
     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`)
 
index 2b900998a9c7da05a3927b88a999b9e7d83915a5..3892260c46ca6c3ee827c9a71206e445e06725de 100644 (file)
@@ -70,10 +70,6 @@ async function saveLive (video: MVideo, live: MVideoLive) {
     const segmentFiles = files.filter(f => f.startsWith(shouldStartWith) && f.endsWith('.ts'))
     await hlsPlaylistToFragmentedMP4(hlsDirectory, segmentFiles, mp4TmpPath)
 
-    for (const file of segmentFiles) {
-      await remove(join(hlsDirectory, file))
-    }
-
     if (!duration) {
       duration = await getDurationFromVideoFile(mp4TmpPath)
     }