diff options
Diffstat (limited to 'server/lib/live-manager.ts')
-rw-r--r-- | server/lib/live-manager.ts | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/server/lib/live-manager.ts b/server/lib/live-manager.ts index 2d8f906e9..6eb05c9d6 100644 --- a/server/lib/live-manager.ts +++ b/server/lib/live-manager.ts | |||
@@ -4,7 +4,7 @@ import * as chokidar from 'chokidar' | |||
4 | import { FfmpegCommand } from 'fluent-ffmpeg' | 4 | import { FfmpegCommand } from 'fluent-ffmpeg' |
5 | import { ensureDir, stat } from 'fs-extra' | 5 | import { ensureDir, stat } from 'fs-extra' |
6 | import { basename } from 'path' | 6 | import { basename } from 'path' |
7 | import { computeResolutionsToTranscode, runLiveMuxing, runLiveTranscoding } from '@server/helpers/ffmpeg-utils' | 7 | import { computeResolutionsToTranscode, getVideoFileFPS, getVideoFileResolution, getVideoStreamCodec, getVideoStreamSize, runLiveMuxing, runLiveTranscoding } from '@server/helpers/ffmpeg-utils' |
8 | import { logger } from '@server/helpers/logger' | 8 | import { logger } from '@server/helpers/logger' |
9 | import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' | 9 | import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' |
10 | import { MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, WEBSERVER } from '@server/initializers/constants' | 10 | import { MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, WEBSERVER } from '@server/initializers/constants' |
@@ -137,6 +137,13 @@ class LiveManager { | |||
137 | this.abortSession(sessionId) | 137 | this.abortSession(sessionId) |
138 | } | 138 | } |
139 | 139 | ||
140 | getLiveQuotaUsedByUser (userId: number) { | ||
141 | const currentLives = this.livesPerUser.get(userId) | ||
142 | if (!currentLives) return 0 | ||
143 | |||
144 | return currentLives.reduce((sum, obj) => sum + obj.size, 0) | ||
145 | } | ||
146 | |||
140 | private getContext () { | 147 | private getContext () { |
141 | return context | 148 | return context |
142 | } | 149 | } |
@@ -173,8 +180,15 @@ class LiveManager { | |||
173 | const playlistUrl = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid) | 180 | const playlistUrl = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid) |
174 | 181 | ||
175 | const session = this.getContext().sessions.get(sessionId) | 182 | const session = this.getContext().sessions.get(sessionId) |
183 | const rtmpUrl = 'rtmp://127.0.0.1:' + config.rtmp.port + streamPath | ||
184 | |||
185 | const [ resolutionResult, fps ] = await Promise.all([ | ||
186 | getVideoFileResolution(rtmpUrl), | ||
187 | getVideoFileFPS(rtmpUrl) | ||
188 | ]) | ||
189 | |||
176 | const resolutionsEnabled = CONFIG.LIVE.TRANSCODING.ENABLED | 190 | const resolutionsEnabled = CONFIG.LIVE.TRANSCODING.ENABLED |
177 | ? computeResolutionsToTranscode(session.videoHeight, 'live') | 191 | ? computeResolutionsToTranscode(resolutionResult.videoFileResolution, 'live') |
178 | : [] | 192 | : [] |
179 | 193 | ||
180 | logger.info('Will mux/transcode live video of original resolution %d.', session.videoHeight, { resolutionsEnabled }) | 194 | logger.info('Will mux/transcode live video of original resolution %d.', session.videoHeight, { resolutionsEnabled }) |
@@ -193,8 +207,9 @@ class LiveManager { | |||
193 | sessionId, | 207 | sessionId, |
194 | videoLive, | 208 | videoLive, |
195 | playlist: videoStreamingPlaylist, | 209 | playlist: videoStreamingPlaylist, |
196 | streamPath, | ||
197 | originalResolution: session.videoHeight, | 210 | originalResolution: session.videoHeight, |
211 | rtmpUrl, | ||
212 | fps, | ||
198 | resolutionsEnabled | 213 | resolutionsEnabled |
199 | }) | 214 | }) |
200 | } | 215 | } |
@@ -203,11 +218,12 @@ class LiveManager { | |||
203 | sessionId: string | 218 | sessionId: string |
204 | videoLive: MVideoLiveVideo | 219 | videoLive: MVideoLiveVideo |
205 | playlist: MStreamingPlaylist | 220 | playlist: MStreamingPlaylist |
206 | streamPath: string | 221 | rtmpUrl: string |
222 | fps: number | ||
207 | resolutionsEnabled: number[] | 223 | resolutionsEnabled: number[] |
208 | originalResolution: number | 224 | originalResolution: number |
209 | }) { | 225 | }) { |
210 | const { sessionId, videoLive, playlist, streamPath, resolutionsEnabled, originalResolution } = options | 226 | const { sessionId, videoLive, playlist, resolutionsEnabled, originalResolution, fps, rtmpUrl } = options |
211 | const startStreamDateTime = new Date().getTime() | 227 | const startStreamDateTime = new Date().getTime() |
212 | const allResolutions = resolutionsEnabled.concat([ originalResolution ]) | 228 | const allResolutions = resolutionsEnabled.concat([ originalResolution ]) |
213 | 229 | ||
@@ -238,17 +254,16 @@ class LiveManager { | |||
238 | const outPath = getHLSDirectory(videoLive.Video) | 254 | const outPath = getHLSDirectory(videoLive.Video) |
239 | await ensureDir(outPath) | 255 | await ensureDir(outPath) |
240 | 256 | ||
257 | const videoUUID = videoLive.Video.uuid | ||
241 | const deleteSegments = videoLive.saveReplay === false | 258 | const deleteSegments = videoLive.saveReplay === false |
242 | 259 | ||
243 | const rtmpUrl = 'rtmp://127.0.0.1:' + config.rtmp.port + streamPath | ||
244 | const ffmpegExec = CONFIG.LIVE.TRANSCODING.ENABLED | 260 | const ffmpegExec = CONFIG.LIVE.TRANSCODING.ENABLED |
245 | ? runLiveTranscoding(rtmpUrl, outPath, allResolutions, deleteSegments) | 261 | ? runLiveTranscoding(rtmpUrl, outPath, allResolutions, fps, deleteSegments) |
246 | : runLiveMuxing(rtmpUrl, outPath, deleteSegments) | 262 | : runLiveMuxing(rtmpUrl, outPath, deleteSegments) |
247 | 263 | ||
248 | logger.info('Running live muxing/transcoding.') | 264 | logger.info('Running live muxing/transcoding for %s.', videoUUID) |
249 | this.transSessions.set(sessionId, ffmpegExec) | 265 | this.transSessions.set(sessionId, ffmpegExec) |
250 | 266 | ||
251 | const videoUUID = videoLive.Video.uuid | ||
252 | const tsWatcher = chokidar.watch(outPath + '/*.ts') | 267 | const tsWatcher = chokidar.watch(outPath + '/*.ts') |
253 | 268 | ||
254 | const updateSegment = segmentPath => this.segmentsSha256Queue.push({ operation: 'update', segmentPath, videoUUID }) | 269 | const updateSegment = segmentPath => this.segmentsSha256Queue.push({ operation: 'update', segmentPath, videoUUID }) |
@@ -307,7 +322,7 @@ class LiveManager { | |||
307 | }) | 322 | }) |
308 | 323 | ||
309 | const onFFmpegEnded = () => { | 324 | const onFFmpegEnded = () => { |
310 | logger.info('RTMP transmuxing for video %s ended. Scheduling cleanup', streamPath) | 325 | logger.info('RTMP transmuxing for video %s ended. Scheduling cleanup', rtmpUrl) |
311 | 326 | ||
312 | this.transSessions.delete(sessionId) | 327 | this.transSessions.delete(sessionId) |
313 | 328 | ||
@@ -332,13 +347,6 @@ class LiveManager { | |||
332 | ffmpegExec.on('end', () => onFFmpegEnded()) | 347 | ffmpegExec.on('end', () => onFFmpegEnded()) |
333 | } | 348 | } |
334 | 349 | ||
335 | getLiveQuotaUsedByUser (userId: number) { | ||
336 | const currentLives = this.livesPerUser.get(userId) | ||
337 | if (!currentLives) return 0 | ||
338 | |||
339 | return currentLives.reduce((sum, obj) => sum + obj.size, 0) | ||
340 | } | ||
341 | |||
342 | private async onEndTransmuxing (videoId: number, cleanupNow = false) { | 350 | private async onEndTransmuxing (videoId: number, cleanupNow = false) { |
343 | try { | 351 | try { |
344 | const fullVideo = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoId) | 352 | const fullVideo = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoId) |