]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/controllers/api/videos/studio.ts
Bumped to version v5.2.1
[github/Chocobozzz/PeerTube.git] / server / controllers / api / videos / studio.ts
CommitLineData
6a490560 1import Bluebird from 'bluebird'
c729caf6 2import express from 'express'
6a490560 3import { move } from 'fs-extra'
5e47f6ab 4import { basename } from 'path'
c729caf6 5import { createAnyReqFiles } from '@server/helpers/express-utils'
5e47f6ab
C
6import { MIMETYPES, VIDEO_FILTERS } from '@server/initializers/constants'
7import { buildTaskFileFieldname, createVideoStudioJob, getStudioTaskFilePath, getTaskFileFromReq } from '@server/lib/video-studio'
c729caf6
C
8import {
9 HttpStatusCode,
92e66e04
C
10 VideoState,
11 VideoStudioCreateEdition,
12 VideoStudioTask,
13 VideoStudioTaskCut,
14 VideoStudioTaskIntro,
15 VideoStudioTaskOutro,
16 VideoStudioTaskPayload,
17 VideoStudioTaskWatermark
c729caf6 18} from '@shared/models'
92e66e04 19import { asyncMiddleware, authenticate, videoStudioAddEditionValidator } from '../../../middlewares'
c729caf6 20
92e66e04 21const studioRouter = express.Router()
c729caf6
C
22
23const tasksFiles = createAnyReqFiles(
24 MIMETYPES.VIDEO.MIMETYPE_EXT,
c729caf6 25 (req: express.Request, file: Express.Multer.File, cb: (err: Error, result?: boolean) => void) => {
92e66e04 26 const body = req.body as VideoStudioCreateEdition
c729caf6
C
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
92e66e04 48studioRouter.post('/:videoId/studio/edit',
c729caf6
C
49 authenticate,
50 tasksFiles,
92e66e04 51 asyncMiddleware(videoStudioAddEditionValidator),
c729caf6
C
52 asyncMiddleware(createEditionTasks)
53)
54
55// ---------------------------------------------------------------------------
56
57export {
92e66e04 58 studioRouter
c729caf6
C
59}
60
61// ---------------------------------------------------------------------------
62
63async function createEditionTasks (req: express.Request, res: express.Response) {
64 const files = req.files as Express.Multer.File[]
92e66e04 65 const body = req.body as VideoStudioCreateEdition
c729caf6
C
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,
6a490560 73 tasks: await Bluebird.mapSeries(body.tasks, (t, i) => buildTaskPayload(t, i, files))
c729caf6
C
74 }
75
5e47f6ab
C
76 await createVideoStudioJob({
77 user: res.locals.oauth.token.User,
78 payload,
79 video
80 })
c729caf6
C
81
82 return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
83}
84
85const taskPayloadBuilders: {
6a490560
C
86 [id in VideoStudioTask['name']]: (
87 task: VideoStudioTask,
88 indice?: number,
89 files?: Express.Multer.File[]
90 ) => Promise<VideoStudioTaskPayload>
c729caf6
C
91} = {
92 'add-intro': buildIntroOutroTask,
93 'add-outro': buildIntroOutroTask,
94 'cut': buildCutTask,
95 'add-watermark': buildWatermarkTask
96}
97
6a490560 98function buildTaskPayload (task: VideoStudioTask, indice: number, files: Express.Multer.File[]): Promise<VideoStudioTaskPayload> {
c729caf6
C
99 return taskPayloadBuilders[task.name](task, indice, files)
100}
101
6a490560
C
102async function buildIntroOutroTask (task: VideoStudioTaskIntro | VideoStudioTaskOutro, indice: number, files: Express.Multer.File[]) {
103 const destination = await moveStudioFileToPersistentTMP(getTaskFileFromReq(files, indice).path)
104
c729caf6
C
105 return {
106 name: task.name,
107 options: {
6a490560 108 file: destination
c729caf6
C
109 }
110 }
111}
112
92e66e04 113function buildCutTask (task: VideoStudioTaskCut) {
6a490560 114 return Promise.resolve({
c729caf6
C
115 name: task.name,
116 options: {
117 start: task.options.start,
118 end: task.options.end
119 }
6a490560 120 })
c729caf6
C
121}
122
6a490560
C
123async function buildWatermarkTask (task: VideoStudioTaskWatermark, indice: number, files: Express.Multer.File[]) {
124 const destination = await moveStudioFileToPersistentTMP(getTaskFileFromReq(files, indice).path)
125
c729caf6
C
126 return {
127 name: task.name,
128 options: {
5e47f6ab
C
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
c729caf6
C
133 }
134 }
135}
6a490560
C
136
137async function moveStudioFileToPersistentTMP (file: string) {
5e47f6ab 138 const destination = getStudioTaskFilePath(basename(file))
6a490560
C
139
140 await move(file, destination)
141
142 return destination
143}