+ return JOB_PRIORITY.TRANSCODING + videoUploadedByUser
+}
+
+// ---------------------------------------------------------------------------
+
+async function buildMoveToObjectStorageJob (options: {
+ video: MVideoUUID
+ previousVideoState: VideoState
+ isNewVideo?: boolean // Default true
+}) {
+ const { video, previousVideoState, isNewVideo = true } = options
+
+ await VideoJobInfoModel.increaseOrCreate(video.uuid, 'pendingMove')
+
+ return {
+ type: 'move-to-object-storage' as 'move-to-object-storage',
+ payload: {
+ videoUUID: video.uuid,
+ isNewVideo,
+ previousVideoState
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+async function getVideoDuration (videoId: number | string) {
+ const video = await VideoModel.load(videoId)
+
+ const duration = video.isLive
+ ? undefined
+ : video.duration
+
+ return { duration, isLive: video.isLive }
+}
+
+const getCachedVideoDuration = memoizee(getVideoDuration, {
+ promise: true,
+ max: MEMOIZE_LENGTH.VIDEO_DURATION,
+ maxAge: MEMOIZE_TTL.VIDEO_DURATION
+})
+
+// ---------------------------------------------------------------------------
+
+async function addVideoJobsAfterUpdate (options: {
+ video: MVideoFullLight
+ isNewVideo: boolean
+
+ nameChanged: boolean
+ oldPrivacy: VideoPrivacy
+}) {
+ const { video, nameChanged, oldPrivacy, isNewVideo } = 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,
+ isNewVideo
+ }
+ })
+
+ const wasConfidentialVideo = new Set([ 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)