diff options
author | Chocobozzz <me@florianbigard.com> | 2020-11-06 09:09:36 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2020-11-09 15:33:04 +0100 |
commit | 3bc68dfd6183078fb56b53e24e74f889c85c4ae0 (patch) | |
tree | eac38175bf815227f39bf0327c7399b85b05ad08 /server | |
parent | f8c00564e7e66c7c9d65ea044a4c1485df0e4c7c (diff) | |
download | PeerTube-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.ts | 30 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-live-ending.ts | 4 |
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 @@ | |||
1 | import * as ffmpeg from 'fluent-ffmpeg' | 1 | import * as ffmpeg from 'fluent-ffmpeg' |
2 | import { readFile, remove, writeFile } from 'fs-extra' | 2 | import { outputFile, readFile, remove, writeFile } from 'fs-extra' |
3 | import { dirname, join } from 'path' | 3 | import { dirname, join } from 'path' |
4 | import { VideoFileMetadata } from '@shared/models/videos/video-file-metadata' | 4 | import { VideoFileMetadata } from '@shared/models/videos/video-file-metadata' |
5 | import { getMaxBitrate, getTargetBitrate, VideoResolution } from '../../shared/models/videos' | 5 | import { getMaxBitrate, getTargetBitrate, VideoResolution } from '../../shared/models/videos' |
@@ -423,8 +423,14 @@ function runLiveMuxing (rtmpUrl: string, outPath: string, deleteSegments: boolea | |||
423 | } | 423 | } |
424 | 424 | ||
425 | async function hlsPlaylistToFragmentedMP4 (hlsDirectory: string, segmentFiles: string[], outputPath: string) { | 425 | async 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 () { | 450 | async 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 | } |