+ private isDurationConstraintValid (streamingStartTime: number) {
+ const maxDuration = CONFIG.LIVE.MAX_DURATION
+ // No limit
+ if (maxDuration < 0) return true
+
+ const now = new Date().getTime()
+ const max = streamingStartTime + maxDuration
+
+ return now <= max
+ }
+
+ private async isQuotaConstraintValid (user: MUserId, live: MVideoLive) {
+ if (live.saveReplay !== true) return true
+
+ return this.isAbleToUploadVideoWithCache(user.id)
+ }
+
+ private async updateLiveViews () {
+ if (!this.isRunning()) return
+
+ if (!isTestInstance()) logger.info('Updating live video views.')
+
+ for (const videoId of this.watchersPerVideo.keys()) {
+ const notBefore = new Date().getTime() - VIEW_LIFETIME.LIVE
+
+ const watchers = this.watchersPerVideo.get(videoId)
+
+ const numWatchers = watchers.length
+
+ const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoId)
+ video.views = numWatchers
+ await video.save()
+
+ await federateVideoIfNeeded(video, false)
+
+ PeerTubeSocket.Instance.sendVideoViewsUpdate(video)
+
+ // Only keep not expired watchers
+ const newWatchers = watchers.filter(w => w > notBefore)
+ this.watchersPerVideo.set(videoId, newWatchers)
+
+ logger.debug('New live video views for %s is %d.', video.url, numWatchers)
+ }
+ }
+
+ private async handleBrokenLives () {
+ const videoIds = await VideoModel.listPublishedLiveIds()
+
+ for (const id of videoIds) {
+ await this.onEndTransmuxing(id, true)
+ }
+ }
+