X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fcontrollers%2Fapi%2Fvideos%2Flive.ts;h=c6f038079750faf157af60c7785b236cbe982691;hb=f012319a644fe8d9d33f2f567fa828442a3b39fd;hp=d08ef9869f46fe793492f79cd2db0ef43f12c391;hpb=c6c0fa6cd8fe8f752463d8982c3dbcd448739c4e;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/controllers/api/videos/live.ts b/server/controllers/api/videos/live.ts index d08ef9869..c6f038079 100644 --- a/server/controllers/api/videos/live.ts +++ b/server/controllers/api/videos/live.ts @@ -1,32 +1,25 @@ -import * as express from 'express' -import { v4 as uuidv4 } from 'uuid' +import express from 'express' +import { exists } from '@server/helpers/custom-validators/misc' import { createReqFiles } from '@server/helpers/express-utils' -import { CONFIG } from '@server/initializers/config' import { ASSETS_PATH, MIMETYPES } from '@server/initializers/constants' -import { getVideoActivityPubUrl } from '@server/lib/activitypub/url' -import { videoLiveAddValidator, videoLiveGetValidator } from '@server/middlewares/validators/videos/video-live' +import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' +import { federateVideoIfNeeded } from '@server/lib/activitypub/videos' +import { Hooks } from '@server/lib/plugins/hooks' +import { buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' +import { videoLiveAddValidator, videoLiveGetValidator, videoLiveUpdateValidator } from '@server/middlewares/validators/videos/video-live' import { VideoLiveModel } from '@server/models/video/video-live' import { MVideoDetails, MVideoFullLight } from '@server/types/models' -import { VideoCreate, VideoPrivacy, VideoState } from '../../../../shared' -import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' +import { buildUUID, uuidToShort } from '@shared/extra-utils' +import { HttpStatusCode, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, VideoState } from '@shared/models' import { logger } from '../../../helpers/logger' import { sequelizeTypescript } from '../../../initializers/database' -import { createVideoMiniatureFromExisting } from '../../../lib/thumbnail' +import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail' import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate } from '../../../middlewares' -import { TagModel } from '../../../models/video/tag' import { VideoModel } from '../../../models/video/video' -import { buildLocalVideoFromCreate } from '@server/lib/video' const liveRouter = express.Router() -const reqVideoFileLive = createReqFiles( - [ 'thumbnailfile', 'previewfile' ], - MIMETYPES.IMAGE.MIMETYPE_EXT, - { - thumbnailfile: CONFIG.STORAGE.TMP_DIR, - previewfile: CONFIG.STORAGE.TMP_DIR - } -) +const reqVideoFileLive = createReqFiles([ 'thumbnailfile', 'previewfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT) liveRouter.post('/live', authenticate, @@ -38,7 +31,14 @@ liveRouter.post('/live', liveRouter.get('/live/:videoId', authenticate, asyncMiddleware(videoLiveGetValidator), - asyncRetryTransactionMiddleware(getVideoLive) + getLiveVideo +) + +liveRouter.put('/live/:videoId', + authenticate, + asyncMiddleware(videoLiveGetValidator), + videoLiveUpdateValidator, + asyncRetryTransactionMiddleware(updateLiveVideo) ) // --------------------------------------------------------------------------- @@ -49,36 +49,62 @@ export { // --------------------------------------------------------------------------- -async function getVideoLive (req: express.Request, res: express.Response) { +function getLiveVideo (req: express.Request, res: express.Response) { const videoLive = res.locals.videoLive return res.json(videoLive.toFormattedJSON()) } +async function updateLiveVideo (req: express.Request, res: express.Response) { + const body: LiveVideoUpdate = req.body + + const video = res.locals.videoAll + const videoLive = res.locals.videoLive + + if (exists(body.saveReplay)) videoLive.saveReplay = body.saveReplay + if (exists(body.permanentLive)) videoLive.permanentLive = body.permanentLive + if (exists(body.latencyMode)) videoLive.latencyMode = body.latencyMode + + video.VideoLive = await videoLive.save() + + await federateVideoIfNeeded(video, false) + + return res.status(HttpStatusCode.NO_CONTENT_204).end() +} + async function addLiveVideo (req: express.Request, res: express.Response) { - const videoInfo: VideoCreate = req.body + const videoInfo: LiveVideoCreate = req.body // Prepare data so we don't block the transaction - const videoData = buildLocalVideoFromCreate(videoInfo, res.locals.videoChannel.id) - videoData.isLive = true + let videoData = buildLocalVideoFromReq(videoInfo, res.locals.videoChannel.id) + videoData = await Hooks.wrapObject(videoData, 'filter:api.video.live.video-attribute.result') - const videoLive = new VideoLiveModel() - videoLive.streamKey = uuidv4() + videoData.isLive = true + videoData.state = VideoState.WAITING_FOR_LIVE + videoData.duration = 0 const video = new VideoModel(videoData) as MVideoDetails - video.url = getVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object - - // Process thumbnail or create it from the video - const thumbnailField = req.files ? req.files['thumbnailfile'] : null - const thumbnailModel = thumbnailField - ? await createVideoMiniatureFromExisting(thumbnailField[0].path, video, ThumbnailType.MINIATURE, false) - : await createVideoMiniatureFromExisting(ASSETS_PATH.DEFAULT_LIVE_BACKGROUND, video, ThumbnailType.MINIATURE, true) + video.url = getLocalVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object - // Process preview or create it from the video - const previewField = req.files ? req.files['previewfile'] : null - const previewModel = previewField - ? await createVideoMiniatureFromExisting(previewField[0].path, video, ThumbnailType.PREVIEW, false) - : await createVideoMiniatureFromExisting(ASSETS_PATH.DEFAULT_LIVE_BACKGROUND, video, ThumbnailType.PREVIEW, true) + const videoLive = new VideoLiveModel() + videoLive.saveReplay = videoInfo.saveReplay || false + videoLive.permanentLive = videoInfo.permanentLive || false + videoLive.latencyMode = videoInfo.latencyMode || LiveVideoLatencyMode.DEFAULT + videoLive.streamKey = buildUUID() + + const [ thumbnailModel, previewModel ] = await buildVideoThumbnailsFromReq({ + video, + files: req.files, + fallback: type => { + return updateVideoMiniatureFromExisting({ + inputPath: ASSETS_PATH.DEFAULT_LIVE_BACKGROUND, + video, + type, + automaticallyGenerated: true, + keepOriginal: true + }) + } + }) const { videoCreated } = await sequelizeTypescript.transaction(async t => { const sequelizeOptions = { transaction: t } @@ -92,24 +118,23 @@ async function addLiveVideo (req: express.Request, res: express.Response) { videoCreated.VideoChannel = res.locals.videoChannel videoLive.videoId = videoCreated.id - await videoLive.save(sequelizeOptions) + videoCreated.VideoLive = await videoLive.save(sequelizeOptions) - // Create tags - if (videoInfo.tags !== undefined) { - const tagInstances = await TagModel.findOrCreateTags(videoInfo.tags, t) + await setVideoTags({ video, tags: videoInfo.tags, transaction: t }) - await video.$set('Tags', tagInstances, sequelizeOptions) - video.Tags = tagInstances - } + await federateVideoIfNeeded(videoCreated, true, t) logger.info('Video live %s with uuid %s created.', videoInfo.name, videoCreated.uuid) return { videoCreated } }) + Hooks.runAction('action:api.live-video.created', { video: videoCreated, req, res }) + return res.json({ video: { id: videoCreated.id, + shortUUID: uuidToShort(videoCreated.uuid), uuid: videoCreated.uuid } })