aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-11-26 11:29:50 +0100
committerChocobozzz <me@florianbigard.com>2020-11-26 11:30:18 +0100
commit884d2c39ae23b44d0d037aaff0f66ad9ae0807ba (patch)
tree1e06fa6954a987b08894c574e31db7e8c106bafe /server/helpers
parent0151c41c65e0e3e94288314afe295358b9d698f7 (diff)
downloadPeerTube-884d2c39ae23b44d0d037aaff0f66ad9ae0807ba.tar.gz
PeerTube-884d2c39ae23b44d0d037aaff0f66ad9ae0807ba.tar.zst
PeerTube-884d2c39ae23b44d0d037aaff0f66ad9ae0807ba.zip
Fix live FPS limit
Diffstat (limited to 'server/helpers')
-rw-r--r--server/helpers/ffmpeg-utils.ts43
-rw-r--r--server/helpers/ffprobe-utils.ts21
2 files changed, 37 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)
diff --git a/server/helpers/ffprobe-utils.ts b/server/helpers/ffprobe-utils.ts
index 16b295bbd..1cf397767 100644
--- a/server/helpers/ffprobe-utils.ts
+++ b/server/helpers/ffprobe-utils.ts
@@ -247,6 +247,26 @@ function getClosestFramerateStandard (fps: number, type: 'HD_STANDARD' | 'STANDA
247 .sort((a, b) => fps % a - fps % b)[0] 247 .sort((a, b) => fps % a - fps % b)[0]
248} 248}
249 249
250function computeFPS (fpsArg: number, resolution: VideoResolution) {
251 let fps = fpsArg
252
253 if (
254 // On small/medium resolutions, limit FPS
255 resolution !== undefined &&
256 resolution < VIDEO_TRANSCODING_FPS.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
257 fps > VIDEO_TRANSCODING_FPS.AVERAGE
258 ) {
259 // Get closest standard framerate by modulo: downsampling has to be done to a divisor of the nominal fps value
260 fps = getClosestFramerateStandard(fps, 'STANDARD')
261 }
262
263 // Hard FPS limits
264 if (fps > VIDEO_TRANSCODING_FPS.MAX) fps = getClosestFramerateStandard(fps, 'HD_STANDARD')
265 else if (fps < VIDEO_TRANSCODING_FPS.MIN) fps = VIDEO_TRANSCODING_FPS.MIN
266
267 return fps
268}
269
250// --------------------------------------------------------------------------- 270// ---------------------------------------------------------------------------
251 271
252export { 272export {
@@ -259,6 +279,7 @@ export {
259 getVideoStreamFromFile, 279 getVideoStreamFromFile,
260 getDurationFromVideoFile, 280 getDurationFromVideoFile,
261 getAudioStream, 281 getAudioStream,
282 computeFPS,
262 getVideoFileFPS, 283 getVideoFileFPS,
263 ffprobePromise, 284 ffprobePromise,
264 getClosestFramerateStandard, 285 getClosestFramerateStandard,