aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api/videos/upload.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers/api/videos/upload.ts')
-rw-r--r--server/controllers/api/videos/upload.ts68
1 files changed, 30 insertions, 38 deletions
diff --git a/server/controllers/api/videos/upload.ts b/server/controllers/api/videos/upload.ts
index 4a9d7b619..cc171eece 100644
--- a/server/controllers/api/videos/upload.ts
+++ b/server/controllers/api/videos/upload.ts
@@ -8,9 +8,9 @@ import { generateWebTorrentVideoFilename } from '@server/lib/paths'
8import { Redis } from '@server/lib/redis' 8import { Redis } from '@server/lib/redis'
9import { uploadx } from '@server/lib/uploadx' 9import { uploadx } from '@server/lib/uploadx'
10import { 10import {
11 addMoveToObjectStorageJob,
12 addOptimizeOrMergeAudioJob,
13 buildLocalVideoFromReq, 11 buildLocalVideoFromReq,
12 buildMoveToObjectStorageJob,
13 buildOptimizeOrMergeAudioJob,
14 buildVideoThumbnailsFromReq, 14 buildVideoThumbnailsFromReq,
15 setVideoTags 15 setVideoTags
16} from '@server/lib/video' 16} from '@server/lib/video'
@@ -18,19 +18,16 @@ import { VideoPathManager } from '@server/lib/video-path-manager'
18import { buildNextVideoState } from '@server/lib/video-state' 18import { buildNextVideoState } from '@server/lib/video-state'
19import { openapiOperationDoc } from '@server/middlewares/doc' 19import { openapiOperationDoc } from '@server/middlewares/doc'
20import { VideoSourceModel } from '@server/models/video/video-source' 20import { VideoSourceModel } from '@server/models/video/video-source'
21import { MVideoFile, MVideoFullLight } from '@server/types/models' 21import { MUserId, MVideoFile, MVideoFullLight } from '@server/types/models'
22import { getLowercaseExtension } from '@shared/core-utils' 22import { getLowercaseExtension } from '@shared/core-utils'
23import { isAudioFile, uuidToShort } from '@shared/extra-utils' 23import { isAudioFile, uuidToShort } from '@shared/extra-utils'
24import { HttpStatusCode, ManageVideoTorrentPayload, VideoCreate, VideoResolution, VideoState } from '@shared/models' 24import { HttpStatusCode, VideoCreate, VideoResolution, VideoState } from '@shared/models'
25import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' 25import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
26import { retryTransactionWrapper } from '../../../helpers/database-utils'
27import { createReqFiles } from '../../../helpers/express-utils' 26import { createReqFiles } from '../../../helpers/express-utils'
28import { buildFileMetadata, ffprobePromise, getVideoStreamDimensionsInfo, getVideoStreamFPS } from '../../../helpers/ffmpeg' 27import { buildFileMetadata, ffprobePromise, getVideoStreamDimensionsInfo, getVideoStreamFPS } from '../../../helpers/ffmpeg'
29import { logger, loggerTagsFactory } from '../../../helpers/logger' 28import { logger, loggerTagsFactory } from '../../../helpers/logger'
30import { MIMETYPES } from '../../../initializers/constants' 29import { MIMETYPES } from '../../../initializers/constants'
31import { sequelizeTypescript } from '../../../initializers/database' 30import { sequelizeTypescript } from '../../../initializers/database'
32import { federateVideoIfNeeded } from '../../../lib/activitypub/videos'
33import { Notifier } from '../../../lib/notifier'
34import { Hooks } from '../../../lib/plugins/hooks' 31import { Hooks } from '../../../lib/plugins/hooks'
35import { generateVideoMiniature } from '../../../lib/thumbnail' 32import { generateVideoMiniature } from '../../../lib/thumbnail'
36import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist' 33import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist'
@@ -216,22 +213,8 @@ async function addVideo (options: {
216 // Channel has a new content, set as updated 213 // Channel has a new content, set as updated
217 await videoCreated.VideoChannel.setAsUpdated() 214 await videoCreated.VideoChannel.setAsUpdated()
218 215
219 createTorrentFederate(videoCreated, videoFile) 216 addVideoJobsAfterUpload(videoCreated, videoFile, user)
220 .catch(err => { 217 .catch(err => logger.error('Cannot build new video jobs of %s.', videoCreated.uuid, { err, ...lTags(videoCreated.uuid) }))
221 logger.error('Cannot create torrent or federate video for %s.', videoCreated.uuid, { err, ...lTags(videoCreated.uuid) })
222
223 return videoCreated
224 }).then(refreshedVideo => {
225 if (!refreshedVideo) return
226
227 if (refreshedVideo.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE) {
228 return addMoveToObjectStorageJob({ video: refreshedVideo, previousVideoState: undefined })
229 }
230
231 if (refreshedVideo.state === VideoState.TO_TRANSCODE) {
232 return addOptimizeOrMergeAudioJob({ video: refreshedVideo, videoFile, user })
233 }
234 }).catch(err => logger.error('Cannot add optimize/merge audio job for %s.', videoCreated.uuid, { err, ...lTags(videoCreated.uuid) }))
235 218
236 Hooks.runAction('action:api.video.uploaded', { video: videoCreated, req, res }) 219 Hooks.runAction('action:api.video.uploaded', { video: videoCreated, req, res })
237 220
@@ -266,23 +249,32 @@ async function buildNewFile (videoPhysicalFile: express.VideoUploadFile) {
266 return videoFile 249 return videoFile
267} 250}
268 251
269async function createTorrentFederate (video: MVideoFullLight, videoFile: MVideoFile) { 252async function addVideoJobsAfterUpload (video: MVideoFullLight, videoFile: MVideoFile, user: MUserId) {
270 const payload: ManageVideoTorrentPayload = { videoId: video.id, videoFileId: videoFile.id, action: 'create' } 253 return JobQueue.Instance.createSequentialJobFlow(
271 254 {
272 const job = await JobQueue.Instance.createJobWithPromise({ type: 'manage-video-torrent', payload }) 255 type: 'manage-video-torrent' as 'manage-video-torrent',
273 await JobQueue.Instance.waitJob(job) 256 payload: {
274 257 videoId: video.id,
275 const refreshedVideo = await VideoModel.loadFull(video.id) 258 videoFileId: videoFile.id,
276 if (!refreshedVideo) return 259 action: 'create'
277 260 }
278 // Only federate and notify after the torrent creation 261 },
279 Notifier.Instance.notifyOnNewVideoIfNeeded(refreshedVideo) 262 {
263 type: 'federate-video' as 'federate-video',
264 payload: {
265 videoUUID: video.uuid,
266 isNewVideo: true
267 }
268 },
280 269
281 await retryTransactionWrapper(() => { 270 video.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE
282 return sequelizeTypescript.transaction(t => federateVideoIfNeeded(refreshedVideo, true, t)) 271 ? await buildMoveToObjectStorageJob({ video, previousVideoState: undefined })
283 }) 272 : undefined,
284 273
285 return refreshedVideo 274 video.state === VideoState.TO_TRANSCODE
275 ? await buildOptimizeOrMergeAudioJob({ video, videoFile, user })
276 : undefined
277 )
286} 278}
287 279
288async function deleteUploadResumableCache (req: express.Request, res: express.Response, next: express.NextFunction) { 280async function deleteUploadResumableCache (req: express.Request, res: express.Response, next: express.NextFunction) {