Load video in permanent live after last one ended
This commit is contained in:
parent
3851e732c4
commit
e772bdf14c
|
@ -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.player.on('theaterChange', (_: any, enabled: boolean) => {
|
||||||
this.zone.run(() => this.theaterEnabled = enabled)
|
this.zone.run(() => this.theaterEnabled = enabled)
|
||||||
})
|
})
|
||||||
|
@ -844,7 +850,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
if (!this.liveVideosSub) {
|
if (!this.liveVideosSub) {
|
||||||
this.liveVideosSub = this.peertubeSocket.getLiveVideosObservable()
|
this.liveVideosSub = this.peertubeSocket.getLiveVideosObservable()
|
||||||
.subscribe(({ payload }) => {
|
.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
|
const videoUUID = this.video.uuid
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,8 @@ interface HLSTranscodeOptions extends BaseTranscodeOptions {
|
||||||
interface HLSFromTSTranscodeOptions extends BaseTranscodeOptions {
|
interface HLSFromTSTranscodeOptions extends BaseTranscodeOptions {
|
||||||
type: 'hls-from-ts'
|
type: 'hls-from-ts'
|
||||||
|
|
||||||
|
isAAC: boolean
|
||||||
|
|
||||||
hlsPlaylist: {
|
hlsPlaylist: {
|
||||||
videoFilename: string
|
videoFilename: string
|
||||||
}
|
}
|
||||||
|
@ -456,9 +458,12 @@ async function buildHLSVODFromTSCommand (command: ffmpeg.FfmpegCommand, options:
|
||||||
const videoPath = getHLSVideoPath(options)
|
const videoPath = getHLSVideoPath(options)
|
||||||
|
|
||||||
command.outputOption('-c copy')
|
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
|
if (options.isAAC) {
|
||||||
command.outputOption('-bsf:a aac_adtstoasc')
|
// 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)
|
addCommonHLSVODCommandOptions(command, videoPath)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import * as Bull from 'bull'
|
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 { 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 { VIDEO_LIVE } from '@server/initializers/constants'
|
||||||
|
import { LiveManager } from '@server/lib/live-manager'
|
||||||
import { generateVideoMiniature } from '@server/lib/thumbnail'
|
import { generateVideoMiniature } from '@server/lib/thumbnail'
|
||||||
import { publishAndFederateIfNeeded } from '@server/lib/video'
|
import { publishAndFederateIfNeeded } from '@server/lib/video'
|
||||||
import { getHLSDirectory } from '@server/lib/video-paths'
|
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 { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models'
|
||||||
import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models'
|
import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models'
|
||||||
import { logger } from '../../../helpers/logger'
|
import { logger } from '../../../helpers/logger'
|
||||||
import { LiveManager } from '@server/lib/live-manager'
|
|
||||||
|
|
||||||
async function processVideoLiveEnding (job: Bull.Job) {
|
async function processVideoLiveEnding (job: Bull.Job) {
|
||||||
const payload = job.data as VideoLiveEndingPayload
|
const payload = job.data as VideoLiveEndingPayload
|
||||||
|
@ -106,13 +106,17 @@ async function saveLive (video: MVideo, live: MVideoLive) {
|
||||||
const concatenatedTsFile = LiveManager.Instance.buildConcatenatedName(playlistFile)
|
const concatenatedTsFile = LiveManager.Instance.buildConcatenatedName(playlistFile)
|
||||||
const concatenatedTsFilePath = join(replayDirectory, concatenatedTsFile)
|
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({
|
const outputPath = await generateHlsPlaylistFromTS({
|
||||||
video: videoWithFiles,
|
video: videoWithFiles,
|
||||||
concatenatedTsFilePath,
|
concatenatedTsFilePath,
|
||||||
resolution: videoFileResolution,
|
resolution: videoFileResolution,
|
||||||
isPortraitMode
|
isPortraitMode,
|
||||||
|
isAAC: audioStream?.codec_name === 'aac'
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!durationDone) {
|
if (!durationDone) {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
|
import * as Bluebird from 'bluebird'
|
||||||
import * as chokidar from 'chokidar'
|
import * as chokidar from 'chokidar'
|
||||||
import { FfmpegCommand } from 'fluent-ffmpeg'
|
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 { basename, join } from 'path'
|
||||||
import { isTestInstance } from '@server/helpers/core-utils'
|
import { isTestInstance } from '@server/helpers/core-utils'
|
||||||
import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils'
|
import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils'
|
||||||
|
@ -24,7 +25,6 @@ import { PeerTubeSocket } from './peertube-socket'
|
||||||
import { isAbleToUploadVideo } from './user'
|
import { isAbleToUploadVideo } from './user'
|
||||||
import { getHLSDirectory } from './video-paths'
|
import { getHLSDirectory } from './video-paths'
|
||||||
import { availableEncoders } from './video-transcoding-profiles'
|
import { availableEncoders } from './video-transcoding-profiles'
|
||||||
import * as Bluebird from 'bluebird'
|
|
||||||
|
|
||||||
import memoizee = require('memoizee')
|
import memoizee = require('memoizee')
|
||||||
|
|
||||||
|
|
|
@ -169,13 +169,15 @@ async function generateHlsPlaylistFromTS (options: {
|
||||||
concatenatedTsFilePath: string
|
concatenatedTsFilePath: string
|
||||||
resolution: VideoResolution
|
resolution: VideoResolution
|
||||||
isPortraitMode: boolean
|
isPortraitMode: boolean
|
||||||
|
isAAC: boolean
|
||||||
}) {
|
}) {
|
||||||
return generateHlsPlaylistCommon({
|
return generateHlsPlaylistCommon({
|
||||||
video: options.video,
|
video: options.video,
|
||||||
resolution: options.resolution,
|
resolution: options.resolution,
|
||||||
isPortraitMode: options.isPortraitMode,
|
isPortraitMode: options.isPortraitMode,
|
||||||
inputPath: options.concatenatedTsFilePath,
|
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
|
inputPath: string
|
||||||
resolution: VideoResolution
|
resolution: VideoResolution
|
||||||
copyCodecs?: boolean
|
copyCodecs?: boolean
|
||||||
|
isAAC?: boolean
|
||||||
isPortraitMode: 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)
|
const baseHlsDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
|
||||||
await ensureDir(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,
|
copyCodecs,
|
||||||
isPortraitMode,
|
isPortraitMode,
|
||||||
|
|
||||||
|
isAAC,
|
||||||
|
|
||||||
hlsPlaylist: {
|
hlsPlaylist: {
|
||||||
videoFilename
|
videoFilename
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue