]>
Commit | Line | Data |
---|---|---|
1 | import Bluebird from 'bluebird' | |
2 | import express from 'express' | |
3 | import { move } from 'fs-extra' | |
4 | import { basename } from 'path' | |
5 | import { createAnyReqFiles } from '@server/helpers/express-utils' | |
6 | import { MIMETYPES, VIDEO_FILTERS } from '@server/initializers/constants' | |
7 | import { buildTaskFileFieldname, createVideoStudioJob, getStudioTaskFilePath, getTaskFileFromReq } from '@server/lib/video-studio' | |
8 | import { | |
9 | HttpStatusCode, | |
10 | VideoState, | |
11 | VideoStudioCreateEdition, | |
12 | VideoStudioTask, | |
13 | VideoStudioTaskCut, | |
14 | VideoStudioTaskIntro, | |
15 | VideoStudioTaskOutro, | |
16 | VideoStudioTaskPayload, | |
17 | VideoStudioTaskWatermark | |
18 | } from '@shared/models' | |
19 | import { asyncMiddleware, authenticate, videoStudioAddEditionValidator } from '../../../middlewares' | |
20 | ||
21 | const studioRouter = express.Router() | |
22 | ||
23 | const tasksFiles = createAnyReqFiles( | |
24 | MIMETYPES.VIDEO.MIMETYPE_EXT, | |
25 | (req: express.Request, file: Express.Multer.File, cb: (err: Error, result?: boolean) => void) => { | |
26 | const body = req.body as VideoStudioCreateEdition | |
27 | ||
28 | // Fetch array element | |
29 | const matches = file.fieldname.match(/tasks\[(\d+)\]/) | |
30 | if (!matches) return cb(new Error('Cannot find array element indice for ' + file.fieldname)) | |
31 | ||
32 | const indice = parseInt(matches[1]) | |
33 | const task = body.tasks[indice] | |
34 | ||
35 | if (!task) return cb(new Error('Cannot find array element of indice ' + indice + ' for ' + file.fieldname)) | |
36 | ||
37 | if ( | |
38 | [ 'add-intro', 'add-outro', 'add-watermark' ].includes(task.name) && | |
39 | file.fieldname === buildTaskFileFieldname(indice) | |
40 | ) { | |
41 | return cb(null, true) | |
42 | } | |
43 | ||
44 | return cb(null, false) | |
45 | } | |
46 | ) | |
47 | ||
48 | studioRouter.post('/:videoId/studio/edit', | |
49 | authenticate, | |
50 | tasksFiles, | |
51 | asyncMiddleware(videoStudioAddEditionValidator), | |
52 | asyncMiddleware(createEditionTasks) | |
53 | ) | |
54 | ||
55 | // --------------------------------------------------------------------------- | |
56 | ||
57 | export { | |
58 | studioRouter | |
59 | } | |
60 | ||
61 | // --------------------------------------------------------------------------- | |
62 | ||
63 | async function createEditionTasks (req: express.Request, res: express.Response) { | |
64 | const files = req.files as Express.Multer.File[] | |
65 | const body = req.body as VideoStudioCreateEdition | |
66 | const video = res.locals.videoAll | |
67 | ||
68 | video.state = VideoState.TO_EDIT | |
69 | await video.save() | |
70 | ||
71 | const payload = { | |
72 | videoUUID: video.uuid, | |
73 | tasks: await Bluebird.mapSeries(body.tasks, (t, i) => buildTaskPayload(t, i, files)) | |
74 | } | |
75 | ||
76 | await createVideoStudioJob({ | |
77 | user: res.locals.oauth.token.User, | |
78 | payload, | |
79 | video | |
80 | }) | |
81 | ||
82 | return res.sendStatus(HttpStatusCode.NO_CONTENT_204) | |
83 | } | |
84 | ||
85 | const taskPayloadBuilders: { | |
86 | [id in VideoStudioTask['name']]: ( | |
87 | task: VideoStudioTask, | |
88 | indice?: number, | |
89 | files?: Express.Multer.File[] | |
90 | ) => Promise<VideoStudioTaskPayload> | |
91 | } = { | |
92 | 'add-intro': buildIntroOutroTask, | |
93 | 'add-outro': buildIntroOutroTask, | |
94 | 'cut': buildCutTask, | |
95 | 'add-watermark': buildWatermarkTask | |
96 | } | |
97 | ||
98 | function buildTaskPayload (task: VideoStudioTask, indice: number, files: Express.Multer.File[]): Promise<VideoStudioTaskPayload> { | |
99 | return taskPayloadBuilders[task.name](task, indice, files) | |
100 | } | |
101 | ||
102 | async function buildIntroOutroTask (task: VideoStudioTaskIntro | VideoStudioTaskOutro, indice: number, files: Express.Multer.File[]) { | |
103 | const destination = await moveStudioFileToPersistentTMP(getTaskFileFromReq(files, indice).path) | |
104 | ||
105 | return { | |
106 | name: task.name, | |
107 | options: { | |
108 | file: destination | |
109 | } | |
110 | } | |
111 | } | |
112 | ||
113 | function buildCutTask (task: VideoStudioTaskCut) { | |
114 | return Promise.resolve({ | |
115 | name: task.name, | |
116 | options: { | |
117 | start: task.options.start, | |
118 | end: task.options.end | |
119 | } | |
120 | }) | |
121 | } | |
122 | ||
123 | async function buildWatermarkTask (task: VideoStudioTaskWatermark, indice: number, files: Express.Multer.File[]) { | |
124 | const destination = await moveStudioFileToPersistentTMP(getTaskFileFromReq(files, indice).path) | |
125 | ||
126 | return { | |
127 | name: task.name, | |
128 | options: { | |
129 | file: destination, | |
130 | watermarkSizeRatio: VIDEO_FILTERS.WATERMARK.SIZE_RATIO, | |
131 | horitonzalMarginRatio: VIDEO_FILTERS.WATERMARK.HORIZONTAL_MARGIN_RATIO, | |
132 | verticalMarginRatio: VIDEO_FILTERS.WATERMARK.VERTICAL_MARGIN_RATIO | |
133 | } | |
134 | } | |
135 | } | |
136 | ||
137 | async function moveStudioFileToPersistentTMP (file: string) { | |
138 | const destination = getStudioTaskFilePath(basename(file)) | |
139 | ||
140 | await move(file, destination) | |
141 | ||
142 | return destination | |
143 | } |