aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/video-studio.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/video-studio.ts')
-rw-r--r--server/lib/video-studio.ts109
1 files changed, 95 insertions, 14 deletions
diff --git a/server/lib/video-studio.ts b/server/lib/video-studio.ts
index beda326a0..2c993faeb 100644
--- a/server/lib/video-studio.ts
+++ b/server/lib/video-studio.ts
@@ -1,19 +1,38 @@
1import { logger } from '@server/helpers/logger' 1import { move, remove } from 'fs-extra'
2import { MVideoFullLight } from '@server/types/models' 2import { join } from 'path'
3import { logger, loggerTagsFactory } from '@server/helpers/logger'
4import { createTorrentAndSetInfoHashFromPath } from '@server/helpers/webtorrent'
5import { CONFIG } from '@server/initializers/config'
6import { UserModel } from '@server/models/user/user'
7import { MUser, MVideo, MVideoFile, MVideoFullLight, MVideoWithAllFiles } from '@server/types/models'
3import { getVideoStreamDuration } from '@shared/ffmpeg' 8import { getVideoStreamDuration } from '@shared/ffmpeg'
4import { VideoStudioEditionPayload, VideoStudioTask } from '@shared/models' 9import { VideoStudioEditionPayload, VideoStudioTask, VideoStudioTaskPayload } from '@shared/models'
5import { remove } from 'fs-extra' 10import { federateVideoIfNeeded } from './activitypub/videos'
11import { JobQueue } from './job-queue'
12import { VideoEditionTranscodingJobHandler } from './runners'
13import { createOptimizeOrMergeAudioJobs } from './transcoding/create-transcoding-job'
14import { getTranscodingJobPriority } from './transcoding/transcoding-priority'
15import { buildNewFile, removeHLSPlaylist, removeWebTorrentFile } from './video-file'
16import { VideoPathManager } from './video-path-manager'
6 17
7function buildTaskFileFieldname (indice: number, fieldName = 'file') { 18const lTags = loggerTagsFactory('video-edition')
19
20export function buildTaskFileFieldname (indice: number, fieldName = 'file') {
8 return `tasks[${indice}][options][${fieldName}]` 21 return `tasks[${indice}][options][${fieldName}]`
9} 22}
10 23
11function getTaskFileFromReq (files: Express.Multer.File[], indice: number, fieldName = 'file') { 24export function getTaskFileFromReq (files: Express.Multer.File[], indice: number, fieldName = 'file') {
12 return files.find(f => f.fieldname === buildTaskFileFieldname(indice, fieldName)) 25 return files.find(f => f.fieldname === buildTaskFileFieldname(indice, fieldName))
13} 26}
14 27
15async function safeCleanupStudioTMPFiles (payload: VideoStudioEditionPayload) { 28export function getStudioTaskFilePath (filename: string) {
16 for (const task of payload.tasks) { 29 return join(CONFIG.STORAGE.TMP_PERSISTENT_DIR, filename)
30}
31
32export async function safeCleanupStudioTMPFiles (tasks: VideoStudioTaskPayload[]) {
33 logger.info('Removing studio task files', { tasks, ...lTags() })
34
35 for (const task of tasks) {
17 try { 36 try {
18 if (task.name === 'add-intro' || task.name === 'add-outro') { 37 if (task.name === 'add-intro' || task.name === 'add-outro') {
19 await remove(task.options.file) 38 await remove(task.options.file)
@@ -26,7 +45,13 @@ async function safeCleanupStudioTMPFiles (payload: VideoStudioEditionPayload) {
26 } 45 }
27} 46}
28 47
29async function approximateIntroOutroAdditionalSize (video: MVideoFullLight, tasks: VideoStudioTask[], fileFinder: (i: number) => string) { 48// ---------------------------------------------------------------------------
49
50export async function approximateIntroOutroAdditionalSize (
51 video: MVideoFullLight,
52 tasks: VideoStudioTask[],
53 fileFinder: (i: number) => string
54) {
30 let additionalDuration = 0 55 let additionalDuration = 0
31 56
32 for (let i = 0; i < tasks.length; i++) { 57 for (let i = 0; i < tasks.length; i++) {
@@ -41,9 +66,65 @@ async function approximateIntroOutroAdditionalSize (video: MVideoFullLight, task
41 return (video.getMaxQualityFile().size / video.duration) * additionalDuration 66 return (video.getMaxQualityFile().size / video.duration) * additionalDuration
42} 67}
43 68
44export { 69// ---------------------------------------------------------------------------
45 approximateIntroOutroAdditionalSize, 70
46 buildTaskFileFieldname, 71export async function createVideoStudioJob (options: {
47 getTaskFileFromReq, 72 video: MVideo
48 safeCleanupStudioTMPFiles 73 user: MUser
74 payload: VideoStudioEditionPayload
75}) {
76 const { video, user, payload } = options
77
78 const priority = await getTranscodingJobPriority({ user, type: 'studio', fallback: 0 })
79
80 if (CONFIG.VIDEO_STUDIO.REMOTE_RUNNERS.ENABLED) {
81 await new VideoEditionTranscodingJobHandler().create({ video, tasks: payload.tasks, priority })
82 return
83 }
84
85 await JobQueue.Instance.createJob({ type: 'video-studio-edition', payload, priority })
86}
87
88export async function onVideoEditionEnded (options: {
89 editionResultPath: string
90 tasks: VideoStudioTaskPayload[]
91 video: MVideoFullLight
92}) {
93 const { video, tasks, editionResultPath } = options
94
95 const newFile = await buildNewFile({ path: editionResultPath, mode: 'web-video' })
96 newFile.videoId = video.id
97
98 const outputPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, newFile)
99 await move(editionResultPath, outputPath)
100
101 await safeCleanupStudioTMPFiles(tasks)
102
103 await createTorrentAndSetInfoHashFromPath(video, newFile, outputPath)
104 await removeAllFiles(video, newFile)
105
106 await newFile.save()
107
108 video.duration = await getVideoStreamDuration(outputPath)
109 await video.save()
110
111 await federateVideoIfNeeded(video, false, undefined)
112
113 const user = await UserModel.loadByVideoId(video.id)
114
115 await createOptimizeOrMergeAudioJobs({ video, videoFile: newFile, isNewVideo: false, user, videoFileAlreadyLocked: false })
116}
117
118// ---------------------------------------------------------------------------
119// Private
120// ---------------------------------------------------------------------------
121
122async function removeAllFiles (video: MVideoWithAllFiles, webTorrentFileException: MVideoFile) {
123 await removeHLSPlaylist(video)
124
125 for (const file of video.VideoFiles) {
126 if (file.id === webTorrentFileException.id) continue
127
128 await removeWebTorrentFile(video, file.id)
129 }
49} 130}