2024-02-12 10:47:52 +01:00
|
|
|
import { ManageVideoTorrentPayload, VideoPrivacy, VideoPrivacyType, VideoState, VideoStateType } from '@peertube/peertube-models'
|
|
|
|
import { CONFIG } from '@server/initializers/config.js'
|
|
|
|
import { VideoJobInfoModel } from '@server/models/video/video-job-info.js'
|
|
|
|
import { MVideo, MVideoFile, MVideoFullLight, MVideoUUID } from '@server/types/models/index.js'
|
|
|
|
import { CreateJobArgument, CreateJobOptions, JobQueue } from './job-queue/job-queue.js'
|
2024-06-13 09:23:12 +02:00
|
|
|
import { createTranscriptionTaskIfNeeded } from './video-captions.js'
|
2024-02-12 10:47:52 +01:00
|
|
|
import { moveFilesIfPrivacyChanged } from './video-privacy.js'
|
|
|
|
|
|
|
|
export async function buildMoveJob (options: {
|
|
|
|
video: MVideoUUID
|
|
|
|
previousVideoState: VideoStateType
|
|
|
|
type: 'move-to-object-storage' | 'move-to-file-system'
|
|
|
|
isNewVideo?: boolean // Default true
|
|
|
|
}) {
|
|
|
|
const { video, previousVideoState, isNewVideo = true, type } = options
|
|
|
|
|
|
|
|
await VideoJobInfoModel.increaseOrCreate(video.uuid, 'pendingMove')
|
|
|
|
|
|
|
|
return {
|
|
|
|
type,
|
|
|
|
payload: {
|
|
|
|
videoUUID: video.uuid,
|
|
|
|
isNewVideo,
|
|
|
|
previousVideoState
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function buildStoryboardJobIfNeeded (options: {
|
|
|
|
video: MVideo
|
|
|
|
federate: boolean
|
|
|
|
}) {
|
|
|
|
const { video, federate } = options
|
|
|
|
|
|
|
|
if (CONFIG.STORYBOARDS.ENABLED) {
|
|
|
|
return {
|
|
|
|
type: 'generate-video-storyboard' as 'generate-video-storyboard',
|
|
|
|
payload: {
|
|
|
|
videoUUID: video.uuid,
|
|
|
|
federate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (federate === true) {
|
|
|
|
return {
|
|
|
|
type: 'federate-video' as 'federate-video',
|
|
|
|
payload: {
|
|
|
|
videoUUID: video.uuid,
|
|
|
|
isNewVideoForFederation: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function addVideoJobsAfterCreation (options: {
|
|
|
|
video: MVideo
|
|
|
|
videoFile: MVideoFile
|
2024-06-13 09:23:12 +02:00
|
|
|
generateTranscription: boolean
|
2024-02-12 10:47:52 +01:00
|
|
|
}) {
|
2024-06-13 09:23:12 +02:00
|
|
|
const { video, videoFile, generateTranscription } = options
|
2024-02-12 10:47:52 +01:00
|
|
|
|
|
|
|
const jobs: (CreateJobArgument & CreateJobOptions)[] = [
|
|
|
|
{
|
|
|
|
type: 'manage-video-torrent' as 'manage-video-torrent',
|
|
|
|
payload: {
|
|
|
|
videoId: video.id,
|
|
|
|
videoFileId: videoFile.id,
|
|
|
|
action: 'create'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
buildStoryboardJobIfNeeded({ video, federate: false }),
|
|
|
|
|
|
|
|
{
|
|
|
|
type: 'notify',
|
|
|
|
payload: {
|
|
|
|
action: 'new-video',
|
|
|
|
videoUUID: video.uuid
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
type: 'federate-video' as 'federate-video',
|
|
|
|
payload: {
|
|
|
|
videoUUID: video.uuid,
|
|
|
|
isNewVideoForFederation: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
if (video.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE) {
|
|
|
|
jobs.push(await buildMoveJob({ video, previousVideoState: undefined, type: 'move-to-object-storage' }))
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video.state === VideoState.TO_TRANSCODE) {
|
|
|
|
jobs.push({
|
|
|
|
type: 'transcoding-job-builder' as 'transcoding-job-builder',
|
|
|
|
payload: {
|
|
|
|
videoUUID: video.uuid,
|
|
|
|
optimizeJob: {
|
|
|
|
isNewVideo: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-06-13 09:23:12 +02:00
|
|
|
await JobQueue.Instance.createSequentialJobFlow(...jobs)
|
|
|
|
|
|
|
|
if (generateTranscription === true && CONFIG.VIDEO_TRANSCRIPTION.ENABLED === true) {
|
|
|
|
await createTranscriptionTaskIfNeeded(video)
|
|
|
|
}
|
2024-02-12 10:47:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export async function addVideoJobsAfterUpdate (options: {
|
|
|
|
video: MVideoFullLight
|
|
|
|
isNewVideoForFederation: boolean
|
|
|
|
|
|
|
|
nameChanged: boolean
|
|
|
|
oldPrivacy: VideoPrivacyType
|
|
|
|
}) {
|
|
|
|
const { video, nameChanged, oldPrivacy, isNewVideoForFederation } = options
|
|
|
|
const jobs: CreateJobArgument[] = []
|
|
|
|
|
|
|
|
const filePathChanged = await moveFilesIfPrivacyChanged(video, oldPrivacy)
|
|
|
|
|
|
|
|
if (!video.isLive && (nameChanged || filePathChanged)) {
|
|
|
|
for (const file of (video.VideoFiles || [])) {
|
|
|
|
const payload: ManageVideoTorrentPayload = { action: 'update-metadata', videoId: video.id, videoFileId: file.id }
|
|
|
|
|
|
|
|
jobs.push({ type: 'manage-video-torrent', payload })
|
|
|
|
}
|
|
|
|
|
|
|
|
const hls = video.getHLSPlaylist()
|
|
|
|
|
|
|
|
for (const file of (hls?.VideoFiles || [])) {
|
|
|
|
const payload: ManageVideoTorrentPayload = { action: 'update-metadata', streamingPlaylistId: hls.id, videoFileId: file.id }
|
|
|
|
|
|
|
|
jobs.push({ type: 'manage-video-torrent', payload })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
jobs.push({
|
|
|
|
type: 'federate-video',
|
|
|
|
payload: {
|
|
|
|
videoUUID: video.uuid,
|
|
|
|
isNewVideoForFederation
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const wasConfidentialVideo = new Set<VideoPrivacyType>([
|
|
|
|
VideoPrivacy.PRIVATE,
|
|
|
|
VideoPrivacy.UNLISTED,
|
|
|
|
VideoPrivacy.INTERNAL
|
|
|
|
]).has(oldPrivacy)
|
|
|
|
|
|
|
|
if (wasConfidentialVideo) {
|
|
|
|
jobs.push({
|
|
|
|
type: 'notify',
|
|
|
|
payload: {
|
|
|
|
action: 'new-video',
|
|
|
|
videoUUID: video.uuid
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return JobQueue.Instance.createSequentialJobFlow(...jobs)
|
|
|
|
}
|