-function transcode (options: TranscodeOptions) {
- return new Promise<void>(async (res, rej) => {
- let command = ffmpeg(options.inputPath)
- .output(options.outputPath)
- .outputOption('-threads ' + CONFIG.TRANSCODING.THREADS)
- .renice(5) // we don't want to make the system unrepsonsive
- .preset(standard)
-
- let fps = await getVideoFileFPS(options.inputPath)
- if (options.resolution !== undefined) {
- // '?x720' or '720x?' for example
- const size = options.isPortraitMode === true ? `${options.resolution}x?` : `?x${options.resolution}`
- command = command.size(size)
-
- // On small/medium resolutions, limit FPS
- if (
- options.resolution < VIDEO_TRANSCODING_FPS.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
- fps > VIDEO_TRANSCODING_FPS.AVERAGE
- ) {
- fps = VIDEO_TRANSCODING_FPS.AVERAGE
- }
+interface HLSTranscodeOptions extends BaseTranscodeOptions {
+ type: 'hls'
+ copyCodecs: boolean
+ hlsPlaylist: {
+ videoFilename: string
+ }
+}
+
+interface HLSFromTSTranscodeOptions extends BaseTranscodeOptions {
+ type: 'hls-from-ts'
+
+ isAAC: boolean
+
+ hlsPlaylist: {
+ videoFilename: string
+ }
+}
+
+interface QuickTranscodeOptions extends BaseTranscodeOptions {
+ type: 'quick-transcode'
+}
+
+interface VideoTranscodeOptions extends BaseTranscodeOptions {
+ type: 'video'
+}
+
+interface MergeAudioTranscodeOptions extends BaseTranscodeOptions {
+ type: 'merge-audio'
+ audioPath: string
+}
+
+interface OnlyAudioTranscodeOptions extends BaseTranscodeOptions {
+ type: 'only-audio'
+}
+
+type TranscodeOptions =
+ HLSTranscodeOptions
+ | HLSFromTSTranscodeOptions
+ | VideoTranscodeOptions
+ | MergeAudioTranscodeOptions
+ | OnlyAudioTranscodeOptions
+ | QuickTranscodeOptions
+
+const builders: {
+ [ type in TranscodeOptionsType ]: (c: FfmpegCommand, o?: TranscodeOptions) => Promise<FfmpegCommand> | FfmpegCommand
+} = {
+ 'quick-transcode': buildQuickTranscodeCommand,
+ 'hls': buildHLSVODCommand,
+ 'hls-from-ts': buildHLSVODFromTSCommand,
+ 'merge-audio': buildAudioMergeCommand,
+ 'only-audio': buildOnlyAudioCommand,
+ 'video': buildx264VODCommand
+}
+
+async function transcode (options: TranscodeOptions) {
+ logger.debug('Will run transcode.', { options })
+
+ let command = getFFmpeg(options.inputPath, 'vod')
+ .output(options.outputPath)
+
+ command = await builders[options.type](command, options)
+
+ await runCommand({ command, job: options.job })
+
+ await fixHLSPlaylistIfNeeded(options)
+}
+
+// ---------------------------------------------------------------------------
+// Live muxing/transcoding functions
+// ---------------------------------------------------------------------------
+
+async function getLiveTranscodingCommand (options: {
+ rtmpUrl: string
+
+ outPath: string
+ masterPlaylistName: string
+
+ resolutions: number[]
+
+ // Input information
+ fps: number
+ bitrate: number
+ ratio: number
+
+ availableEncoders: AvailableEncoders
+ profile: string
+}) {
+ const { rtmpUrl, outPath, resolutions, fps, bitrate, availableEncoders, profile, masterPlaylistName, ratio } = options
+ const input = rtmpUrl
+
+ const command = getFFmpeg(input, 'live')
+
+ const varStreamMap: string[] = []
+
+ const complexFilter: FilterSpecification[] = [
+ {
+ inputs: '[v:0]',
+ filter: 'split',
+ options: resolutions.length,
+ outputs: resolutions.map(r => `vtemp${r}`)