From e772bdf14c46701552491dc337a21325c34e1ec2 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 4 Dec 2020 15:29:18 +0100 Subject: [PATCH] Load video in permanent live after last one ended --- .../+videos/+video-watch/video-watch.component.ts | 13 ++++++++++++- server/helpers/ffmpeg-utils.ts | 11 ++++++++--- server/lib/job-queue/handlers/video-live-ending.ts | 14 +++++++++----- server/lib/live-manager.ts | 4 ++-- server/lib/video-transcoding.ts | 9 +++++++-- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/client/src/app/+videos/+video-watch/video-watch.component.ts b/client/src/app/+videos/+video-watch/video-watch.component.ts index 66af9709d..b15de2a79 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.ts +++ b/client/src/app/+videos/+video-watch/video-watch.component.ts @@ -607,6 +607,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy { } }) + this.player.one('ended', () => { + if (this.video.isLive) { + this.video.state.id = VideoState.LIVE_ENDED + } + }) + this.player.on('theaterChange', (_: any, enabled: boolean) => { this.zone.run(() => this.theaterEnabled = enabled) }) @@ -844,7 +850,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy { if (!this.liveVideosSub) { this.liveVideosSub = this.peertubeSocket.getLiveVideosObservable() .subscribe(({ payload }) => { - if (payload.state !== VideoState.PUBLISHED || this.video.state.id !== VideoState.WAITING_FOR_LIVE) return + if (payload.state !== VideoState.PUBLISHED) return + + const videoState = this.video.state.id + if (videoState !== VideoState.WAITING_FOR_LIVE && videoState !== VideoState.LIVE_ENDED) return + + console.log('Loading video after live update.') const videoUUID = this.video.uuid diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index 9d6fe76cb..bf6408d3e 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts @@ -137,6 +137,8 @@ interface HLSTranscodeOptions extends BaseTranscodeOptions { interface HLSFromTSTranscodeOptions extends BaseTranscodeOptions { type: 'hls-from-ts' + isAAC: boolean + hlsPlaylist: { videoFilename: string } @@ -456,9 +458,12 @@ async function buildHLSVODFromTSCommand (command: ffmpeg.FfmpegCommand, options: const videoPath = getHLSVideoPath(options) command.outputOption('-c copy') - // Required for example when copying an AAC stream from an MPEG-TS - // Since it's a bitstream filter, we don't need to reencode the audio - command.outputOption('-bsf:a aac_adtstoasc') + + if (options.isAAC) { + // Required for example when copying an AAC stream from an MPEG-TS + // Since it's a bitstream filter, we don't need to reencode the audio + command.outputOption('-bsf:a aac_adtstoasc') + } addCommonHLSVODCommandOptions(command, videoPath) diff --git a/server/lib/job-queue/handlers/video-live-ending.ts b/server/lib/job-queue/handlers/video-live-ending.ts index 4daf9249b..e10e306a7 100644 --- a/server/lib/job-queue/handlers/video-live-ending.ts +++ b/server/lib/job-queue/handlers/video-live-ending.ts @@ -1,8 +1,9 @@ import * as Bull from 'bull' -import { copy, pathExists, readdir, remove } from 'fs-extra' +import { pathExists, readdir, remove } from 'fs-extra' import { join } from 'path' -import { getDurationFromVideoFile, getVideoFileResolution } from '@server/helpers/ffprobe-utils' +import { ffprobePromise, getAudioStream, getAudioStreamCodec, getDurationFromVideoFile, getVideoFileResolution } from '@server/helpers/ffprobe-utils' import { VIDEO_LIVE } from '@server/initializers/constants' +import { LiveManager } from '@server/lib/live-manager' import { generateVideoMiniature } from '@server/lib/thumbnail' import { publishAndFederateIfNeeded } from '@server/lib/video' import { getHLSDirectory } from '@server/lib/video-paths' @@ -14,7 +15,6 @@ import { VideoStreamingPlaylistModel } from '@server/models/video/video-streamin import { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models' import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models' import { logger } from '../../../helpers/logger' -import { LiveManager } from '@server/lib/live-manager' async function processVideoLiveEnding (job: Bull.Job) { const payload = job.data as VideoLiveEndingPayload @@ -106,13 +106,17 @@ async function saveLive (video: MVideo, live: MVideoLive) { const concatenatedTsFile = LiveManager.Instance.buildConcatenatedName(playlistFile) const concatenatedTsFilePath = join(replayDirectory, concatenatedTsFile) - const { videoFileResolution, isPortraitMode } = await getVideoFileResolution(concatenatedTsFilePath) + const probe = await ffprobePromise(concatenatedTsFilePath) + const { audioStream } = await getAudioStream(concatenatedTsFilePath, probe) + + const { videoFileResolution, isPortraitMode } = await getVideoFileResolution(concatenatedTsFilePath, probe) const outputPath = await generateHlsPlaylistFromTS({ video: videoWithFiles, concatenatedTsFilePath, resolution: videoFileResolution, - isPortraitMode + isPortraitMode, + isAAC: audioStream?.codec_name === 'aac' }) if (!durationDone) { diff --git a/server/lib/live-manager.ts b/server/lib/live-manager.ts index c2dd116a9..ef50e3cdb 100644 --- a/server/lib/live-manager.ts +++ b/server/lib/live-manager.ts @@ -1,7 +1,8 @@ +import * as Bluebird from 'bluebird' import * as chokidar from 'chokidar' import { FfmpegCommand } from 'fluent-ffmpeg' -import { appendFile, copy, ensureDir, readFile, stat } from 'fs-extra' +import { appendFile, ensureDir, readFile, stat } from 'fs-extra' import { basename, join } from 'path' import { isTestInstance } from '@server/helpers/core-utils' import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils' @@ -24,7 +25,6 @@ import { PeerTubeSocket } from './peertube-socket' import { isAbleToUploadVideo } from './user' import { getHLSDirectory } from './video-paths' import { availableEncoders } from './video-transcoding-profiles' -import * as Bluebird from 'bluebird' import memoizee = require('memoizee') diff --git a/server/lib/video-transcoding.ts b/server/lib/video-transcoding.ts index 44ecf4cc9..e7108bd5a 100644 --- a/server/lib/video-transcoding.ts +++ b/server/lib/video-transcoding.ts @@ -169,13 +169,15 @@ async function generateHlsPlaylistFromTS (options: { concatenatedTsFilePath: string resolution: VideoResolution isPortraitMode: boolean + isAAC: boolean }) { return generateHlsPlaylistCommon({ video: options.video, resolution: options.resolution, isPortraitMode: options.isPortraitMode, inputPath: options.concatenatedTsFilePath, - type: 'hls-from-ts' as 'hls-from-ts' + type: 'hls-from-ts' as 'hls-from-ts', + isAAC: options.isAAC }) } @@ -234,9 +236,10 @@ async function generateHlsPlaylistCommon (options: { inputPath: string resolution: VideoResolution copyCodecs?: boolean + isAAC?: boolean isPortraitMode: boolean }) { - const { type, video, inputPath, resolution, copyCodecs, isPortraitMode } = options + const { type, video, inputPath, resolution, copyCodecs, isPortraitMode, isAAC } = options const baseHlsDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid) await ensureDir(join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)) @@ -257,6 +260,8 @@ async function generateHlsPlaylistCommon (options: { copyCodecs, isPortraitMode, + isAAC, + hlsPlaylist: { videoFilename }