1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-05 02:39:33 +02:00

Support max FPS configuration

This commit is contained in:
Chocobozzz 2024-08-12 16:17:11 +02:00
parent 0bd2474fed
commit bbaf96d60d
No known key found for this signature in database
GPG key ID: 583A612D890159BE
37 changed files with 736 additions and 623 deletions

View file

@ -1,31 +1,44 @@
import { VIDEO_TRANSCODING_FPS } from '@server/initializers/constants.js'
import { CONFIG } from '@server/initializers/config.js'
import { logger } from '../logger.js'
export function computeOutputFPS (options: {
inputFPS: number
isOriginResolution: boolean
resolution: number
type: 'vod' | 'live'
}) {
const { resolution } = options
const { resolution, isOriginResolution, type } = options
const settings = type === 'vod'
? buildTranscodingFPSOptions(CONFIG.TRANSCODING.FPS.MAX)
: buildTranscodingFPSOptions(CONFIG.LIVE.TRANSCODING.FPS.MAX)
let fps = options.inputFPS
if (
// On small/medium resolutions, limit FPS
// On small/medium transcoded resolutions, limit FPS
!isOriginResolution &&
resolution !== undefined &&
resolution < VIDEO_TRANSCODING_FPS.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
fps > VIDEO_TRANSCODING_FPS.AVERAGE
resolution < settings.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
fps > settings.AVERAGE
) {
// Get closest standard framerate by modulo: downsampling has to be done to a divisor of the nominal fps value
fps = getClosestFramerateStandard({ fps, type: 'STANDARD' })
fps = getClosestFramerate({ fps, settings, type: 'STANDARD' })
}
if (fps < VIDEO_TRANSCODING_FPS.HARD_MIN) {
throw new Error(`Cannot compute FPS because ${fps} is lower than our minimum value ${VIDEO_TRANSCODING_FPS.HARD_MIN}`)
if (fps < settings.HARD_MIN) {
throw new Error(`Cannot compute FPS because ${fps} is lower than our minimum value ${settings.HARD_MIN}`)
}
// Cap min FPS
if (fps < VIDEO_TRANSCODING_FPS.SOFT_MIN) fps = VIDEO_TRANSCODING_FPS.SOFT_MIN
fps = Math.max(fps, settings.TRANSCODED_MIN)
// Cap max FPS
if (fps > VIDEO_TRANSCODING_FPS.SOFT_MAX) fps = getClosestFramerateStandard({ fps, type: 'HD_STANDARD' })
if (fps > settings.TRANSCODED_MAX) {
fps = getClosestFramerate({ fps, settings, type: 'HD_STANDARD' })
}
logger.debug(`Computed output FPS ${fps} for resolution ${resolution}p`, { options, settings })
return fps
}
@ -34,12 +47,44 @@ export function computeOutputFPS (options: {
// Private
// ---------------------------------------------------------------------------
function getClosestFramerateStandard (options: {
fps: number
type: 'HD_STANDARD' | 'STANDARD'
}) {
const { fps, type } = options
function buildTranscodingFPSOptions (maxFPS: number) {
const STANDARD = [ 24, 25, 30 ].filter(v => v <= maxFPS)
if (STANDARD.length === 0) STANDARD.push(maxFPS)
return VIDEO_TRANSCODING_FPS[type].slice(0)
.sort((a, b) => fps % a - fps % b)[0]
const HD_STANDARD = [ 50, 60, maxFPS ].filter(v => v <= maxFPS)
return {
HARD_MIN: 0.1,
TRANSCODED_MIN: 1,
TRANSCODED_MAX: maxFPS,
STANDARD,
HD_STANDARD,
AVERAGE: Math.min(30, maxFPS),
KEEP_ORIGIN_FPS_RESOLUTION_MIN: 720 // We keep the original FPS on high resolutions (720 minimum)
}
}
function getClosestFramerate (options: {
fps: number
settings: ReturnType<typeof buildTranscodingFPSOptions>
type: Extract<keyof ReturnType<typeof buildTranscodingFPSOptions>, 'HD_STANDARD' | 'STANDARD'>
}) {
const { fps, settings, type } = options
const copy = [ ...settings[type] ]
// Biggest FPS first
const descSorted = copy.sort((a, b) => b - a)
// Find biggest FPS that can be divided by input FPS
const found = descSorted.find(e => fps % e === 0)
if (found) return found
// Approximation to the best result
return copy.sort((a, b) => fps % a - fps % b)[0]
}