aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-12-04 15:29:18 +0100
committerChocobozzz <me@florianbigard.com>2020-12-04 15:38:32 +0100
commite772bdf14c46701552491dc337a21325c34e1ec2 (patch)
treece50d56a3433306beeb8c4c0cd711636bac242ee
parent3851e732c4b1da0bc0c40a46ed5a89d93cdc5389 (diff)
downloadPeerTube-e772bdf14c46701552491dc337a21325c34e1ec2.tar.gz
PeerTube-e772bdf14c46701552491dc337a21325c34e1ec2.tar.zst
PeerTube-e772bdf14c46701552491dc337a21325c34e1ec2.zip
Load video in permanent live after last one ended
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.component.ts13
-rw-r--r--server/helpers/ffmpeg-utils.ts11
-rw-r--r--server/lib/job-queue/handlers/video-live-ending.ts14
-rw-r--r--server/lib/live-manager.ts4
-rw-r--r--server/lib/video-transcoding.ts9
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 {
607 } 607 }
608 }) 608 })
609 609
610 this.player.one('ended', () => {
611 if (this.video.isLive) {
612 this.video.state.id = VideoState.LIVE_ENDED
613 }
614 })
615
610 this.player.on('theaterChange', (_: any, enabled: boolean) => { 616 this.player.on('theaterChange', (_: any, enabled: boolean) => {
611 this.zone.run(() => this.theaterEnabled = enabled) 617 this.zone.run(() => this.theaterEnabled = enabled)
612 }) 618 })
@@ -844,7 +850,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
844 if (!this.liveVideosSub) { 850 if (!this.liveVideosSub) {
845 this.liveVideosSub = this.peertubeSocket.getLiveVideosObservable() 851 this.liveVideosSub = this.peertubeSocket.getLiveVideosObservable()
846 .subscribe(({ payload }) => { 852 .subscribe(({ payload }) => {
847 if (payload.state !== VideoState.PUBLISHED || this.video.state.id !== VideoState.WAITING_FOR_LIVE) return 853 if (payload.state !== VideoState.PUBLISHED) return
854
855 const videoState = this.video.state.id
856 if (videoState !== VideoState.WAITING_FOR_LIVE && videoState !== VideoState.LIVE_ENDED) return
857
858 console.log('Loading video after live update.')
848 859
849 const videoUUID = this.video.uuid 860 const videoUUID = this.video.uuid
850 861
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 {
137interface HLSFromTSTranscodeOptions extends BaseTranscodeOptions { 137interface HLSFromTSTranscodeOptions extends BaseTranscodeOptions {
138 type: 'hls-from-ts' 138 type: 'hls-from-ts'
139 139
140 isAAC: boolean
141
140 hlsPlaylist: { 142 hlsPlaylist: {
141 videoFilename: string 143 videoFilename: string
142 } 144 }
@@ -456,9 +458,12 @@ async function buildHLSVODFromTSCommand (command: ffmpeg.FfmpegCommand, options:
456 const videoPath = getHLSVideoPath(options) 458 const videoPath = getHLSVideoPath(options)
457 459
458 command.outputOption('-c copy') 460 command.outputOption('-c copy')
459 // Required for example when copying an AAC stream from an MPEG-TS 461
460 // Since it's a bitstream filter, we don't need to reencode the audio 462 if (options.isAAC) {
461 command.outputOption('-bsf:a aac_adtstoasc') 463 // Required for example when copying an AAC stream from an MPEG-TS
464 // Since it's a bitstream filter, we don't need to reencode the audio
465 command.outputOption('-bsf:a aac_adtstoasc')
466 }
462 467
463 addCommonHLSVODCommandOptions(command, videoPath) 468 addCommonHLSVODCommandOptions(command, videoPath)
464 469
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 @@
1import * as Bull from 'bull' 1import * as Bull from 'bull'
2import { copy, pathExists, readdir, remove } from 'fs-extra' 2import { pathExists, readdir, remove } from 'fs-extra'
3import { join } from 'path' 3import { join } from 'path'
4import { getDurationFromVideoFile, getVideoFileResolution } from '@server/helpers/ffprobe-utils' 4import { ffprobePromise, getAudioStream, getAudioStreamCodec, getDurationFromVideoFile, getVideoFileResolution } from '@server/helpers/ffprobe-utils'
5import { VIDEO_LIVE } from '@server/initializers/constants' 5import { VIDEO_LIVE } from '@server/initializers/constants'
6import { LiveManager } from '@server/lib/live-manager'
6import { generateVideoMiniature } from '@server/lib/thumbnail' 7import { generateVideoMiniature } from '@server/lib/thumbnail'
7import { publishAndFederateIfNeeded } from '@server/lib/video' 8import { publishAndFederateIfNeeded } from '@server/lib/video'
8import { getHLSDirectory } from '@server/lib/video-paths' 9import { getHLSDirectory } from '@server/lib/video-paths'
@@ -14,7 +15,6 @@ import { VideoStreamingPlaylistModel } from '@server/models/video/video-streamin
14import { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models' 15import { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models'
15import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models' 16import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models'
16import { logger } from '../../../helpers/logger' 17import { logger } from '../../../helpers/logger'
17import { LiveManager } from '@server/lib/live-manager'
18 18
19async function processVideoLiveEnding (job: Bull.Job) { 19async function processVideoLiveEnding (job: Bull.Job) {
20 const payload = job.data as VideoLiveEndingPayload 20 const payload = job.data as VideoLiveEndingPayload
@@ -106,13 +106,17 @@ async function saveLive (video: MVideo, live: MVideoLive) {
106 const concatenatedTsFile = LiveManager.Instance.buildConcatenatedName(playlistFile) 106 const concatenatedTsFile = LiveManager.Instance.buildConcatenatedName(playlistFile)
107 const concatenatedTsFilePath = join(replayDirectory, concatenatedTsFile) 107 const concatenatedTsFilePath = join(replayDirectory, concatenatedTsFile)
108 108
109 const { videoFileResolution, isPortraitMode } = await getVideoFileResolution(concatenatedTsFilePath) 109 const probe = await ffprobePromise(concatenatedTsFilePath)
110 const { audioStream } = await getAudioStream(concatenatedTsFilePath, probe)
111
112 const { videoFileResolution, isPortraitMode } = await getVideoFileResolution(concatenatedTsFilePath, probe)
110 113
111 const outputPath = await generateHlsPlaylistFromTS({ 114 const outputPath = await generateHlsPlaylistFromTS({
112 video: videoWithFiles, 115 video: videoWithFiles,
113 concatenatedTsFilePath, 116 concatenatedTsFilePath,
114 resolution: videoFileResolution, 117 resolution: videoFileResolution,
115 isPortraitMode 118 isPortraitMode,
119 isAAC: audioStream?.codec_name === 'aac'
116 }) 120 })
117 121
118 if (!durationDone) { 122 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 @@
1 1
2import * as Bluebird from 'bluebird'
2import * as chokidar from 'chokidar' 3import * as chokidar from 'chokidar'
3import { FfmpegCommand } from 'fluent-ffmpeg' 4import { FfmpegCommand } from 'fluent-ffmpeg'
4import { appendFile, copy, ensureDir, readFile, stat } from 'fs-extra' 5import { appendFile, ensureDir, readFile, stat } from 'fs-extra'
5import { basename, join } from 'path' 6import { basename, join } from 'path'
6import { isTestInstance } from '@server/helpers/core-utils' 7import { isTestInstance } from '@server/helpers/core-utils'
7import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils' 8import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils'
@@ -24,7 +25,6 @@ import { PeerTubeSocket } from './peertube-socket'
24import { isAbleToUploadVideo } from './user' 25import { isAbleToUploadVideo } from './user'
25import { getHLSDirectory } from './video-paths' 26import { getHLSDirectory } from './video-paths'
26import { availableEncoders } from './video-transcoding-profiles' 27import { availableEncoders } from './video-transcoding-profiles'
27import * as Bluebird from 'bluebird'
28 28
29import memoizee = require('memoizee') 29import memoizee = require('memoizee')
30 30
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: {
169 concatenatedTsFilePath: string 169 concatenatedTsFilePath: string
170 resolution: VideoResolution 170 resolution: VideoResolution
171 isPortraitMode: boolean 171 isPortraitMode: boolean
172 isAAC: boolean
172}) { 173}) {
173 return generateHlsPlaylistCommon({ 174 return generateHlsPlaylistCommon({
174 video: options.video, 175 video: options.video,
175 resolution: options.resolution, 176 resolution: options.resolution,
176 isPortraitMode: options.isPortraitMode, 177 isPortraitMode: options.isPortraitMode,
177 inputPath: options.concatenatedTsFilePath, 178 inputPath: options.concatenatedTsFilePath,
178 type: 'hls-from-ts' as 'hls-from-ts' 179 type: 'hls-from-ts' as 'hls-from-ts',
180 isAAC: options.isAAC
179 }) 181 })
180} 182}
181 183
@@ -234,9 +236,10 @@ async function generateHlsPlaylistCommon (options: {
234 inputPath: string 236 inputPath: string
235 resolution: VideoResolution 237 resolution: VideoResolution
236 copyCodecs?: boolean 238 copyCodecs?: boolean
239 isAAC?: boolean
237 isPortraitMode: boolean 240 isPortraitMode: boolean
238}) { 241}) {
239 const { type, video, inputPath, resolution, copyCodecs, isPortraitMode } = options 242 const { type, video, inputPath, resolution, copyCodecs, isPortraitMode, isAAC } = options
240 243
241 const baseHlsDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid) 244 const baseHlsDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
242 await ensureDir(join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)) 245 await ensureDir(join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid))
@@ -257,6 +260,8 @@ async function generateHlsPlaylistCommon (options: {
257 copyCodecs, 260 copyCodecs,
258 isPortraitMode, 261 isPortraitMode,
259 262
263 isAAC,
264
260 hlsPlaylist: { 265 hlsPlaylist: {
261 videoFilename 266 videoFilename
262 } 267 }