aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-11-03 15:33:30 +0100
committerChocobozzz <chocobozzz@cpy.re>2020-11-09 15:33:04 +0100
commit97969c4edf51b37eee691adba43368bb0fbb729b (patch)
treec1089f898fb936d75651630afcf406995eeb9fba /server/lib
parentaf4ae64f6faf38f8179f2e07d3cd4ad60006be92 (diff)
downloadPeerTube-97969c4edf51b37eee691adba43368bb0fbb729b.tar.gz
PeerTube-97969c4edf51b37eee691adba43368bb0fbb729b.tar.zst
PeerTube-97969c4edf51b37eee691adba43368bb0fbb729b.zip
Add check constraints live tests
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/job-queue/handlers/video-live-ending.ts19
-rw-r--r--server/lib/live-manager.ts14
-rw-r--r--server/lib/user.ts6
-rw-r--r--server/lib/video.ts15
4 files changed, 32 insertions, 22 deletions
diff --git a/server/lib/job-queue/handlers/video-live-ending.ts b/server/lib/job-queue/handlers/video-live-ending.ts
index 32eeff4d1..1e964726e 100644
--- a/server/lib/job-queue/handlers/video-live-ending.ts
+++ b/server/lib/job-queue/handlers/video-live-ending.ts
@@ -8,9 +8,10 @@ import { generateHlsPlaylist } from '@server/lib/video-transcoding'
8import { VideoModel } from '@server/models/video/video' 8import { VideoModel } from '@server/models/video/video'
9import { VideoLiveModel } from '@server/models/video/video-live' 9import { VideoLiveModel } from '@server/models/video/video-live'
10import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist' 10import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
11import { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models' 11import { MStreamingPlaylist, MVideo, MVideoLive, MVideoWithFile } from '@server/types/models'
12import { VideoLiveEndingPayload, VideoState } from '@shared/models' 12import { VideoLiveEndingPayload, VideoState } from '@shared/models'
13import { logger } from '../../../helpers/logger' 13import { logger } from '../../../helpers/logger'
14import { VideoFileModel } from '@server/models/video/video-file'
14 15
15async function processVideoLiveEnding (job: Bull.Job) { 16async function processVideoLiveEnding (job: Bull.Job) {
16 const payload = job.data as VideoLiveEndingPayload 17 const payload = job.data as VideoLiveEndingPayload
@@ -60,6 +61,10 @@ async function saveLive (video: MVideo, live: MVideoLive) {
60 const segmentFiles = files.filter(f => f.startsWith(shouldStartWith) && f.endsWith('.ts')) 61 const segmentFiles = files.filter(f => f.startsWith(shouldStartWith) && f.endsWith('.ts'))
61 await hlsPlaylistToFragmentedMP4(hlsDirectory, segmentFiles, mp4TmpName) 62 await hlsPlaylistToFragmentedMP4(hlsDirectory, segmentFiles, mp4TmpName)
62 63
64 for (const file of segmentFiles) {
65 await remove(join(hlsDirectory, file))
66 }
67
63 if (!duration) { 68 if (!duration) {
64 duration = await getDurationFromVideoFile(mp4TmpName) 69 duration = await getDurationFromVideoFile(mp4TmpName)
65 } 70 }
@@ -77,8 +82,13 @@ async function saveLive (video: MVideo, live: MVideoLive) {
77 82
78 await video.save() 83 await video.save()
79 84
85 // Remove old HLS playlist video files
80 const videoWithFiles = await VideoModel.loadWithFiles(video.id) 86 const videoWithFiles = await VideoModel.loadWithFiles(video.id)
81 87
88 const hlsPlaylist = videoWithFiles.getHLSPlaylist()
89 await VideoFileModel.removeHLSFilesOfVideoId(hlsPlaylist.id)
90 hlsPlaylist.VideoFiles = []
91
82 for (const resolution of resolutions) { 92 for (const resolution of resolutions) {
83 const videoInputPath = buildMP4TmpName(resolution) 93 const videoInputPath = buildMP4TmpName(resolution)
84 const { isPortraitMode } = await getVideoFileResolution(videoInputPath) 94 const { isPortraitMode } = await getVideoFileResolution(videoInputPath)
@@ -90,12 +100,11 @@ async function saveLive (video: MVideo, live: MVideoLive) {
90 copyCodecs: true, 100 copyCodecs: true,
91 isPortraitMode 101 isPortraitMode
92 }) 102 })
93 }
94 103
95 video.state = VideoState.PUBLISHED 104 await remove(join(hlsDirectory, videoInputPath))
96 await video.save() 105 }
97 106
98 await publishAndFederateIfNeeded(video) 107 await publishAndFederateIfNeeded(video, true)
99} 108}
100 109
101async function cleanupLive (video: MVideo, streamingPlaylist: MStreamingPlaylist) { 110async function cleanupLive (video: MVideo, streamingPlaylist: MStreamingPlaylist) {
diff --git a/server/lib/live-manager.ts b/server/lib/live-manager.ts
index e115d2d50..2d8f906e9 100644
--- a/server/lib/live-manager.ts
+++ b/server/lib/live-manager.ts
@@ -133,10 +133,8 @@ class LiveManager {
133 const sessionId = this.videoSessions.get(videoId) 133 const sessionId = this.videoSessions.get(videoId)
134 if (!sessionId) return 134 if (!sessionId) return
135 135
136 this.videoSessions.delete(videoId)
136 this.abortSession(sessionId) 137 this.abortSession(sessionId)
137
138 this.onEndTransmuxing(videoId, true)
139 .catch(err => logger.error('Cannot end transmuxing of video %d.', videoId, { err }))
140 } 138 }
141 139
142 private getContext () { 140 private getContext () {
@@ -259,9 +257,12 @@ class LiveManager {
259 updateSegment(segmentPath) 257 updateSegment(segmentPath)
260 258
261 if (this.isDurationConstraintValid(startStreamDateTime) !== true) { 259 if (this.isDurationConstraintValid(startStreamDateTime) !== true) {
260 logger.info('Stopping session of %s: max duration exceeded.', videoUUID)
261
262 this.stopSessionOf(videoLive.videoId) 262 this.stopSessionOf(videoLive.videoId)
263 } 263 }
264 264
265 // Check user quota if the user enabled replay saving
265 if (videoLive.saveReplay === true) { 266 if (videoLive.saveReplay === true) {
266 stat(segmentPath) 267 stat(segmentPath)
267 .then(segmentStat => { 268 .then(segmentStat => {
@@ -270,6 +271,8 @@ class LiveManager {
270 .then(() => this.isQuotaConstraintValid(user, videoLive)) 271 .then(() => this.isQuotaConstraintValid(user, videoLive))
271 .then(quotaValid => { 272 .then(quotaValid => {
272 if (quotaValid !== true) { 273 if (quotaValid !== true) {
274 logger.info('Stopping session of %s: user quota exceeded.', videoUUID)
275
273 this.stopSessionOf(videoLive.videoId) 276 this.stopSessionOf(videoLive.videoId)
274 } 277 }
275 }) 278 })
@@ -319,7 +322,7 @@ class LiveManager {
319 onFFmpegEnded() 322 onFFmpegEnded()
320 323
321 // Don't care that we killed the ffmpeg process 324 // Don't care that we killed the ffmpeg process
322 if (err?.message?.includes('SIGINT')) return 325 if (err?.message?.includes('Exiting normally')) return
323 326
324 logger.error('Live transcoding error.', { err, stdout, stderr }) 327 logger.error('Live transcoding error.', { err, stdout, stderr })
325 328
@@ -348,8 +351,7 @@ class LiveManager {
348 } 351 }
349 }, { delay: cleanupNow ? 0 : VIDEO_LIVE.CLEANUP_DELAY }) 352 }, { delay: cleanupNow ? 0 : VIDEO_LIVE.CLEANUP_DELAY })
350 353
351 // FIXME: use end 354 fullVideo.state = VideoState.LIVE_ENDED
352 fullVideo.state = VideoState.WAITING_FOR_LIVE
353 await fullVideo.save() 355 await fullVideo.save()
354 356
355 PeerTubeSocket.Instance.sendVideoLiveNewState(fullVideo) 357 PeerTubeSocket.Instance.sendVideoLiveNewState(fullVideo)
diff --git a/server/lib/user.ts b/server/lib/user.ts
index d3338f329..7d6497302 100644
--- a/server/lib/user.ts
+++ b/server/lib/user.ts
@@ -18,8 +18,6 @@ import { Redis } from './redis'
18import { createLocalVideoChannel } from './video-channel' 18import { createLocalVideoChannel } from './video-channel'
19import { createWatchLaterPlaylist } from './video-playlist' 19import { createWatchLaterPlaylist } from './video-playlist'
20 20
21import memoizee = require('memoizee')
22
23type ChannelNames = { name: string, displayName: string } 21type ChannelNames = { name: string, displayName: string }
24 22
25async function createUserAccountAndChannelAndPlaylist (parameters: { 23async function createUserAccountAndChannelAndPlaylist (parameters: {
@@ -152,8 +150,8 @@ async function isAbleToUploadVideo (userId: number, size: number) {
152 if (user.videoQuota === -1 && user.videoQuotaDaily === -1) return Promise.resolve(true) 150 if (user.videoQuota === -1 && user.videoQuotaDaily === -1) return Promise.resolve(true)
153 151
154 const [ totalBytes, totalBytesDaily ] = await Promise.all([ 152 const [ totalBytes, totalBytesDaily ] = await Promise.all([
155 getOriginalVideoFileTotalFromUser(user.id), 153 getOriginalVideoFileTotalFromUser(user),
156 getOriginalVideoFileTotalDailyFromUser(user.id) 154 getOriginalVideoFileTotalDailyFromUser(user)
157 ]) 155 ])
158 156
159 const uploadedTotal = size + totalBytes 157 const uploadedTotal = size + totalBytes
diff --git a/server/lib/video.ts b/server/lib/video.ts
index 81b7c4159..8d9918b2d 100644
--- a/server/lib/video.ts
+++ b/server/lib/video.ts
@@ -4,7 +4,7 @@ import { TagModel } from '@server/models/video/tag'
4import { VideoModel } from '@server/models/video/video' 4import { VideoModel } from '@server/models/video/video'
5import { FilteredModelAttributes } from '@server/types' 5import { FilteredModelAttributes } from '@server/types'
6import { MTag, MThumbnail, MVideoTag, MVideoThumbnail, MVideoUUID } from '@server/types/models' 6import { MTag, MThumbnail, MVideoTag, MVideoThumbnail, MVideoUUID } from '@server/types/models'
7import { ThumbnailType, VideoCreate, VideoPrivacy } from '@shared/models' 7import { ThumbnailType, VideoCreate, VideoPrivacy, VideoState } from '@shared/models'
8import { federateVideoIfNeeded } from './activitypub/videos' 8import { federateVideoIfNeeded } from './activitypub/videos'
9import { Notifier } from './notifier' 9import { Notifier } from './notifier'
10import { createVideoMiniatureFromExisting } from './thumbnail' 10import { createVideoMiniatureFromExisting } from './thumbnail'
@@ -81,8 +81,8 @@ async function setVideoTags (options: {
81 } 81 }
82} 82}
83 83
84async function publishAndFederateIfNeeded (video: MVideoUUID) { 84async function publishAndFederateIfNeeded (video: MVideoUUID, wasLive = false) {
85 const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => { 85 const result = await sequelizeTypescript.transaction(async t => {
86 // Maybe the video changed in database, refresh it 86 // Maybe the video changed in database, refresh it
87 const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t) 87 const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t)
88 // Video does not exist anymore 88 // Video does not exist anymore
@@ -92,14 +92,15 @@ async function publishAndFederateIfNeeded (video: MVideoUUID) {
92 const videoPublished = await videoDatabase.publishIfNeededAndSave(t) 92 const videoPublished = await videoDatabase.publishIfNeededAndSave(t)
93 93
94 // If the video was not published, we consider it is a new one for other instances 94 // If the video was not published, we consider it is a new one for other instances
95 await federateVideoIfNeeded(videoDatabase, videoPublished, t) 95 // Live videos are always federated, so it's not a new video
96 await federateVideoIfNeeded(videoDatabase, !wasLive && videoPublished, t)
96 97
97 return { videoDatabase, videoPublished } 98 return { videoDatabase, videoPublished }
98 }) 99 })
99 100
100 if (videoPublished) { 101 if (result?.videoPublished) {
101 Notifier.Instance.notifyOnNewVideoIfNeeded(videoDatabase) 102 Notifier.Instance.notifyOnNewVideoIfNeeded(result.videoDatabase)
102 Notifier.Instance.notifyOnVideoPublishedAfterTranscoding(videoDatabase) 103 Notifier.Instance.notifyOnVideoPublishedAfterTranscoding(result.videoDatabase)
103 } 104 }
104} 105}
105 106