aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers/ffmpeg-utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/helpers/ffmpeg-utils.ts')
-rw-r--r--server/helpers/ffmpeg-utils.ts43
1 files changed, 16 insertions, 27 deletions
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts
index 9755dd67c..3cc062b8c 100644
--- a/server/helpers/ffmpeg-utils.ts
+++ b/server/helpers/ffmpeg-utils.ts
@@ -1,11 +1,11 @@
1import * as ffmpeg from 'fluent-ffmpeg' 1import * as ffmpeg from 'fluent-ffmpeg'
2import { readFile, remove, writeFile } from 'fs-extra' 2import { readFile, remove, writeFile } from 'fs-extra'
3import { dirname, join } from 'path' 3import { dirname, join } from 'path'
4import { FFMPEG_NICE, VIDEO_LIVE, VIDEO_TRANSCODING_ENCODERS, VIDEO_TRANSCODING_FPS } from '@server/initializers/constants' 4import { FFMPEG_NICE, VIDEO_LIVE, VIDEO_TRANSCODING_ENCODERS } from '@server/initializers/constants'
5import { VideoResolution } from '../../shared/models/videos' 5import { VideoResolution } from '../../shared/models/videos'
6import { checkFFmpegEncoders } from '../initializers/checker-before-init' 6import { checkFFmpegEncoders } from '../initializers/checker-before-init'
7import { CONFIG } from '../initializers/config' 7import { CONFIG } from '../initializers/config'
8import { getAudioStream, getClosestFramerateStandard, getVideoFileFPS } from './ffprobe-utils' 8import { computeFPS, getAudioStream, getVideoFileFPS } from './ffprobe-utils'
9import { processImage } from './image-utils' 9import { processImage } from './image-utils'
10import { logger } from './logger' 10import { logger } from './logger'
11 11
@@ -223,7 +223,17 @@ async function getLiveTranscodingCommand (options: {
223 223
224 for (let i = 0; i < resolutions.length; i++) { 224 for (let i = 0; i < resolutions.length; i++) {
225 const resolution = resolutions[i] 225 const resolution = resolutions[i]
226 const baseEncoderBuilderParams = { input, availableEncoders, profile, fps, resolution, streamNum: i, videoType: 'live' as 'live' } 226 const resolutionFPS = computeFPS(fps, resolution)
227
228 const baseEncoderBuilderParams = {
229 input,
230 availableEncoders,
231 profile,
232 fps: resolutionFPS,
233 resolution,
234 streamNum: i,
235 videoType: 'live' as 'live'
236 }
227 237
228 { 238 {
229 const builderResult = await getEncoderBuilderResult(Object.assign({}, baseEncoderBuilderParams, { streamType: 'VIDEO' })) 239 const builderResult = await getEncoderBuilderResult(Object.assign({}, baseEncoderBuilderParams, { streamType: 'VIDEO' }))
@@ -233,7 +243,7 @@ async function getLiveTranscodingCommand (options: {
233 243
234 command.outputOption(`-map [vout${resolution}]`) 244 command.outputOption(`-map [vout${resolution}]`)
235 245
236 addDefaultEncoderParams({ command, encoder: builderResult.encoder, fps, streamNum: i }) 246 addDefaultEncoderParams({ command, encoder: builderResult.encoder, fps: resolutionFPS, streamNum: i })
237 247
238 logger.debug('Apply ffmpeg live video params from %s.', builderResult.encoder, builderResult) 248 logger.debug('Apply ffmpeg live video params from %s.', builderResult.encoder, builderResult)
239 249
@@ -249,7 +259,7 @@ async function getLiveTranscodingCommand (options: {
249 259
250 command.outputOption('-map a:0') 260 command.outputOption('-map a:0')
251 261
252 addDefaultEncoderParams({ command, encoder: builderResult.encoder, fps, streamNum: i }) 262 addDefaultEncoderParams({ command, encoder: builderResult.encoder, fps: resolutionFPS, streamNum: i })
253 263
254 logger.debug('Apply ffmpeg live audio params from %s.', builderResult.encoder, builderResult) 264 logger.debug('Apply ffmpeg live audio params from %s.', builderResult.encoder, builderResult)
255 265
@@ -387,15 +397,7 @@ function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string
387 397
388async function buildx264VODCommand (command: ffmpeg.FfmpegCommand, options: TranscodeOptions) { 398async function buildx264VODCommand (command: ffmpeg.FfmpegCommand, options: TranscodeOptions) {
389 let fps = await getVideoFileFPS(options.inputPath) 399 let fps = await getVideoFileFPS(options.inputPath)
390 if ( 400 fps = computeFPS(fps, options.resolution)
391 // On small/medium resolutions, limit FPS
392 options.resolution !== undefined &&
393 options.resolution < VIDEO_TRANSCODING_FPS.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
394 fps > VIDEO_TRANSCODING_FPS.AVERAGE
395 ) {
396 // Get closest standard framerate by modulo: downsampling has to be done to a divisor of the nominal fps value
397 fps = getClosestFramerateStandard(fps, 'STANDARD')
398 }
399 401
400 command = await presetVideo(command, options.inputPath, options, fps) 402 command = await presetVideo(command, options.inputPath, options, fps)
401 403
@@ -408,12 +410,6 @@ async function buildx264VODCommand (command: ffmpeg.FfmpegCommand, options: Tran
408 command = command.size(size) 410 command = command.size(size)
409 } 411 }
410 412
411 // Hard FPS limits
412 if (fps > VIDEO_TRANSCODING_FPS.MAX) fps = getClosestFramerateStandard(fps, 'HD_STANDARD')
413 else if (fps < VIDEO_TRANSCODING_FPS.MIN) fps = VIDEO_TRANSCODING_FPS.MIN
414
415 command = command.withFPS(fps)
416
417 return command 413 return command
418} 414}
419 415
@@ -422,13 +418,6 @@ async function buildAudioMergeCommand (command: ffmpeg.FfmpegCommand, options: M
422 418
423 command = await presetVideo(command, options.audioPath, options) 419 command = await presetVideo(command, options.audioPath, options)
424 420
425 /*
426 MAIN reference: https://slhck.info/video/2017/03/01/rate-control.html
427 Our target situation is closer to a livestream than a stream,
428 since we want to reduce as much a possible the encoding burden,
429 although not to the point of a livestream where there is a hard
430 constraint on the frames per second to be encoded.
431 */
432 command.outputOption('-preset:v veryfast') 421 command.outputOption('-preset:v veryfast')
433 422
434 command = command.input(options.audioPath) 423 command = command.input(options.audioPath)