aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/live-manager.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/live-manager.ts')
-rw-r--r--server/lib/live-manager.ts48
1 files changed, 30 insertions, 18 deletions
diff --git a/server/lib/live-manager.ts b/server/lib/live-manager.ts
index dcf016169..c2dd116a9 100644
--- a/server/lib/live-manager.ts
+++ b/server/lib/live-manager.ts
@@ -1,7 +1,7 @@
1 1
2import * as chokidar from 'chokidar' 2import * as chokidar from 'chokidar'
3import { FfmpegCommand } from 'fluent-ffmpeg' 3import { FfmpegCommand } from 'fluent-ffmpeg'
4import { copy, ensureDir, stat } from 'fs-extra' 4import { appendFile, copy, ensureDir, readFile, stat } from 'fs-extra'
5import { basename, join } from 'path' 5import { basename, join } from 'path'
6import { isTestInstance } from '@server/helpers/core-utils' 6import { isTestInstance } from '@server/helpers/core-utils'
7import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils' 7import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils'
@@ -24,6 +24,7 @@ import { PeerTubeSocket } from './peertube-socket'
24import { isAbleToUploadVideo } from './user' 24import { isAbleToUploadVideo } from './user'
25import { getHLSDirectory } from './video-paths' 25import { getHLSDirectory } from './video-paths'
26import { availableEncoders } from './video-transcoding-profiles' 26import { availableEncoders } from './video-transcoding-profiles'
27import * as Bluebird from 'bluebird'
27 28
28import memoizee = require('memoizee') 29import memoizee = require('memoizee')
29 30
@@ -158,6 +159,32 @@ class LiveManager {
158 this.segmentsSha256.delete(videoUUID) 159 this.segmentsSha256.delete(videoUUID)
159 } 160 }
160 161
162 addSegmentToReplay (hlsVideoPath: string, segmentPath: string) {
163 const segmentName = basename(segmentPath)
164 const dest = join(hlsVideoPath, VIDEO_LIVE.REPLAY_DIRECTORY, this.buildConcatenatedName(segmentName))
165
166 return readFile(segmentPath)
167 .then(data => appendFile(dest, data))
168 .catch(err => logger.error('Cannot copy segment %s to repay directory.', segmentPath, { err }))
169 }
170
171 buildConcatenatedName (segmentOrPlaylistPath: string) {
172 const num = basename(segmentOrPlaylistPath).match(/^(\d+)(-|\.)/)
173
174 return 'concat-' + num[1] + '.ts'
175 }
176
177 private processSegments (hlsVideoPath: string, videoUUID: string, videoLive: MVideoLive, segmentPaths: string[]) {
178 Bluebird.mapSeries(segmentPaths, async previousSegment => {
179 // Add sha hash of previous segments, because ffmpeg should have finished generating them
180 await this.addSegmentSha(videoUUID, previousSegment)
181
182 if (videoLive.saveReplay) {
183 await this.addSegmentToReplay(hlsVideoPath, previousSegment)
184 }
185 }).catch(err => logger.error('Cannot process segments in %s', hlsVideoPath, { err }))
186 }
187
161 private getContext () { 188 private getContext () {
162 return context 189 return context
163 } 190 }
@@ -302,28 +329,13 @@ class LiveManager {
302 const segmentsToProcessPerPlaylist: { [playlistId: string]: string[] } = {} 329 const segmentsToProcessPerPlaylist: { [playlistId: string]: string[] } = {}
303 const playlistIdMatcher = /^([\d+])-/ 330 const playlistIdMatcher = /^([\d+])-/
304 331
305 const processSegments = (segmentsToProcess: string[]) => {
306 // Add sha hash of previous segments, because ffmpeg should have finished generating them
307 for (const previousSegment of segmentsToProcess) {
308 this.addSegmentSha(videoUUID, previousSegment)
309 .catch(err => logger.error('Cannot add sha segment of video %s -> %s.', videoUUID, previousSegment, { err }))
310
311 if (videoLive.saveReplay) {
312 const segmentName = basename(previousSegment)
313
314 copy(previousSegment, join(outPath, VIDEO_LIVE.REPLAY_DIRECTORY, segmentName))
315 .catch(err => logger.error('Cannot copy segment %s to repay directory.', previousSegment, { err }))
316 }
317 }
318 }
319
320 const addHandler = segmentPath => { 332 const addHandler = segmentPath => {
321 logger.debug('Live add handler of %s.', segmentPath) 333 logger.debug('Live add handler of %s.', segmentPath)
322 334
323 const playlistId = basename(segmentPath).match(playlistIdMatcher)[0] 335 const playlistId = basename(segmentPath).match(playlistIdMatcher)[0]
324 336
325 const segmentsToProcess = segmentsToProcessPerPlaylist[playlistId] || [] 337 const segmentsToProcess = segmentsToProcessPerPlaylist[playlistId] || []
326 processSegments(segmentsToProcess) 338 this.processSegments(outPath, videoUUID, videoLive, segmentsToProcess)
327 339
328 segmentsToProcessPerPlaylist[playlistId] = [ segmentPath ] 340 segmentsToProcessPerPlaylist[playlistId] = [ segmentPath ]
329 341
@@ -400,7 +412,7 @@ class LiveManager {
400 .then(() => { 412 .then(() => {
401 // Process remaining segments hash 413 // Process remaining segments hash
402 for (const key of Object.keys(segmentsToProcessPerPlaylist)) { 414 for (const key of Object.keys(segmentsToProcessPerPlaylist)) {
403 processSegments(segmentsToProcessPerPlaylist[key]) 415 this.processSegments(outPath, videoUUID, videoLive, segmentsToProcessPerPlaylist[key])
404 } 416 }
405 }) 417 })
406 .catch(err => logger.error('Cannot close watchers of %s or process remaining hash segments.', outPath, { err })) 418 .catch(err => logger.error('Cannot close watchers of %s or process remaining hash segments.', outPath, { err }))