aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-06-12 20:04:58 +0200
committerChocobozzz <me@florianbigard.com>2018-06-12 20:37:51 +0200
commit2186386cca113506791583cb07d6ccacba7af4e0 (patch)
tree3c214c0b5fbd64332624267fa6e51fd4a9cf6474 /server/controllers
parent6ccdf3a23ecec5ba2eeaf487fd1fafdc7606b4bf (diff)
downloadPeerTube-2186386cca113506791583cb07d6ccacba7af4e0.tar.gz
PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.tar.zst
PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.zip
Add concept of video state, and add ability to wait transcoding before
publishing a video
Diffstat (limited to 'server/controllers')
-rw-r--r--server/controllers/activitypub/client.ts8
-rw-r--r--server/controllers/activitypub/outbox.ts4
-rw-r--r--server/controllers/api/users.ts7
-rw-r--r--server/controllers/api/videos/index.ts47
4 files changed, 30 insertions, 36 deletions
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts
index 1c780783c..ea8e25f68 100644
--- a/server/controllers/activitypub/client.ts
+++ b/server/controllers/activitypub/client.ts
@@ -123,11 +123,11 @@ async function accountFollowingController (req: express.Request, res: express.Re
123async function videoController (req: express.Request, res: express.Response, next: express.NextFunction) { 123async function videoController (req: express.Request, res: express.Response, next: express.NextFunction) {
124 const video: VideoModel = res.locals.video 124 const video: VideoModel = res.locals.video
125 125
126 const audience = await getAudience(video.VideoChannel.Account.Actor, undefined, video.privacy === VideoPrivacy.PUBLIC) 126 const audience = getAudience(video.VideoChannel.Account.Actor, video.privacy === VideoPrivacy.PUBLIC)
127 const videoObject = audiencify(video.toActivityPubObject(), audience) 127 const videoObject = audiencify(video.toActivityPubObject(), audience)
128 128
129 if (req.path.endsWith('/activity')) { 129 if (req.path.endsWith('/activity')) {
130 const data = await createActivityData(video.url, video.VideoChannel.Account.Actor, videoObject, undefined, audience) 130 const data = createActivityData(video.url, video.VideoChannel.Account.Actor, videoObject, audience)
131 return activityPubResponse(activityPubContextify(data), res) 131 return activityPubResponse(activityPubContextify(data), res)
132 } 132 }
133 133
@@ -210,12 +210,12 @@ async function videoCommentController (req: express.Request, res: express.Respon
210 210
211 const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined) 211 const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined)
212 const isPublic = true // Comments are always public 212 const isPublic = true // Comments are always public
213 const audience = await getAudience(videoComment.Account.Actor, undefined, isPublic) 213 const audience = getAudience(videoComment.Account.Actor, isPublic)
214 214
215 const videoCommentObject = audiencify(videoComment.toActivityPubObject(threadParentComments), audience) 215 const videoCommentObject = audiencify(videoComment.toActivityPubObject(threadParentComments), audience)
216 216
217 if (req.path.endsWith('/activity')) { 217 if (req.path.endsWith('/activity')) {
218 const data = await createActivityData(videoComment.url, videoComment.Account.Actor, videoCommentObject, undefined, audience) 218 const data = createActivityData(videoComment.url, videoComment.Account.Actor, videoCommentObject, audience)
219 return activityPubResponse(activityPubContextify(data), res) 219 return activityPubResponse(activityPubContextify(data), res)
220 } 220 }
221 221
diff --git a/server/controllers/activitypub/outbox.ts b/server/controllers/activitypub/outbox.ts
index 2793ae267..ae7adcd4c 100644
--- a/server/controllers/activitypub/outbox.ts
+++ b/server/controllers/activitypub/outbox.ts
@@ -54,12 +54,12 @@ async function buildActivities (actor: ActorModel, start: number, count: number)
54 // This is a shared video 54 // This is a shared video
55 if (video.VideoShares !== undefined && video.VideoShares.length !== 0) { 55 if (video.VideoShares !== undefined && video.VideoShares.length !== 0) {
56 const videoShare = video.VideoShares[0] 56 const videoShare = video.VideoShares[0]
57 const announceActivity = await announceActivityData(videoShare.url, actor, video.url, undefined, createActivityAudience) 57 const announceActivity = announceActivityData(videoShare.url, actor, video.url, createActivityAudience)
58 58
59 activities.push(announceActivity) 59 activities.push(announceActivity)
60 } else { 60 } else {
61 const videoObject = video.toActivityPubObject() 61 const videoObject = video.toActivityPubObject()
62 const createActivity = await createActivityData(video.url, byActor, videoObject, undefined, createActivityAudience) 62 const createActivity = createActivityData(video.url, byActor, videoObject, createActivityAudience)
63 63
64 activities.push(createActivity) 64 activities.push(createActivity)
65 } 65 }
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index 8dff4b87c..2b40c44d9 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -166,7 +166,7 @@ export {
166 166
167async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) { 167async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
168 const user = res.locals.oauth.token.User as UserModel 168 const user = res.locals.oauth.token.User as UserModel
169 const resultList = await VideoModel.listAccountVideosForApi( 169 const resultList = await VideoModel.listUserVideosForApi(
170 user.Account.id, 170 user.Account.id,
171 req.query.start as number, 171 req.query.start as number,
172 req.query.count as number, 172 req.query.count as number,
@@ -174,7 +174,8 @@ async function getUserVideos (req: express.Request, res: express.Response, next:
174 false // Display my NSFW videos 174 false // Display my NSFW videos
175 ) 175 )
176 176
177 return res.json(getFormattedObjects(resultList.data, resultList.total)) 177 const additionalAttributes = { waitTranscoding: true, state: true }
178 return res.json(getFormattedObjects(resultList.data, resultList.total, { additionalAttributes }))
178} 179}
179 180
180async function createUserRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { 181async function createUserRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
@@ -318,7 +319,7 @@ async function updateMe (req: express.Request, res: express.Response, next: expr
318} 319}
319 320
320async function updateMyAvatar (req: express.Request, res: express.Response, next: express.NextFunction) { 321async function updateMyAvatar (req: express.Request, res: express.Response, next: express.NextFunction) {
321 const avatarPhysicalFile = req.files['avatarfile'][0] 322 const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ]
322 const user = res.locals.oauth.token.user 323 const user = res.locals.oauth.token.user
323 const actor = user.Account.Actor 324 const actor = user.Account.Actor
324 325
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 7f5e74626..9d9b2b0e1 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -1,6 +1,6 @@
1import * as express from 'express' 1import * as express from 'express'
2import { extname, join } from 'path' 2import { extname, join } from 'path'
3import { VideoCreate, VideoPrivacy, VideoUpdate } from '../../../../shared' 3import { VideoCreate, VideoPrivacy, VideoState, VideoUpdate } from '../../../../shared'
4import { renamePromise } from '../../../helpers/core-utils' 4import { renamePromise } from '../../../helpers/core-utils'
5import { retryTransactionWrapper } from '../../../helpers/database-utils' 5import { retryTransactionWrapper } from '../../../helpers/database-utils'
6import { getVideoFileResolution } from '../../../helpers/ffmpeg-utils' 6import { getVideoFileResolution } from '../../../helpers/ffmpeg-utils'
@@ -21,11 +21,11 @@ import {
21} from '../../../initializers' 21} from '../../../initializers'
22import { 22import {
23 changeVideoChannelShare, 23 changeVideoChannelShare,
24 federateVideoIfNeeded,
24 fetchRemoteVideoDescription, 25 fetchRemoteVideoDescription,
25 getVideoActivityPubUrl, 26 getVideoActivityPubUrl
26 shareVideoByServerAndChannel
27} from '../../../lib/activitypub' 27} from '../../../lib/activitypub'
28import { sendCreateVideo, sendCreateView, sendUpdateVideo } from '../../../lib/activitypub/send' 28import { sendCreateView } from '../../../lib/activitypub/send'
29import { JobQueue } from '../../../lib/job-queue' 29import { JobQueue } from '../../../lib/job-queue'
30import { Redis } from '../../../lib/redis' 30import { Redis } from '../../../lib/redis'
31import { 31import {
@@ -51,7 +51,7 @@ import { videoCommentRouter } from './comment'
51import { rateVideoRouter } from './rate' 51import { rateVideoRouter } from './rate'
52import { VideoFilter } from '../../../../shared/models/videos/video-query.type' 52import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
53import { VideoSortField } from '../../../../client/src/app/shared/video/sort-field.type' 53import { VideoSortField } from '../../../../client/src/app/shared/video/sort-field.type'
54import { isNSFWHidden, createReqFiles } from '../../../helpers/express-utils' 54import { createReqFiles, isNSFWHidden } from '../../../helpers/express-utils'
55 55
56const videosRouter = express.Router() 56const videosRouter = express.Router()
57 57
@@ -185,8 +185,10 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
185 category: videoInfo.category, 185 category: videoInfo.category,
186 licence: videoInfo.licence, 186 licence: videoInfo.licence,
187 language: videoInfo.language, 187 language: videoInfo.language,
188 commentsEnabled: videoInfo.commentsEnabled, 188 commentsEnabled: videoInfo.commentsEnabled || false,
189 nsfw: videoInfo.nsfw, 189 waitTranscoding: videoInfo.waitTranscoding || false,
190 state: CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED,
191 nsfw: videoInfo.nsfw || false,
190 description: videoInfo.description, 192 description: videoInfo.description,
191 support: videoInfo.support, 193 support: videoInfo.support,
192 privacy: videoInfo.privacy, 194 privacy: videoInfo.privacy,
@@ -194,19 +196,20 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
194 channelId: res.locals.videoChannel.id 196 channelId: res.locals.videoChannel.id
195 } 197 }
196 const video = new VideoModel(videoData) 198 const video = new VideoModel(videoData)
197 video.url = getVideoActivityPubUrl(video) 199 video.url = getVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object
198 200
201 // Build the file object
199 const { videoFileResolution } = await getVideoFileResolution(videoPhysicalFile.path) 202 const { videoFileResolution } = await getVideoFileResolution(videoPhysicalFile.path)
200
201 const videoFileData = { 203 const videoFileData = {
202 extname: extname(videoPhysicalFile.filename), 204 extname: extname(videoPhysicalFile.filename),
203 resolution: videoFileResolution, 205 resolution: videoFileResolution,
204 size: videoPhysicalFile.size 206 size: videoPhysicalFile.size
205 } 207 }
206 const videoFile = new VideoFileModel(videoFileData) 208 const videoFile = new VideoFileModel(videoFileData)
209
210 // Move physical file
207 const videoDir = CONFIG.STORAGE.VIDEOS_DIR 211 const videoDir = CONFIG.STORAGE.VIDEOS_DIR
208 const destination = join(videoDir, video.getVideoFilename(videoFile)) 212 const destination = join(videoDir, video.getVideoFilename(videoFile))
209
210 await renamePromise(videoPhysicalFile.path, destination) 213 await renamePromise(videoPhysicalFile.path, destination)
211 // This is important in case if there is another attempt in the retry process 214 // This is important in case if there is another attempt in the retry process
212 videoPhysicalFile.filename = video.getVideoFilename(videoFile) 215 videoPhysicalFile.filename = video.getVideoFilename(videoFile)
@@ -230,6 +233,7 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
230 await video.createPreview(videoFile) 233 await video.createPreview(videoFile)
231 } 234 }
232 235
236 // Create the torrent file
233 await video.createTorrentAndSetInfoHash(videoFile) 237 await video.createTorrentAndSetInfoHash(videoFile)
234 238
235 const videoCreated = await sequelizeTypescript.transaction(async t => { 239 const videoCreated = await sequelizeTypescript.transaction(async t => {
@@ -251,20 +255,14 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
251 video.Tags = tagInstances 255 video.Tags = tagInstances
252 } 256 }
253 257
254 // Let transcoding job send the video to friends because the video file extension might change 258 await federateVideoIfNeeded(video, true, t)
255 if (CONFIG.TRANSCODING.ENABLED === true) return videoCreated
256 // Don't send video to remote servers, it is private
257 if (video.privacy === VideoPrivacy.PRIVATE) return videoCreated
258
259 await sendCreateVideo(video, t)
260 await shareVideoByServerAndChannel(video, t)
261 259
262 logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoCreated.uuid) 260 logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoCreated.uuid)
263 261
264 return videoCreated 262 return videoCreated
265 }) 263 })
266 264
267 if (CONFIG.TRANSCODING.ENABLED === true) { 265 if (video.state === VideoState.TO_TRANSCODE) {
268 // Put uuid because we don't have id auto incremented for now 266 // Put uuid because we don't have id auto incremented for now
269 const dataInput = { 267 const dataInput = {
270 videoUUID: videoCreated.uuid, 268 videoUUID: videoCreated.uuid,
@@ -318,6 +316,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
318 if (videoInfoToUpdate.licence !== undefined) videoInstance.set('licence', videoInfoToUpdate.licence) 316 if (videoInfoToUpdate.licence !== undefined) videoInstance.set('licence', videoInfoToUpdate.licence)
319 if (videoInfoToUpdate.language !== undefined) videoInstance.set('language', videoInfoToUpdate.language) 317 if (videoInfoToUpdate.language !== undefined) videoInstance.set('language', videoInfoToUpdate.language)
320 if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw) 318 if (videoInfoToUpdate.nsfw !== undefined) videoInstance.set('nsfw', videoInfoToUpdate.nsfw)
319 if (videoInfoToUpdate.waitTranscoding !== undefined) videoInstance.set('waitTranscoding', videoInfoToUpdate.waitTranscoding)
321 if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support) 320 if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support)
322 if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) 321 if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description)
323 if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled) 322 if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled)
@@ -343,19 +342,13 @@ async function updateVideo (req: express.Request, res: express.Response) {
343 // Video channel update? 342 // Video channel update?
344 if (res.locals.videoChannel && videoInstanceUpdated.channelId !== res.locals.videoChannel.id) { 343 if (res.locals.videoChannel && videoInstanceUpdated.channelId !== res.locals.videoChannel.id) {
345 await videoInstanceUpdated.$set('VideoChannel', res.locals.videoChannel, { transaction: t }) 344 await videoInstanceUpdated.$set('VideoChannel', res.locals.videoChannel, { transaction: t })
346 videoInstance.VideoChannel = res.locals.videoChannel 345 videoInstanceUpdated.VideoChannel = res.locals.videoChannel
347 346
348 if (wasPrivateVideo === false) await changeVideoChannelShare(videoInstanceUpdated, oldVideoChannel, t) 347 if (wasPrivateVideo === false) await changeVideoChannelShare(videoInstanceUpdated, oldVideoChannel, t)
349 } 348 }
350 349
351 // Now we'll update the video's meta data to our friends 350 const isNewVideo = wasPrivateVideo && videoInstanceUpdated.privacy !== VideoPrivacy.PRIVATE
352 if (wasPrivateVideo === false) await sendUpdateVideo(videoInstanceUpdated, t) 351 await federateVideoIfNeeded(videoInstanceUpdated, isNewVideo)
353
354 // Video is not private anymore, send a create action to remote servers
355 if (wasPrivateVideo === true && videoInstanceUpdated.privacy !== VideoPrivacy.PRIVATE) {
356 await sendCreateVideo(videoInstanceUpdated, t)
357 await shareVideoByServerAndChannel(videoInstanceUpdated, t)
358 }
359 }) 352 })
360 353
361 logger.info('Video with name %s and uuid %s updated.', videoInstance.name, videoInstance.uuid) 354 logger.info('Video with name %s and uuid %s updated.', videoInstance.name, videoInstance.uuid)