diff options
author | Chocobozzz <me@florianbigard.com> | 2020-12-04 15:29:18 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2020-12-04 15:38:32 +0100 |
commit | e772bdf14c46701552491dc337a21325c34e1ec2 (patch) | |
tree | ce50d56a3433306beeb8c4c0cd711636bac242ee | |
parent | 3851e732c4b1da0bc0c40a46ed5a89d93cdc5389 (diff) | |
download | PeerTube-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.ts | 13 | ||||
-rw-r--r-- | server/helpers/ffmpeg-utils.ts | 11 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-live-ending.ts | 14 | ||||
-rw-r--r-- | server/lib/live-manager.ts | 4 | ||||
-rw-r--r-- | 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 { | |||
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 { | |||
137 | interface HLSFromTSTranscodeOptions extends BaseTranscodeOptions { | 137 | interface 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 @@ | |||
1 | import * as Bull from 'bull' | 1 | import * as Bull from 'bull' |
2 | import { copy, pathExists, readdir, remove } from 'fs-extra' | 2 | import { pathExists, readdir, remove } from 'fs-extra' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { getDurationFromVideoFile, getVideoFileResolution } from '@server/helpers/ffprobe-utils' | 4 | import { ffprobePromise, getAudioStream, getAudioStreamCodec, getDurationFromVideoFile, getVideoFileResolution } from '@server/helpers/ffprobe-utils' |
5 | import { VIDEO_LIVE } from '@server/initializers/constants' | 5 | import { VIDEO_LIVE } from '@server/initializers/constants' |
6 | import { LiveManager } from '@server/lib/live-manager' | ||
6 | import { generateVideoMiniature } from '@server/lib/thumbnail' | 7 | import { generateVideoMiniature } from '@server/lib/thumbnail' |
7 | import { publishAndFederateIfNeeded } from '@server/lib/video' | 8 | import { publishAndFederateIfNeeded } from '@server/lib/video' |
8 | import { getHLSDirectory } from '@server/lib/video-paths' | 9 | import { getHLSDirectory } from '@server/lib/video-paths' |
@@ -14,7 +15,6 @@ import { VideoStreamingPlaylistModel } from '@server/models/video/video-streamin | |||
14 | import { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models' | 15 | import { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models' |
15 | import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models' | 16 | import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models' |
16 | import { logger } from '../../../helpers/logger' | 17 | import { logger } from '../../../helpers/logger' |
17 | import { LiveManager } from '@server/lib/live-manager' | ||
18 | 18 | ||
19 | async function processVideoLiveEnding (job: Bull.Job) { | 19 | async 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 | ||
2 | import * as Bluebird from 'bluebird' | ||
2 | import * as chokidar from 'chokidar' | 3 | import * as chokidar from 'chokidar' |
3 | import { FfmpegCommand } from 'fluent-ffmpeg' | 4 | import { FfmpegCommand } from 'fluent-ffmpeg' |
4 | import { appendFile, copy, ensureDir, readFile, stat } from 'fs-extra' | 5 | import { appendFile, ensureDir, readFile, stat } from 'fs-extra' |
5 | import { basename, join } from 'path' | 6 | import { basename, join } from 'path' |
6 | import { isTestInstance } from '@server/helpers/core-utils' | 7 | import { isTestInstance } from '@server/helpers/core-utils' |
7 | import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils' | 8 | import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils' |
@@ -24,7 +25,6 @@ import { PeerTubeSocket } from './peertube-socket' | |||
24 | import { isAbleToUploadVideo } from './user' | 25 | import { isAbleToUploadVideo } from './user' |
25 | import { getHLSDirectory } from './video-paths' | 26 | import { getHLSDirectory } from './video-paths' |
26 | import { availableEncoders } from './video-transcoding-profiles' | 27 | import { availableEncoders } from './video-transcoding-profiles' |
27 | import * as Bluebird from 'bluebird' | ||
28 | 28 | ||
29 | import memoizee = require('memoizee') | 29 | import 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 | } |