diff options
author | Chocobozzz <me@florianbigard.com> | 2022-02-11 10:51:33 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2022-02-28 10:42:19 +0100 |
commit | c729caf6cc34630877a0e5a1bda1719384cd0c8a (patch) | |
tree | 1d2e13722e518c73d2c9e6f0969615e29d51cf8c /server/lib/job-queue | |
parent | a24bf4dc659cebb65d887862bf21d7a35e9ec791 (diff) | |
download | PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.tar.gz PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.tar.zst PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.zip |
Add basic video editor support
Diffstat (limited to 'server/lib/job-queue')
-rw-r--r-- | server/lib/job-queue/handlers/video-edition.ts | 229 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-file-import.ts | 12 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-import.ts | 8 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-live-ending.ts | 8 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-transcoding.ts | 10 | ||||
-rw-r--r-- | server/lib/job-queue/job-queue.ts | 9 |
6 files changed, 255 insertions, 21 deletions
diff --git a/server/lib/job-queue/handlers/video-edition.ts b/server/lib/job-queue/handlers/video-edition.ts new file mode 100644 index 000000000..c5ba0452f --- /dev/null +++ b/server/lib/job-queue/handlers/video-edition.ts | |||
@@ -0,0 +1,229 @@ | |||
1 | import { Job } from 'bull' | ||
2 | import { move, remove } from 'fs-extra' | ||
3 | import { join } from 'path' | ||
4 | import { addIntroOutro, addWatermark, cutVideo } from '@server/helpers/ffmpeg' | ||
5 | import { createTorrentAndSetInfoHashFromPath } from '@server/helpers/webtorrent' | ||
6 | import { CONFIG } from '@server/initializers/config' | ||
7 | import { federateVideoIfNeeded } from '@server/lib/activitypub/videos' | ||
8 | import { generateWebTorrentVideoFilename } from '@server/lib/paths' | ||
9 | import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles' | ||
10 | import { isAbleToUploadVideo } from '@server/lib/user' | ||
11 | import { addMoveToObjectStorageJob, addOptimizeOrMergeAudioJob } from '@server/lib/video' | ||
12 | import { approximateIntroOutroAdditionalSize } from '@server/lib/video-editor' | ||
13 | import { VideoPathManager } from '@server/lib/video-path-manager' | ||
14 | import { buildNextVideoState } from '@server/lib/video-state' | ||
15 | import { UserModel } from '@server/models/user/user' | ||
16 | import { VideoModel } from '@server/models/video/video' | ||
17 | import { VideoFileModel } from '@server/models/video/video-file' | ||
18 | import { MVideo, MVideoFile, MVideoFullLight, MVideoId, MVideoWithAllFiles } from '@server/types/models' | ||
19 | import { getLowercaseExtension, pick } from '@shared/core-utils' | ||
20 | import { | ||
21 | buildFileMetadata, | ||
22 | buildUUID, | ||
23 | ffprobePromise, | ||
24 | getFileSize, | ||
25 | getVideoStreamDimensionsInfo, | ||
26 | getVideoStreamDuration, | ||
27 | getVideoStreamFPS | ||
28 | } from '@shared/extra-utils' | ||
29 | import { | ||
30 | VideoEditionPayload, | ||
31 | VideoEditionTaskPayload, | ||
32 | VideoEditorTask, | ||
33 | VideoEditorTaskCutPayload, | ||
34 | VideoEditorTaskIntroPayload, | ||
35 | VideoEditorTaskOutroPayload, | ||
36 | VideoEditorTaskWatermarkPayload, | ||
37 | VideoState | ||
38 | } from '@shared/models' | ||
39 | import { logger, loggerTagsFactory } from '../../../helpers/logger' | ||
40 | |||
41 | const lTagsBase = loggerTagsFactory('video-edition') | ||
42 | |||
43 | async function processVideoEdition (job: Job) { | ||
44 | const payload = job.data as VideoEditionPayload | ||
45 | |||
46 | logger.info('Process video edition of %s in job %d.', payload.videoUUID, job.id) | ||
47 | |||
48 | const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(payload.videoUUID) | ||
49 | |||
50 | // No video, maybe deleted? | ||
51 | if (!video) { | ||
52 | logger.info('Can\'t process job %d, video does not exist.', job.id, lTagsBase(payload.videoUUID)) | ||
53 | return undefined | ||
54 | } | ||
55 | |||
56 | await checkUserQuotaOrThrow(video, payload) | ||
57 | |||
58 | const inputFile = video.getMaxQualityFile() | ||
59 | |||
60 | const editionResultPath = await VideoPathManager.Instance.makeAvailableVideoFile(inputFile, async originalFilePath => { | ||
61 | let tmpInputFilePath: string | ||
62 | let outputPath: string | ||
63 | |||
64 | for (const task of payload.tasks) { | ||
65 | const outputFilename = buildUUID() + inputFile.extname | ||
66 | outputPath = join(CONFIG.STORAGE.TMP_DIR, outputFilename) | ||
67 | |||
68 | await processTask({ | ||
69 | inputPath: tmpInputFilePath ?? originalFilePath, | ||
70 | video, | ||
71 | outputPath, | ||
72 | task | ||
73 | }) | ||
74 | |||
75 | if (tmpInputFilePath) await remove(tmpInputFilePath) | ||
76 | |||
77 | // For the next iteration | ||
78 | tmpInputFilePath = outputPath | ||
79 | } | ||
80 | |||
81 | return outputPath | ||
82 | }) | ||
83 | |||
84 | logger.info('Video edition ended for video %s.', video.uuid) | ||
85 | |||
86 | const newFile = await buildNewFile(video, editionResultPath) | ||
87 | |||
88 | const outputPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, newFile) | ||
89 | await move(editionResultPath, outputPath) | ||
90 | |||
91 | await createTorrentAndSetInfoHashFromPath(video, newFile, outputPath) | ||
92 | |||
93 | await removeAllFiles(video, newFile) | ||
94 | |||
95 | await newFile.save() | ||
96 | |||
97 | video.state = buildNextVideoState() | ||
98 | video.duration = await getVideoStreamDuration(outputPath) | ||
99 | await video.save() | ||
100 | |||
101 | await federateVideoIfNeeded(video, false, undefined) | ||
102 | |||
103 | if (video.state === VideoState.TO_TRANSCODE) { | ||
104 | const user = await UserModel.loadByVideoId(video.id) | ||
105 | |||
106 | await addOptimizeOrMergeAudioJob(video, newFile, user, false) | ||
107 | } else if (video.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE) { | ||
108 | await addMoveToObjectStorageJob(video, false) | ||
109 | } | ||
110 | } | ||
111 | |||
112 | // --------------------------------------------------------------------------- | ||
113 | |||
114 | export { | ||
115 | processVideoEdition | ||
116 | } | ||
117 | |||
118 | // --------------------------------------------------------------------------- | ||
119 | |||
120 | type TaskProcessorOptions <T extends VideoEditionTaskPayload = VideoEditionTaskPayload> = { | ||
121 | inputPath: string | ||
122 | outputPath: string | ||
123 | video: MVideo | ||
124 | task: T | ||
125 | } | ||
126 | |||
127 | const taskProcessors: { [id in VideoEditorTask['name']]: (options: TaskProcessorOptions) => Promise<any> } = { | ||
128 | 'add-intro': processAddIntroOutro, | ||
129 | 'add-outro': processAddIntroOutro, | ||
130 | 'cut': processCut, | ||
131 | 'add-watermark': processAddWatermark | ||
132 | } | ||
133 | |||
134 | async function processTask (options: TaskProcessorOptions) { | ||
135 | const { video, task } = options | ||
136 | |||
137 | logger.info('Processing %s task for video %s.', task.name, video.uuid, { task }) | ||
138 | |||
139 | const processor = taskProcessors[options.task.name] | ||
140 | if (!process) throw new Error('Unknown task ' + task.name) | ||
141 | |||
142 | return processor(options) | ||
143 | } | ||
144 | |||
145 | function processAddIntroOutro (options: TaskProcessorOptions<VideoEditorTaskIntroPayload | VideoEditorTaskOutroPayload>) { | ||
146 | const { task } = options | ||
147 | |||
148 | return addIntroOutro({ | ||
149 | ...pick(options, [ 'inputPath', 'outputPath' ]), | ||
150 | |||
151 | introOutroPath: task.options.file, | ||
152 | type: task.name === 'add-intro' | ||
153 | ? 'intro' | ||
154 | : 'outro', | ||
155 | |||
156 | availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(), | ||
157 | profile: CONFIG.TRANSCODING.PROFILE | ||
158 | }) | ||
159 | } | ||
160 | |||
161 | function processCut (options: TaskProcessorOptions<VideoEditorTaskCutPayload>) { | ||
162 | const { task } = options | ||
163 | |||
164 | return cutVideo({ | ||
165 | ...pick(options, [ 'inputPath', 'outputPath' ]), | ||
166 | |||
167 | start: task.options.start, | ||
168 | end: task.options.end | ||
169 | }) | ||
170 | } | ||
171 | |||
172 | function processAddWatermark (options: TaskProcessorOptions<VideoEditorTaskWatermarkPayload>) { | ||
173 | const { task } = options | ||
174 | |||
175 | return addWatermark({ | ||
176 | ...pick(options, [ 'inputPath', 'outputPath' ]), | ||
177 | |||
178 | watermarkPath: task.options.file, | ||
179 | |||
180 | availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(), | ||
181 | profile: CONFIG.TRANSCODING.PROFILE | ||
182 | }) | ||
183 | } | ||
184 | |||
185 | async function buildNewFile (video: MVideoId, path: string) { | ||
186 | const videoFile = new VideoFileModel({ | ||
187 | extname: getLowercaseExtension(path), | ||
188 | size: await getFileSize(path), | ||
189 | metadata: await buildFileMetadata(path), | ||
190 | videoStreamingPlaylistId: null, | ||
191 | videoId: video.id | ||
192 | }) | ||
193 | |||
194 | const probe = await ffprobePromise(path) | ||
195 | |||
196 | videoFile.fps = await getVideoStreamFPS(path, probe) | ||
197 | videoFile.resolution = (await getVideoStreamDimensionsInfo(path, probe)).resolution | ||
198 | |||
199 | videoFile.filename = generateWebTorrentVideoFilename(videoFile.resolution, videoFile.extname) | ||
200 | |||
201 | return videoFile | ||
202 | } | ||
203 | |||
204 | async function removeAllFiles (video: MVideoWithAllFiles, webTorrentFileException: MVideoFile) { | ||
205 | const hls = video.getHLSPlaylist() | ||
206 | |||
207 | if (hls) { | ||
208 | await video.removeStreamingPlaylistFiles(hls) | ||
209 | await hls.destroy() | ||
210 | } | ||
211 | |||
212 | for (const file of video.VideoFiles) { | ||
213 | if (file.id === webTorrentFileException.id) continue | ||
214 | |||
215 | await video.removeWebTorrentFileAndTorrent(file) | ||
216 | await file.destroy() | ||
217 | } | ||
218 | } | ||
219 | |||
220 | async function checkUserQuotaOrThrow (video: MVideoFullLight, payload: VideoEditionPayload) { | ||
221 | const user = await UserModel.loadByVideoId(video.id) | ||
222 | |||
223 | const filePathFinder = (i: number) => (payload.tasks[i] as VideoEditorTaskIntroPayload | VideoEditorTaskOutroPayload).options.file | ||
224 | |||
225 | const additionalBytes = await approximateIntroOutroAdditionalSize(video, payload.tasks, filePathFinder) | ||
226 | if (await isAbleToUploadVideo(user.id, additionalBytes) === false) { | ||
227 | throw new Error('Quota exceeded for this user to edit the video') | ||
228 | } | ||
229 | } | ||
diff --git a/server/lib/job-queue/handlers/video-file-import.ts b/server/lib/job-queue/handlers/video-file-import.ts index 0d9e80cb8..6b2d60317 100644 --- a/server/lib/job-queue/handlers/video-file-import.ts +++ b/server/lib/job-queue/handlers/video-file-import.ts | |||
@@ -1,18 +1,18 @@ | |||
1 | import { Job } from 'bull' | 1 | import { Job } from 'bull' |
2 | import { copy, stat } from 'fs-extra' | 2 | import { copy, stat } from 'fs-extra' |
3 | import { getLowercaseExtension } from '@shared/core-utils' | ||
4 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 3 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' |
5 | import { CONFIG } from '@server/initializers/config' | 4 | import { CONFIG } from '@server/initializers/config' |
6 | import { federateVideoIfNeeded } from '@server/lib/activitypub/videos' | 5 | import { federateVideoIfNeeded } from '@server/lib/activitypub/videos' |
7 | import { generateWebTorrentVideoFilename } from '@server/lib/paths' | 6 | import { generateWebTorrentVideoFilename } from '@server/lib/paths' |
8 | import { addMoveToObjectStorageJob } from '@server/lib/video' | 7 | import { addMoveToObjectStorageJob } from '@server/lib/video' |
9 | import { VideoPathManager } from '@server/lib/video-path-manager' | 8 | import { VideoPathManager } from '@server/lib/video-path-manager' |
9 | import { VideoModel } from '@server/models/video/video' | ||
10 | import { VideoFileModel } from '@server/models/video/video-file' | ||
10 | import { MVideoFullLight } from '@server/types/models' | 11 | import { MVideoFullLight } from '@server/types/models' |
12 | import { getLowercaseExtension } from '@shared/core-utils' | ||
11 | import { VideoFileImportPayload, VideoStorage } from '@shared/models' | 13 | import { VideoFileImportPayload, VideoStorage } from '@shared/models' |
12 | import { getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' | 14 | import { getVideoStreamFPS, getVideoStreamDimensionsInfo } from '../../../helpers/ffmpeg' |
13 | import { logger } from '../../../helpers/logger' | 15 | import { logger } from '../../../helpers/logger' |
14 | import { VideoModel } from '../../../models/video/video' | ||
15 | import { VideoFileModel } from '../../../models/video/video-file' | ||
16 | 16 | ||
17 | async function processVideoFileImport (job: Job) { | 17 | async function processVideoFileImport (job: Job) { |
18 | const payload = job.data as VideoFileImportPayload | 18 | const payload = job.data as VideoFileImportPayload |
@@ -45,9 +45,9 @@ export { | |||
45 | // --------------------------------------------------------------------------- | 45 | // --------------------------------------------------------------------------- |
46 | 46 | ||
47 | async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) { | 47 | async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) { |
48 | const { resolution } = await getVideoFileResolution(inputFilePath) | 48 | const { resolution } = await getVideoStreamDimensionsInfo(inputFilePath) |
49 | const { size } = await stat(inputFilePath) | 49 | const { size } = await stat(inputFilePath) |
50 | const fps = await getVideoFileFPS(inputFilePath) | 50 | const fps = await getVideoStreamFPS(inputFilePath) |
51 | 51 | ||
52 | const fileExt = getLowercaseExtension(inputFilePath) | 52 | const fileExt = getLowercaseExtension(inputFilePath) |
53 | 53 | ||
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts index b6e05d8f5..b3ca28c2f 100644 --- a/server/lib/job-queue/handlers/video-import.ts +++ b/server/lib/job-queue/handlers/video-import.ts | |||
@@ -25,7 +25,7 @@ import { | |||
25 | VideoResolution, | 25 | VideoResolution, |
26 | VideoState | 26 | VideoState |
27 | } from '@shared/models' | 27 | } from '@shared/models' |
28 | import { ffprobePromise, getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' | 28 | import { ffprobePromise, getVideoStreamDuration, getVideoStreamFPS, getVideoStreamDimensionsInfo } from '../../../helpers/ffmpeg' |
29 | import { logger } from '../../../helpers/logger' | 29 | import { logger } from '../../../helpers/logger' |
30 | import { getSecureTorrentName } from '../../../helpers/utils' | 30 | import { getSecureTorrentName } from '../../../helpers/utils' |
31 | import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent' | 31 | import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent' |
@@ -121,10 +121,10 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid | |||
121 | 121 | ||
122 | const { resolution } = await isAudioFile(tempVideoPath, probe) | 122 | const { resolution } = await isAudioFile(tempVideoPath, probe) |
123 | ? { resolution: VideoResolution.H_NOVIDEO } | 123 | ? { resolution: VideoResolution.H_NOVIDEO } |
124 | : await getVideoFileResolution(tempVideoPath) | 124 | : await getVideoStreamDimensionsInfo(tempVideoPath) |
125 | 125 | ||
126 | const fps = await getVideoFileFPS(tempVideoPath, probe) | 126 | const fps = await getVideoStreamFPS(tempVideoPath, probe) |
127 | const duration = await getDurationFromVideoFile(tempVideoPath, probe) | 127 | const duration = await getVideoStreamDuration(tempVideoPath, probe) |
128 | 128 | ||
129 | // Prepare video file object for creation in database | 129 | // Prepare video file object for creation in database |
130 | const fileExt = getLowercaseExtension(tempVideoPath) | 130 | const fileExt = getLowercaseExtension(tempVideoPath) |
diff --git a/server/lib/job-queue/handlers/video-live-ending.ts b/server/lib/job-queue/handlers/video-live-ending.ts index a04cfa2c9..497f6612a 100644 --- a/server/lib/job-queue/handlers/video-live-ending.ts +++ b/server/lib/job-queue/handlers/video-live-ending.ts | |||
@@ -1,12 +1,12 @@ | |||
1 | import { Job } from 'bull' | 1 | import { Job } from 'bull' |
2 | import { pathExists, readdir, remove } from 'fs-extra' | 2 | import { pathExists, readdir, remove } from 'fs-extra' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { ffprobePromise, getAudioStream, getDurationFromVideoFile, getVideoFileResolution } from '@server/helpers/ffprobe-utils' | 4 | import { ffprobePromise, getAudioStream, getVideoStreamDuration, getVideoStreamDimensionsInfo } from '@server/helpers/ffmpeg' |
5 | import { VIDEO_LIVE } from '@server/initializers/constants' | 5 | import { VIDEO_LIVE } from '@server/initializers/constants' |
6 | import { buildConcatenatedName, cleanupLive, LiveSegmentShaStore } from '@server/lib/live' | 6 | import { buildConcatenatedName, cleanupLive, LiveSegmentShaStore } from '@server/lib/live' |
7 | import { generateHLSMasterPlaylistFilename, generateHlsSha256SegmentsFilename, getLiveDirectory } from '@server/lib/paths' | 7 | import { generateHLSMasterPlaylistFilename, generateHlsSha256SegmentsFilename, getLiveDirectory } from '@server/lib/paths' |
8 | import { generateVideoMiniature } from '@server/lib/thumbnail' | 8 | import { generateVideoMiniature } from '@server/lib/thumbnail' |
9 | import { generateHlsPlaylistResolutionFromTS } from '@server/lib/transcoding/video-transcoding' | 9 | import { generateHlsPlaylistResolutionFromTS } from '@server/lib/transcoding/transcoding' |
10 | import { VideoPathManager } from '@server/lib/video-path-manager' | 10 | import { VideoPathManager } from '@server/lib/video-path-manager' |
11 | import { moveToNextState } from '@server/lib/video-state' | 11 | import { moveToNextState } from '@server/lib/video-state' |
12 | import { VideoModel } from '@server/models/video/video' | 12 | import { VideoModel } from '@server/models/video/video' |
@@ -96,7 +96,7 @@ async function saveLive (video: MVideo, live: MVideoLive, streamingPlaylist: MSt | |||
96 | const probe = await ffprobePromise(concatenatedTsFilePath) | 96 | const probe = await ffprobePromise(concatenatedTsFilePath) |
97 | const { audioStream } = await getAudioStream(concatenatedTsFilePath, probe) | 97 | const { audioStream } = await getAudioStream(concatenatedTsFilePath, probe) |
98 | 98 | ||
99 | const { resolution, isPortraitMode } = await getVideoFileResolution(concatenatedTsFilePath, probe) | 99 | const { resolution, isPortraitMode } = await getVideoStreamDimensionsInfo(concatenatedTsFilePath, probe) |
100 | 100 | ||
101 | const { resolutionPlaylistPath: outputPath } = await generateHlsPlaylistResolutionFromTS({ | 101 | const { resolutionPlaylistPath: outputPath } = await generateHlsPlaylistResolutionFromTS({ |
102 | video: videoWithFiles, | 102 | video: videoWithFiles, |
@@ -107,7 +107,7 @@ async function saveLive (video: MVideo, live: MVideoLive, streamingPlaylist: MSt | |||
107 | }) | 107 | }) |
108 | 108 | ||
109 | if (!durationDone) { | 109 | if (!durationDone) { |
110 | videoWithFiles.duration = await getDurationFromVideoFile(outputPath) | 110 | videoWithFiles.duration = await getVideoStreamDuration(outputPath) |
111 | await videoWithFiles.save() | 111 | await videoWithFiles.save() |
112 | 112 | ||
113 | durationDone = true | 113 | durationDone = true |
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts index 5540b791d..512979734 100644 --- a/server/lib/job-queue/handlers/video-transcoding.ts +++ b/server/lib/job-queue/handlers/video-transcoding.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { Job } from 'bull' | 1 | import { Job } from 'bull' |
2 | import { TranscodeOptionsType } from '@server/helpers/ffmpeg-utils' | 2 | import { TranscodeVODOptionsType } from '@server/helpers/ffmpeg' |
3 | import { addTranscodingJob, getTranscodingJobPriority } from '@server/lib/video' | 3 | import { addTranscodingJob, getTranscodingJobPriority } from '@server/lib/video' |
4 | import { VideoPathManager } from '@server/lib/video-path-manager' | 4 | import { VideoPathManager } from '@server/lib/video-path-manager' |
5 | import { moveToFailedTranscodingState, moveToNextState } from '@server/lib/video-state' | 5 | import { moveToFailedTranscodingState, moveToNextState } from '@server/lib/video-state' |
@@ -16,7 +16,7 @@ import { | |||
16 | VideoTranscodingPayload | 16 | VideoTranscodingPayload |
17 | } from '@shared/models' | 17 | } from '@shared/models' |
18 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 18 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
19 | import { computeLowerResolutionsToTranscode } from '../../../helpers/ffprobe-utils' | 19 | import { computeLowerResolutionsToTranscode } from '../../../helpers/ffmpeg' |
20 | import { logger, loggerTagsFactory } from '../../../helpers/logger' | 20 | import { logger, loggerTagsFactory } from '../../../helpers/logger' |
21 | import { CONFIG } from '../../../initializers/config' | 21 | import { CONFIG } from '../../../initializers/config' |
22 | import { VideoModel } from '../../../models/video/video' | 22 | import { VideoModel } from '../../../models/video/video' |
@@ -25,7 +25,7 @@ import { | |||
25 | mergeAudioVideofile, | 25 | mergeAudioVideofile, |
26 | optimizeOriginalVideofile, | 26 | optimizeOriginalVideofile, |
27 | transcodeNewWebTorrentResolution | 27 | transcodeNewWebTorrentResolution |
28 | } from '../../transcoding/video-transcoding' | 28 | } from '../../transcoding/transcoding' |
29 | 29 | ||
30 | type HandlerFunction = (job: Job, payload: VideoTranscodingPayload, video: MVideoFullLight, user: MUser) => Promise<void> | 30 | type HandlerFunction = (job: Job, payload: VideoTranscodingPayload, video: MVideoFullLight, user: MUser) => Promise<void> |
31 | 31 | ||
@@ -174,10 +174,10 @@ async function onHlsPlaylistGeneration (video: MVideoFullLight, user: MUser, pay | |||
174 | async function onVideoFirstWebTorrentTranscoding ( | 174 | async function onVideoFirstWebTorrentTranscoding ( |
175 | videoArg: MVideoWithFile, | 175 | videoArg: MVideoWithFile, |
176 | payload: OptimizeTranscodingPayload | MergeAudioTranscodingPayload, | 176 | payload: OptimizeTranscodingPayload | MergeAudioTranscodingPayload, |
177 | transcodeType: TranscodeOptionsType, | 177 | transcodeType: TranscodeVODOptionsType, |
178 | user: MUserId | 178 | user: MUserId |
179 | ) { | 179 | ) { |
180 | const { resolution, isPortraitMode, audioStream } = await videoArg.getMaxQualityFileInfo() | 180 | const { resolution, isPortraitMode, audioStream } = await videoArg.probeMaxQualityFile() |
181 | 181 | ||
182 | // Maybe the video changed in database, refresh it | 182 | // Maybe the video changed in database, refresh it |
183 | const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoArg.uuid) | 183 | const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoArg.uuid) |
diff --git a/server/lib/job-queue/job-queue.ts b/server/lib/job-queue/job-queue.ts index 22bd1f5d2..e10a3bab5 100644 --- a/server/lib/job-queue/job-queue.ts +++ b/server/lib/job-queue/job-queue.ts | |||
@@ -14,6 +14,7 @@ import { | |||
14 | JobType, | 14 | JobType, |
15 | MoveObjectStoragePayload, | 15 | MoveObjectStoragePayload, |
16 | RefreshPayload, | 16 | RefreshPayload, |
17 | VideoEditionPayload, | ||
17 | VideoFileImportPayload, | 18 | VideoFileImportPayload, |
18 | VideoImportPayload, | 19 | VideoImportPayload, |
19 | VideoLiveEndingPayload, | 20 | VideoLiveEndingPayload, |
@@ -31,6 +32,7 @@ import { refreshAPObject } from './handlers/activitypub-refresher' | |||
31 | import { processActorKeys } from './handlers/actor-keys' | 32 | import { processActorKeys } from './handlers/actor-keys' |
32 | import { processEmail } from './handlers/email' | 33 | import { processEmail } from './handlers/email' |
33 | import { processMoveToObjectStorage } from './handlers/move-to-object-storage' | 34 | import { processMoveToObjectStorage } from './handlers/move-to-object-storage' |
35 | import { processVideoEdition } from './handlers/video-edition' | ||
34 | import { processVideoFileImport } from './handlers/video-file-import' | 36 | import { processVideoFileImport } from './handlers/video-file-import' |
35 | import { processVideoImport } from './handlers/video-import' | 37 | import { processVideoImport } from './handlers/video-import' |
36 | import { processVideoLiveEnding } from './handlers/video-live-ending' | 38 | import { processVideoLiveEnding } from './handlers/video-live-ending' |
@@ -53,6 +55,7 @@ type CreateJobArgument = | |||
53 | { type: 'actor-keys', payload: ActorKeysPayload } | | 55 | { type: 'actor-keys', payload: ActorKeysPayload } | |
54 | { type: 'video-redundancy', payload: VideoRedundancyPayload } | | 56 | { type: 'video-redundancy', payload: VideoRedundancyPayload } | |
55 | { type: 'delete-resumable-upload-meta-file', payload: DeleteResumableUploadMetaFilePayload } | | 57 | { type: 'delete-resumable-upload-meta-file', payload: DeleteResumableUploadMetaFilePayload } | |
58 | { type: 'video-edition', payload: VideoEditionPayload } | | ||
56 | { type: 'move-to-object-storage', payload: MoveObjectStoragePayload } | 59 | { type: 'move-to-object-storage', payload: MoveObjectStoragePayload } |
57 | 60 | ||
58 | export type CreateJobOptions = { | 61 | export type CreateJobOptions = { |
@@ -75,7 +78,8 @@ const handlers: { [id in JobType]: (job: Job) => Promise<any> } = { | |||
75 | 'video-live-ending': processVideoLiveEnding, | 78 | 'video-live-ending': processVideoLiveEnding, |
76 | 'actor-keys': processActorKeys, | 79 | 'actor-keys': processActorKeys, |
77 | 'video-redundancy': processVideoRedundancy, | 80 | 'video-redundancy': processVideoRedundancy, |
78 | 'move-to-object-storage': processMoveToObjectStorage | 81 | 'move-to-object-storage': processMoveToObjectStorage, |
82 | 'video-edition': processVideoEdition | ||
79 | } | 83 | } |
80 | 84 | ||
81 | const jobTypes: JobType[] = [ | 85 | const jobTypes: JobType[] = [ |
@@ -93,7 +97,8 @@ const jobTypes: JobType[] = [ | |||
93 | 'video-redundancy', | 97 | 'video-redundancy', |
94 | 'actor-keys', | 98 | 'actor-keys', |
95 | 'video-live-ending', | 99 | 'video-live-ending', |
96 | 'move-to-object-storage' | 100 | 'move-to-object-storage', |
101 | 'video-edition' | ||
97 | ] | 102 | ] |
98 | 103 | ||
99 | class JobQueue { | 104 | class JobQueue { |