mirror of https://github.com/Chocobozzz/PeerTube
Fix audio sync after saving replay
hls.js seems to not correctly handle audio gaps with fragmented mp4 (but can with a ts playlist)pull/3284/head
parent
f8c00564e7
commit
3bc68dfd61
|
@ -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",
|
||||
|
|
|
@ -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'
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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`)
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue