+// ---------------------------------------------------------------------------
+
+export async function createVideoStudioJob (options: {
+ video: MVideo
+ user: MUser
+ payload: VideoStudioEditionPayload
+}) {
+ const { video, user, payload } = options
+
+ const priority = await getTranscodingJobPriority({ user, type: 'studio', fallback: 0 })
+
+ if (CONFIG.VIDEO_STUDIO.REMOTE_RUNNERS.ENABLED) {
+ await new VideoStudioTranscodingJobHandler().create({ video, tasks: payload.tasks, priority })
+ return
+ }
+
+ await JobQueue.Instance.createJob({ type: 'video-studio-edition', payload, priority })
+}
+
+export async function onVideoStudioEnded (options: {
+ editionResultPath: string
+ tasks: VideoStudioTaskPayload[]
+ video: MVideoFullLight
+}) {
+ const { video, tasks, editionResultPath } = options
+
+ const newFile = await buildNewFile({ path: editionResultPath, mode: 'web-video' })
+ newFile.videoId = video.id
+
+ const outputPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, newFile)
+ await move(editionResultPath, outputPath)
+
+ await safeCleanupStudioTMPFiles(tasks)
+
+ await createTorrentAndSetInfoHashFromPath(video, newFile, outputPath)
+ await removeAllFiles(video, newFile)
+
+ await newFile.save()
+
+ video.duration = await getVideoStreamDuration(outputPath)
+ await video.save()
+
+ await federateVideoIfNeeded(video, false, undefined)
+
+ const user = await UserModel.loadByVideoId(video.id)
+
+ await createOptimizeOrMergeAudioJobs({ video, videoFile: newFile, isNewVideo: false, user, videoFileAlreadyLocked: false })
+}
+
+// ---------------------------------------------------------------------------
+// Private
+// ---------------------------------------------------------------------------
+
+async function removeAllFiles (video: MVideoWithAllFiles, webTorrentFileException: MVideoFile) {
+ await removeHLSPlaylist(video)
+
+ for (const file of video.VideoFiles) {
+ if (file.id === webTorrentFileException.id) continue
+
+ await removeWebTorrentFile(video, file.id)
+ }