diff options
author | Chocobozzz <me@florianbigard.com> | 2020-11-03 15:33:30 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2020-11-09 15:33:04 +0100 |
commit | 97969c4edf51b37eee691adba43368bb0fbb729b (patch) | |
tree | c1089f898fb936d75651630afcf406995eeb9fba /server/lib | |
parent | af4ae64f6faf38f8179f2e07d3cd4ad60006be92 (diff) | |
download | PeerTube-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.ts | 19 | ||||
-rw-r--r-- | server/lib/live-manager.ts | 14 | ||||
-rw-r--r-- | server/lib/user.ts | 6 | ||||
-rw-r--r-- | server/lib/video.ts | 15 |
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' | |||
8 | import { VideoModel } from '@server/models/video/video' | 8 | import { VideoModel } from '@server/models/video/video' |
9 | import { VideoLiveModel } from '@server/models/video/video-live' | 9 | import { VideoLiveModel } from '@server/models/video/video-live' |
10 | import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist' | 10 | import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist' |
11 | import { MStreamingPlaylist, MVideo, MVideoLive } from '@server/types/models' | 11 | import { MStreamingPlaylist, MVideo, MVideoLive, MVideoWithFile } from '@server/types/models' |
12 | import { VideoLiveEndingPayload, VideoState } from '@shared/models' | 12 | import { VideoLiveEndingPayload, VideoState } from '@shared/models' |
13 | import { logger } from '../../../helpers/logger' | 13 | import { logger } from '../../../helpers/logger' |
14 | import { VideoFileModel } from '@server/models/video/video-file' | ||
14 | 15 | ||
15 | async function processVideoLiveEnding (job: Bull.Job) { | 16 | async 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 | ||
101 | async function cleanupLive (video: MVideo, streamingPlaylist: MStreamingPlaylist) { | 110 | async 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' | |||
18 | import { createLocalVideoChannel } from './video-channel' | 18 | import { createLocalVideoChannel } from './video-channel' |
19 | import { createWatchLaterPlaylist } from './video-playlist' | 19 | import { createWatchLaterPlaylist } from './video-playlist' |
20 | 20 | ||
21 | import memoizee = require('memoizee') | ||
22 | |||
23 | type ChannelNames = { name: string, displayName: string } | 21 | type ChannelNames = { name: string, displayName: string } |
24 | 22 | ||
25 | async function createUserAccountAndChannelAndPlaylist (parameters: { | 23 | async 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' | |||
4 | import { VideoModel } from '@server/models/video/video' | 4 | import { VideoModel } from '@server/models/video/video' |
5 | import { FilteredModelAttributes } from '@server/types' | 5 | import { FilteredModelAttributes } from '@server/types' |
6 | import { MTag, MThumbnail, MVideoTag, MVideoThumbnail, MVideoUUID } from '@server/types/models' | 6 | import { MTag, MThumbnail, MVideoTag, MVideoThumbnail, MVideoUUID } from '@server/types/models' |
7 | import { ThumbnailType, VideoCreate, VideoPrivacy } from '@shared/models' | 7 | import { ThumbnailType, VideoCreate, VideoPrivacy, VideoState } from '@shared/models' |
8 | import { federateVideoIfNeeded } from './activitypub/videos' | 8 | import { federateVideoIfNeeded } from './activitypub/videos' |
9 | import { Notifier } from './notifier' | 9 | import { Notifier } from './notifier' |
10 | import { createVideoMiniatureFromExisting } from './thumbnail' | 10 | import { createVideoMiniatureFromExisting } from './thumbnail' |
@@ -81,8 +81,8 @@ async function setVideoTags (options: { | |||
81 | } | 81 | } |
82 | } | 82 | } |
83 | 83 | ||
84 | async function publishAndFederateIfNeeded (video: MVideoUUID) { | 84 | async 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 | ||