import { getMaxBitrate, getTargetBitrate, VideoResolution } from '../../shared/models/videos'
import { checkFFmpegEncoders } from '../initializers/checker-before-init'
import { CONFIG } from '../initializers/config'
-import { FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers/constants'
+import { FFMPEG_NICE, VIDEO_LIVE, VIDEO_TRANSCODING_FPS } from '../initializers/constants'
import { processImage } from './image-utils'
import { logger } from './logger'
})
}
-function runLiveTranscoding (rtmpUrl: string, outPath: string, resolutions: number[]) {
+function runLiveTranscoding (rtmpUrl: string, outPath: string, resolutions: number[], deleteSegments: boolean) {
const command = getFFmpeg(rtmpUrl)
command.inputOption('-fflags nobuffer')
varStreamMap.push(`v:${i},a:${i}`)
}
- addDefaultLiveHLSParams(command, outPath)
+ addDefaultLiveHLSParams(command, outPath, deleteSegments)
command.outputOption('-var_stream_map', varStreamMap.join(' '))
return command
}
-function runLiveMuxing (rtmpUrl: string, outPath: string) {
+function runLiveMuxing (rtmpUrl: string, outPath: string, deleteSegments: boolean) {
const command = getFFmpeg(rtmpUrl)
command.inputOption('-fflags nobuffer')
command.outputOption('-map 0:a?')
command.outputOption('-map 0:v?')
- addDefaultLiveHLSParams(command, outPath)
+ addDefaultLiveHLSParams(command, outPath, deleteSegments)
command.run()
return command
}
+async function hlsPlaylistToFragmentedMP4 (hlsDirectory: string, segmentFiles: string[], outputPath: string) {
+ const concatFile = 'concat.txt'
+ const concatFilePath = join(hlsDirectory, concatFile)
+ const content = segmentFiles.map(f => 'file ' + f)
+ .join('\n')
+
+ await writeFile(concatFilePath, content + '\n')
+
+ const command = getFFmpeg(concatFilePath)
+ command.inputOption('-safe 0')
+ command.inputOption('-f concat')
+
+ command.outputOption('-c copy')
+ command.output(outputPath)
+
+ command.run()
+
+ function cleaner () {
+ remove(concatFile)
+ .catch(err => logger.error('Cannot remove concat file in %s.', hlsDirectory, { err }))
+ }
+
+ return new Promise<string>((res, rej) => {
+ command.on('error', err => {
+ cleaner()
+
+ rej(err)
+ })
+
+ command.on('end', () => {
+ cleaner()
+
+ res()
+ })
+ })
+}
+
// ---------------------------------------------------------------------------
export {
getVideoFileFPS,
computeResolutionsToTranscode,
audio,
+ hlsPlaylistToFragmentedMP4,
getVideoFileBitrate,
canDoQuickTranscode
}
.outputOption('-map_metadata -1') // strip all metadata
}
-function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string) {
- command.outputOption('-hls_time 4')
- command.outputOption('-hls_list_size 15')
- command.outputOption('-hls_flags delete_segments')
+function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string, deleteSegments: boolean) {
+ command.outputOption('-hls_time ' + VIDEO_LIVE.SEGMENT_TIME)
+ command.outputOption('-hls_list_size ' + VIDEO_LIVE.SEGMENTS_LIST_SIZE)
+
+ if (deleteSegments === true) {
+ command.outputOption('-hls_flags delete_segments')
+ }
+
command.outputOption(`-hls_segment_filename ${join(outPath, '%v-%d.ts')}`)
command.outputOption('-master_pl_name master.m3u8')
command.outputOption(`-f hls`)