65 lines
2.5 KiB
TypeScript
65 lines
2.5 KiB
TypeScript
import { LiveVideoStartPayload } from '@peertube/peertube-models'
|
|
import { logger, loggerTagsFactory } from '@server/helpers/logger.js'
|
|
import { startScheduledLiveSession } from '@server/controllers/api/live-stream.js'
|
|
import { CONFIG } from '@server/initializers/config.js'
|
|
import { LiveVideoProcessManager } from '@server/lib/live-videos/live-video-process-manager.js'
|
|
import { LIVE_VIDEO_START_LEAD_TIME_MS } from '@server/lib/live-videos/shared.js'
|
|
import { LiveVideoModel, LiveVideoStatus } from '@server/models/video/live-video.js'
|
|
import { Job } from 'bullmq'
|
|
import { setTimeout as wait } from 'node:timers/promises'
|
|
|
|
const lTags = loggerTagsFactory('jobs', 'live-video-start')
|
|
const LIVE_VIDEO_START_POLL_MS = 5_000
|
|
|
|
export async function processLiveVideoStart (job: Job) {
|
|
const payload = job.data as LiveVideoStartPayload
|
|
let liveVideo: LiveVideoModel
|
|
|
|
while (true) {
|
|
const currentLiveVideo = await LiveVideoModel.loadById(payload.liveVideoId)
|
|
if (!currentLiveVideo) {
|
|
logger.warn('Cannot find live video %d for scheduled start job %s.', payload.liveVideoId, job.id, lTags())
|
|
return
|
|
}
|
|
|
|
if (currentLiveVideo.status !== LiveVideoStatus.SCHEDULED) {
|
|
logger.info('Skipping scheduled start of live video %d because status is %s.', currentLiveVideo.id, currentLiveVideo.status, lTags())
|
|
return
|
|
}
|
|
|
|
const now = Date.now()
|
|
const startAt = currentLiveVideo.startTime.getTime()
|
|
const endAt = currentLiveVideo.endTime.getTime()
|
|
if (endAt <= now) {
|
|
logger.info('Skipping scheduled start of live video %d because it is already finished.', currentLiveVideo.id, lTags())
|
|
return
|
|
}
|
|
|
|
const launchAt = startAt - LIVE_VIDEO_START_LEAD_TIME_MS
|
|
const waitMs = launchAt - now
|
|
if (waitMs <= 0) {
|
|
liveVideo = currentLiveVideo
|
|
break
|
|
}
|
|
|
|
await wait(Math.min(waitMs, LIVE_VIDEO_START_POLL_MS))
|
|
}
|
|
|
|
if (CONFIG.LIVE.ENABLE_SOURCE_START) {
|
|
await LiveVideoProcessManager.Instance.start(liveVideo)
|
|
} else {
|
|
logger.info('Skipping source-side scheduled live start for live video %d because live.enable_source_start is disabled.', liveVideo.id, lTags())
|
|
}
|
|
|
|
const sinkWaitMs = liveVideo.startTime.getTime() - Date.now()
|
|
if (sinkWaitMs > 0) {
|
|
await wait(sinkWaitMs)
|
|
}
|
|
|
|
if (CONFIG.LIVE.ENABLE_SINK_START) {
|
|
await startScheduledLiveSession(liveVideo.targetCamera, { keepAliveUntil: liveVideo.endTime })
|
|
} else {
|
|
logger.info('Skipping sink-side scheduled live start for live video %d because live.enable_sink_start is disabled.', liveVideo.id, lTags())
|
|
}
|
|
}
|