aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-11-06 09:09:36 +0100
committerChocobozzz <chocobozzz@cpy.re>2020-11-09 15:33:04 +0100
commit3bc68dfd6183078fb56b53e24e74f889c85c4ae0 (patch)
treeeac38175bf815227f39bf0327c7399b85b05ad08 /server
parentf8c00564e7e66c7c9d65ea044a4c1485df0e4c7c (diff)
downloadPeerTube-3bc68dfd6183078fb56b53e24e74f889c85c4ae0.tar.gz
PeerTube-3bc68dfd6183078fb56b53e24e74f889c85c4ae0.tar.zst
PeerTube-3bc68dfd6183078fb56b53e24e74f889c85c4ae0.zip
Fix audio sync after saving replay
hls.js seems to not correctly handle audio gaps with fragmented mp4 (but can with a ts playlist)
Diffstat (limited to 'server')
-rw-r--r--server/helpers/ffmpeg-utils.ts30
-rw-r--r--server/lib/job-queue/handlers/video-live-ending.ts4
2 files changed, 18 insertions, 16 deletions
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts
index 3b794b8a2..7a54b4642 100644
--- a/server/helpers/ffmpeg-utils.ts
+++ b/server/helpers/ffmpeg-utils.ts
@@ -1,5 +1,5 @@
1import * as ffmpeg from 'fluent-ffmpeg' 1import * as ffmpeg from 'fluent-ffmpeg'
2import { readFile, remove, writeFile } from 'fs-extra' 2import { outputFile, readFile, remove, writeFile } from 'fs-extra'
3import { dirname, join } from 'path' 3import { dirname, join } from 'path'
4import { VideoFileMetadata } from '@shared/models/videos/video-file-metadata' 4import { VideoFileMetadata } from '@shared/models/videos/video-file-metadata'
5import { getMaxBitrate, getTargetBitrate, VideoResolution } from '../../shared/models/videos' 5import { getMaxBitrate, getTargetBitrate, VideoResolution } from '../../shared/models/videos'
@@ -423,8 +423,14 @@ function runLiveMuxing (rtmpUrl: string, outPath: string, deleteSegments: boolea
423} 423}
424 424
425async function hlsPlaylistToFragmentedMP4 (hlsDirectory: string, segmentFiles: string[], outputPath: string) { 425async function hlsPlaylistToFragmentedMP4 (hlsDirectory: string, segmentFiles: string[], outputPath: string) {
426 const concatFile = 'concat.txt' 426 const concatFilePath = join(hlsDirectory, 'concat.txt')
427 const concatFilePath = join(hlsDirectory, concatFile) 427
428 function cleaner () {
429 remove(concatFilePath)
430 .catch(err => logger.error('Cannot remove concat file in %s.', hlsDirectory, { err }))
431 }
432
433 // First concat the ts files to a mp4 file
428 const content = segmentFiles.map(f => 'file ' + f) 434 const content = segmentFiles.map(f => 'file ' + f)
429 .join('\n') 435 .join('\n')
430 436
@@ -434,25 +440,25 @@ async function hlsPlaylistToFragmentedMP4 (hlsDirectory: string, segmentFiles: s
434 command.inputOption('-safe 0') 440 command.inputOption('-safe 0')
435 command.inputOption('-f concat') 441 command.inputOption('-f concat')
436 442
437 command.outputOption('-c copy') 443 command.outputOption('-c:v copy')
444 command.audioFilter('aresample=async=1:first_pts=0')
438 command.output(outputPath) 445 command.output(outputPath)
439 446
440 command.run() 447 return runCommand(command, cleaner)
448}
441 449
442 function cleaner () { 450async function runCommand (command: ffmpeg.FfmpegCommand, onEnd?: Function) {
443 remove(concatFilePath) 451 command.run()
444 .catch(err => logger.error('Cannot remove concat file in %s.', hlsDirectory, { err }))
445 }
446 452
447 return new Promise<string>((res, rej) => { 453 return new Promise<string>((res, rej) => {
448 command.on('error', err => { 454 command.on('error', err => {
449 cleaner() 455 if (onEnd) onEnd()
450 456
451 rej(err) 457 rej(err)
452 }) 458 })
453 459
454 command.on('end', () => { 460 command.on('end', () => {
455 cleaner() 461 if (onEnd) onEnd()
456 462
457 res() 463 res()
458 }) 464 })
@@ -501,7 +507,7 @@ function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string
501 command.outputOption('-hls_flags delete_segments') 507 command.outputOption('-hls_flags delete_segments')
502 } 508 }
503 509
504 command.outputOption(`-hls_segment_filename ${join(outPath, '%v-%d.ts')}`) 510 command.outputOption(`-hls_segment_filename ${join(outPath, '%v-%04d.ts')}`)
505 command.outputOption('-master_pl_name master.m3u8') 511 command.outputOption('-master_pl_name master.m3u8')
506 command.outputOption(`-f hls`) 512 command.outputOption(`-f hls`)
507 513
diff --git a/server/lib/job-queue/handlers/video-live-ending.ts b/server/lib/job-queue/handlers/video-live-ending.ts
index 2b900998a..3892260c4 100644
--- a/server/lib/job-queue/handlers/video-live-ending.ts
+++ b/server/lib/job-queue/handlers/video-live-ending.ts
@@ -70,10 +70,6 @@ async function saveLive (video: MVideo, live: MVideoLive) {
70 const segmentFiles = files.filter(f => f.startsWith(shouldStartWith) && f.endsWith('.ts')) 70 const segmentFiles = files.filter(f => f.startsWith(shouldStartWith) && f.endsWith('.ts'))
71 await hlsPlaylistToFragmentedMP4(hlsDirectory, segmentFiles, mp4TmpPath) 71 await hlsPlaylistToFragmentedMP4(hlsDirectory, segmentFiles, mp4TmpPath)
72 72
73 for (const file of segmentFiles) {
74 await remove(join(hlsDirectory, file))
75 }
76
77 if (!duration) { 73 if (!duration) {
78 duration = await getDurationFromVideoFile(mp4TmpPath) 74 duration = await getDurationFromVideoFile(mp4TmpPath)
79 } 75 }