diff options
Diffstat (limited to 'server/lib/live-manager.ts')
-rw-r--r-- | server/lib/live-manager.ts | 48 |
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 | ||
2 | import * as chokidar from 'chokidar' | 2 | import * as chokidar from 'chokidar' |
3 | import { FfmpegCommand } from 'fluent-ffmpeg' | 3 | import { FfmpegCommand } from 'fluent-ffmpeg' |
4 | import { copy, ensureDir, stat } from 'fs-extra' | 4 | import { appendFile, copy, ensureDir, readFile, stat } from 'fs-extra' |
5 | import { basename, join } from 'path' | 5 | import { basename, join } from 'path' |
6 | import { isTestInstance } from '@server/helpers/core-utils' | 6 | import { isTestInstance } from '@server/helpers/core-utils' |
7 | import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils' | 7 | import { getLiveMuxingCommand, getLiveTranscodingCommand } from '@server/helpers/ffmpeg-utils' |
@@ -24,6 +24,7 @@ import { PeerTubeSocket } from './peertube-socket' | |||
24 | import { isAbleToUploadVideo } from './user' | 24 | import { isAbleToUploadVideo } from './user' |
25 | import { getHLSDirectory } from './video-paths' | 25 | import { getHLSDirectory } from './video-paths' |
26 | import { availableEncoders } from './video-transcoding-profiles' | 26 | import { availableEncoders } from './video-transcoding-profiles' |
27 | import * as Bluebird from 'bluebird' | ||
27 | 28 | ||
28 | import memoizee = require('memoizee') | 29 | import 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 })) |