aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api/videos/live.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers/api/videos/live.ts')
-rw-r--r--server/controllers/api/videos/live.ts224
1 files changed, 0 insertions, 224 deletions
diff --git a/server/controllers/api/videos/live.ts b/server/controllers/api/videos/live.ts
deleted file mode 100644
index e19e8c652..000000000
--- a/server/controllers/api/videos/live.ts
+++ /dev/null
@@ -1,224 +0,0 @@
1import express from 'express'
2import { exists } from '@server/helpers/custom-validators/misc'
3import { createReqFiles } from '@server/helpers/express-utils'
4import { getFormattedObjects } from '@server/helpers/utils'
5import { ASSETS_PATH, MIMETYPES } from '@server/initializers/constants'
6import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url'
7import { federateVideoIfNeeded } from '@server/lib/activitypub/videos'
8import { Hooks } from '@server/lib/plugins/hooks'
9import { buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
10import {
11 videoLiveAddValidator,
12 videoLiveFindReplaySessionValidator,
13 videoLiveGetValidator,
14 videoLiveListSessionsValidator,
15 videoLiveUpdateValidator
16} from '@server/middlewares/validators/videos/video-live'
17import { VideoLiveModel } from '@server/models/video/video-live'
18import { VideoLiveSessionModel } from '@server/models/video/video-live-session'
19import { MVideoDetails, MVideoFullLight, MVideoLive } from '@server/types/models'
20import { buildUUID, uuidToShort } from '@shared/extra-utils'
21import { HttpStatusCode, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, UserRight, VideoPrivacy, VideoState } from '@shared/models'
22import { logger } from '../../../helpers/logger'
23import { sequelizeTypescript } from '../../../initializers/database'
24import { updateLocalVideoMiniatureFromExisting } from '../../../lib/thumbnail'
25import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, optionalAuthenticate } from '../../../middlewares'
26import { VideoModel } from '../../../models/video/video'
27import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting'
28import { VideoPasswordModel } from '@server/models/video/video-password'
29
30const liveRouter = express.Router()
31
32const reqVideoFileLive = createReqFiles([ 'thumbnailfile', 'previewfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT)
33
34liveRouter.post('/live',
35 authenticate,
36 reqVideoFileLive,
37 asyncMiddleware(videoLiveAddValidator),
38 asyncRetryTransactionMiddleware(addLiveVideo)
39)
40
41liveRouter.get('/live/:videoId/sessions',
42 authenticate,
43 asyncMiddleware(videoLiveGetValidator),
44 videoLiveListSessionsValidator,
45 asyncMiddleware(getLiveVideoSessions)
46)
47
48liveRouter.get('/live/:videoId',
49 optionalAuthenticate,
50 asyncMiddleware(videoLiveGetValidator),
51 getLiveVideo
52)
53
54liveRouter.put('/live/:videoId',
55 authenticate,
56 asyncMiddleware(videoLiveGetValidator),
57 videoLiveUpdateValidator,
58 asyncRetryTransactionMiddleware(updateLiveVideo)
59)
60
61liveRouter.get('/:videoId/live-session',
62 asyncMiddleware(videoLiveFindReplaySessionValidator),
63 getLiveReplaySession
64)
65
66// ---------------------------------------------------------------------------
67
68export {
69 liveRouter
70}
71
72// ---------------------------------------------------------------------------
73
74function getLiveVideo (req: express.Request, res: express.Response) {
75 const videoLive = res.locals.videoLive
76
77 return res.json(videoLive.toFormattedJSON(canSeePrivateLiveInformation(res)))
78}
79
80function getLiveReplaySession (req: express.Request, res: express.Response) {
81 const session = res.locals.videoLiveSession
82
83 return res.json(session.toFormattedJSON())
84}
85
86async function getLiveVideoSessions (req: express.Request, res: express.Response) {
87 const videoLive = res.locals.videoLive
88
89 const data = await VideoLiveSessionModel.listSessionsOfLiveForAPI({ videoId: videoLive.videoId })
90
91 return res.json(getFormattedObjects(data, data.length))
92}
93
94function canSeePrivateLiveInformation (res: express.Response) {
95 const user = res.locals.oauth?.token.User
96 if (!user) return false
97
98 if (user.hasRight(UserRight.GET_ANY_LIVE)) return true
99
100 const video = res.locals.videoAll
101 return video.VideoChannel.Account.userId === user.id
102}
103
104async function updateLiveVideo (req: express.Request, res: express.Response) {
105 const body: LiveVideoUpdate = req.body
106
107 const video = res.locals.videoAll
108 const videoLive = res.locals.videoLive
109
110 const newReplaySettingModel = await updateReplaySettings(videoLive, body)
111 if (newReplaySettingModel) videoLive.replaySettingId = newReplaySettingModel.id
112 else videoLive.replaySettingId = null
113
114 if (exists(body.permanentLive)) videoLive.permanentLive = body.permanentLive
115 if (exists(body.latencyMode)) videoLive.latencyMode = body.latencyMode
116
117 video.VideoLive = await videoLive.save()
118
119 await federateVideoIfNeeded(video, false)
120
121 return res.status(HttpStatusCode.NO_CONTENT_204).end()
122}
123
124async function updateReplaySettings (videoLive: MVideoLive, body: LiveVideoUpdate) {
125 if (exists(body.saveReplay)) videoLive.saveReplay = body.saveReplay
126
127 // The live replay is not saved anymore, destroy the old model if it existed
128 if (!videoLive.saveReplay) {
129 if (videoLive.replaySettingId) {
130 await VideoLiveReplaySettingModel.removeSettings(videoLive.replaySettingId)
131 }
132
133 return undefined
134 }
135
136 const settingModel = videoLive.replaySettingId
137 ? await VideoLiveReplaySettingModel.load(videoLive.replaySettingId)
138 : new VideoLiveReplaySettingModel()
139
140 if (exists(body.replaySettings.privacy)) settingModel.privacy = body.replaySettings.privacy
141
142 return settingModel.save()
143}
144
145async function addLiveVideo (req: express.Request, res: express.Response) {
146 const videoInfo: LiveVideoCreate = req.body
147
148 // Prepare data so we don't block the transaction
149 let videoData = buildLocalVideoFromReq(videoInfo, res.locals.videoChannel.id)
150 videoData = await Hooks.wrapObject(videoData, 'filter:api.video.live.video-attribute.result')
151
152 videoData.isLive = true
153 videoData.state = VideoState.WAITING_FOR_LIVE
154 videoData.duration = 0
155
156 const video = new VideoModel(videoData) as MVideoDetails
157 video.url = getLocalVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object
158
159 const videoLive = new VideoLiveModel()
160 videoLive.saveReplay = videoInfo.saveReplay || false
161 videoLive.permanentLive = videoInfo.permanentLive || false
162 videoLive.latencyMode = videoInfo.latencyMode || LiveVideoLatencyMode.DEFAULT
163 videoLive.streamKey = buildUUID()
164
165 const [ thumbnailModel, previewModel ] = await buildVideoThumbnailsFromReq({
166 video,
167 files: req.files,
168 fallback: type => {
169 return updateLocalVideoMiniatureFromExisting({
170 inputPath: ASSETS_PATH.DEFAULT_LIVE_BACKGROUND,
171 video,
172 type,
173 automaticallyGenerated: true,
174 keepOriginal: true
175 })
176 }
177 })
178
179 const { videoCreated } = await sequelizeTypescript.transaction(async t => {
180 const sequelizeOptions = { transaction: t }
181
182 const videoCreated = await video.save(sequelizeOptions) as MVideoFullLight
183
184 if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
185 if (previewModel) await videoCreated.addAndSaveThumbnail(previewModel, t)
186
187 // Do not forget to add video channel information to the created video
188 videoCreated.VideoChannel = res.locals.videoChannel
189
190 if (videoLive.saveReplay) {
191 const replaySettings = new VideoLiveReplaySettingModel({
192 privacy: videoInfo.replaySettings.privacy
193 })
194 await replaySettings.save(sequelizeOptions)
195
196 videoLive.replaySettingId = replaySettings.id
197 }
198
199 videoLive.videoId = videoCreated.id
200 videoCreated.VideoLive = await videoLive.save(sequelizeOptions)
201
202 await setVideoTags({ video, tags: videoInfo.tags, transaction: t })
203
204 await federateVideoIfNeeded(videoCreated, true, t)
205
206 if (videoInfo.privacy === VideoPrivacy.PASSWORD_PROTECTED) {
207 await VideoPasswordModel.addPasswords(videoInfo.videoPasswords, video.id, t)
208 }
209
210 logger.info('Video live %s with uuid %s created.', videoInfo.name, videoCreated.uuid)
211
212 return { videoCreated }
213 })
214
215 Hooks.runAction('action:api.live-video.created', { video: videoCreated, req, res })
216
217 return res.json({
218 video: {
219 id: videoCreated.id,
220 shortUUID: uuidToShort(videoCreated.uuid),
221 uuid: videoCreated.uuid
222 }
223 })
224}