aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api/videos/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers/api/videos/index.ts')
-rw-r--r--server/controllers/api/videos/index.ts139
1 files changed, 69 insertions, 70 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index e2798830e..63de662a7 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -15,6 +15,7 @@ import { getServerAccount } from '../../../helpers/utils'
15import { CONFIG, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers' 15import { CONFIG, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers'
16import { database as db } from '../../../initializers/database' 16import { database as db } from '../../../initializers/database'
17import { sendAddVideo } from '../../../lib/activitypub/send/send-add' 17import { sendAddVideo } from '../../../lib/activitypub/send/send-add'
18import { sendCreateViewToOrigin } from '../../../lib/activitypub/send/send-create'
18import { sendUpdateVideo } from '../../../lib/activitypub/send/send-update' 19import { sendUpdateVideo } from '../../../lib/activitypub/send/send-update'
19import { shareVideoByServer } from '../../../lib/activitypub/share' 20import { shareVideoByServer } from '../../../lib/activitypub/share'
20import { getVideoActivityPubUrl } from '../../../lib/activitypub/url' 21import { getVideoActivityPubUrl } from '../../../lib/activitypub/url'
@@ -26,7 +27,6 @@ import {
26 authenticate, 27 authenticate,
27 paginationValidator, 28 paginationValidator,
28 setPagination, 29 setPagination,
29 setVideosSearch,
30 setVideosSort, 30 setVideosSort,
31 videosAddValidator, 31 videosAddValidator,
32 videosGetValidator, 32 videosGetValidator,
@@ -40,7 +40,6 @@ import { abuseVideoRouter } from './abuse'
40import { blacklistRouter } from './blacklist' 40import { blacklistRouter } from './blacklist'
41import { videoChannelRouter } from './channel' 41import { videoChannelRouter } from './channel'
42import { rateVideoRouter } from './rate' 42import { rateVideoRouter } from './rate'
43import { sendCreateViewToOrigin } from '../../../lib/activitypub/send/send-create'
44 43
45const videosRouter = express.Router() 44const videosRouter = express.Router()
46 45
@@ -84,6 +83,14 @@ videosRouter.get('/',
84 setPagination, 83 setPagination,
85 asyncMiddleware(listVideos) 84 asyncMiddleware(listVideos)
86) 85)
86videosRouter.get('/search',
87 videosSearchValidator,
88 paginationValidator,
89 videosSortValidator,
90 setVideosSort,
91 setPagination,
92 asyncMiddleware(searchVideos)
93)
87videosRouter.put('/:id', 94videosRouter.put('/:id',
88 authenticate, 95 authenticate,
89 asyncMiddleware(videosUpdateValidator), 96 asyncMiddleware(videosUpdateValidator),
@@ -115,16 +122,6 @@ videosRouter.delete('/:id',
115 asyncMiddleware(removeVideoRetryWrapper) 122 asyncMiddleware(removeVideoRetryWrapper)
116) 123)
117 124
118videosRouter.get('/search/:value',
119 videosSearchValidator,
120 paginationValidator,
121 videosSortValidator,
122 setVideosSort,
123 setPagination,
124 setVideosSearch,
125 asyncMiddleware(searchVideos)
126)
127
128// --------------------------------------------------------------------------- 125// ---------------------------------------------------------------------------
129 126
130export { 127export {
@@ -157,59 +154,64 @@ async function addVideoRetryWrapper (req: express.Request, res: express.Response
157 errorMessage: 'Cannot insert the video with many retries.' 154 errorMessage: 'Cannot insert the video with many retries.'
158 } 155 }
159 156
160 await retryTransactionWrapper(addVideo, options) 157 const video = await retryTransactionWrapper(addVideo, options)
161 158
162 // TODO : include Location of the new video -> 201 159 res.json({
163 res.type('json').status(204).end() 160 video: {
161 id: video.id,
162 uuid: video.uuid
163 }
164 }).end()
164} 165}
165 166
166async function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) { 167async function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) {
167 const videoInfo: VideoCreate = req.body 168 const videoInfo: VideoCreate = req.body
168 let videoUUID = ''
169 169
170 await db.sequelize.transaction(async t => { 170 // Prepare data so we don't block the transaction
171 const sequelizeOptions = { transaction: t } 171 const videoData = {
172 name: videoInfo.name,
173 remote: false,
174 extname: extname(videoPhysicalFile.filename),
175 category: videoInfo.category,
176 licence: videoInfo.licence,
177 language: videoInfo.language,
178 nsfw: videoInfo.nsfw,
179 description: videoInfo.description,
180 privacy: videoInfo.privacy,
181 duration: videoPhysicalFile['duration'], // duration was added by a previous middleware
182 channelId: res.locals.videoChannel.id
183 }
184 const video = db.Video.build(videoData)
185 video.url = getVideoActivityPubUrl(video)
172 186
173 const videoData = { 187 const videoFilePath = join(CONFIG.STORAGE.VIDEOS_DIR, videoPhysicalFile.filename)
174 name: videoInfo.name, 188 const videoFileHeight = await getVideoFileHeight(videoFilePath)
175 remote: false,
176 extname: extname(videoPhysicalFile.filename),
177 category: videoInfo.category,
178 licence: videoInfo.licence,
179 language: videoInfo.language,
180 nsfw: videoInfo.nsfw,
181 description: videoInfo.description,
182 privacy: videoInfo.privacy,
183 duration: videoPhysicalFile['duration'], // duration was added by a previous middleware
184 channelId: res.locals.videoChannel.id
185 }
186 const video = db.Video.build(videoData)
187 video.url = getVideoActivityPubUrl(video)
188 189
189 const videoFilePath = join(CONFIG.STORAGE.VIDEOS_DIR, videoPhysicalFile.filename) 190 const videoFileData = {
190 const videoFileHeight = await getVideoFileHeight(videoFilePath) 191 extname: extname(videoPhysicalFile.filename),
192 resolution: videoFileHeight,
193 size: videoPhysicalFile.size
194 }
195 const videoFile = db.VideoFile.build(videoFileData)
196 const videoDir = CONFIG.STORAGE.VIDEOS_DIR
197 const source = join(videoDir, videoPhysicalFile.filename)
198 const destination = join(videoDir, video.getVideoFilename(videoFile))
191 199
192 const videoFileData = { 200 await renamePromise(source, destination)
193 extname: extname(videoPhysicalFile.filename), 201 // This is important in case if there is another attempt in the retry process
194 resolution: videoFileHeight, 202 videoPhysicalFile.filename = video.getVideoFilename(videoFile)
195 size: videoPhysicalFile.size
196 }
197 const videoFile = db.VideoFile.build(videoFileData)
198 const videoDir = CONFIG.STORAGE.VIDEOS_DIR
199 const source = join(videoDir, videoPhysicalFile.filename)
200 const destination = join(videoDir, video.getVideoFilename(videoFile))
201 203
202 await renamePromise(source, destination) 204 const tasks = []
203 // This is important in case if there is another attempt in the retry process
204 videoPhysicalFile.filename = video.getVideoFilename(videoFile)
205 205
206 const tasks = [] 206 tasks.push(
207 video.createTorrentAndSetInfoHash(videoFile),
208 video.createThumbnail(videoFile),
209 video.createPreview(videoFile)
210 )
211 await Promise.all(tasks)
207 212
208 tasks.push( 213 return db.sequelize.transaction(async t => {
209 video.createTorrentAndSetInfoHash(videoFile), 214 const sequelizeOptions = { transaction: t }
210 video.createThumbnail(videoFile),
211 video.createPreview(videoFile)
212 )
213 215
214 if (CONFIG.TRANSCODING.ENABLED === true) { 216 if (CONFIG.TRANSCODING.ENABLED === true) {
215 // Put uuid because we don't have id auto incremented for now 217 // Put uuid because we don't have id auto incremented for now
@@ -217,21 +219,17 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
217 videoUUID: video.uuid 219 videoUUID: video.uuid
218 } 220 }
219 221
220 tasks.push( 222 await transcodingJobScheduler.createJob(t, 'videoFileOptimizer', dataInput)
221 transcodingJobScheduler.createJob(t, 'videoFileOptimizer', dataInput)
222 )
223 } 223 }
224 await Promise.all(tasks)
225 224
226 const videoCreated = await video.save(sequelizeOptions) 225 const videoCreated = await video.save(sequelizeOptions)
227 // Do not forget to add video channel information to the created video 226 // Do not forget to add video channel information to the created video
228 videoCreated.VideoChannel = res.locals.videoChannel 227 videoCreated.VideoChannel = res.locals.videoChannel
229 videoUUID = videoCreated.uuid
230 228
231 videoFile.videoId = video.id 229 videoFile.videoId = video.id
232
233 await videoFile.save(sequelizeOptions) 230 await videoFile.save(sequelizeOptions)
234 video.VideoFiles = [videoFile] 231
232 video.VideoFiles = [ videoFile ]
235 233
236 if (videoInfo.tags) { 234 if (videoInfo.tags) {
237 const tagInstances = await db.Tag.findOrCreateTags(videoInfo.tags, t) 235 const tagInstances = await db.Tag.findOrCreateTags(videoInfo.tags, t)
@@ -241,15 +239,17 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
241 } 239 }
242 240
243 // Let transcoding job send the video to friends because the video file extension might change 241 // Let transcoding job send the video to friends because the video file extension might change
244 if (CONFIG.TRANSCODING.ENABLED === true) return undefined 242 if (CONFIG.TRANSCODING.ENABLED === true) return videoCreated
245 // Don't send video to remote servers, it is private 243 // Don't send video to remote servers, it is private
246 if (video.privacy === VideoPrivacy.PRIVATE) return undefined 244 if (video.privacy === VideoPrivacy.PRIVATE) return videoCreated
247 245
248 await sendAddVideo(video, t) 246 await sendAddVideo(video, t)
249 await shareVideoByServer(video, t) 247 await shareVideoByServer(video, t)
250 })
251 248
252 logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoUUID) 249 logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoCreated.uuid)
250
251 return videoCreated
252 })
253} 253}
254 254
255async function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { 255async function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
@@ -280,7 +280,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
280 if (videoInfoToUpdate.licence !== undefined) videoInstance.set('licence', videoInfoToUpdate.licence) 280 if (videoInfoToUpdate.licence !== undefined) videoInstance.set('licence', videoInfoToUpdate.licence)
281 if (videoInfoToUpdate.language !== undefined) videoInstance.set('language', videoInfoToUpdate.language) 281 if (videoInfoToUpdate.language !== undefined) videoInstance.set('language', videoInfoToUpdate.language)
282 if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw) 282 if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw)
283 if (videoInfoToUpdate.privacy !== undefined) videoInstance.set('privacy', videoInfoToUpdate.privacy) 283 if (videoInfoToUpdate.privacy !== undefined) videoInstance.set('privacy', parseInt(videoInfoToUpdate.privacy.toString(), 10))
284 if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) 284 if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description)
285 285
286 const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) 286 const videoInstanceUpdated = await videoInstance.save(sequelizeOptions)
@@ -298,9 +298,9 @@ async function updateVideo (req: express.Request, res: express.Response) {
298 } 298 }
299 299
300 // Video is not private anymore, send a create action to remote servers 300 // Video is not private anymore, send a create action to remote servers
301 if (wasPrivateVideo === true && videoInstance.privacy !== VideoPrivacy.PRIVATE) { 301 if (wasPrivateVideo === true && videoInstanceUpdated.privacy !== VideoPrivacy.PRIVATE) {
302 await sendAddVideo(videoInstance, t) 302 await sendAddVideo(videoInstanceUpdated, t)
303 await shareVideoByServer(videoInstance, t) 303 await shareVideoByServer(videoInstanceUpdated, t)
304 } 304 }
305 }) 305 })
306 306
@@ -378,8 +378,7 @@ async function removeVideo (req: express.Request, res: express.Response) {
378 378
379async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) { 379async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
380 const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags( 380 const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags(
381 req.params.value, 381 req.query.search,
382 req.query.field,
383 req.query.start, 382 req.query.start,
384 req.query.count, 383 req.query.count,
385 req.query.sort 384 req.query.sort