]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add minimum bitrate limit
authorChocobozzz <me@florianbigard.com>
Wed, 10 Nov 2021 10:04:00 +0000 (11:04 +0100)
committerChocobozzz <me@florianbigard.com>
Wed, 10 Nov 2021 10:04:00 +0000 (11:04 +0100)
server/helpers/ffmpeg-utils.ts
server/lib/transcoding/video-transcoding-profiles.ts
shared/core-utils/videos/bitrate.ts

index cc79828f66570daf3cd68a8e2cfeab38e8ee37f8..ab29d46913f02f76322ab401f2f296d53d4b400c 100644 (file)
@@ -286,7 +286,10 @@ async function getLiveTranscodingCommand (options: {
 
       addDefaultEncoderParams({ command, encoder: builderResult.encoder, fps: resolutionFPS, streamNum: i })
 
-      logger.debug('Apply ffmpeg live video params from %s using %s profile.', builderResult.encoder, profile, builderResult, lTags())
+      logger.debug(
+        'Apply ffmpeg live video params from %s using %s profile.', builderResult.encoder, profile, builderResult,
+        { fps: resolutionFPS, resolution, ...lTags() }
+      )
 
       command.outputOption(`${buildStreamSuffix('-c:v', i)} ${builderResult.encoder}`)
       applyEncoderOptions(command, builderResult.result)
@@ -310,7 +313,10 @@ async function getLiveTranscodingCommand (options: {
 
       addDefaultEncoderParams({ command, encoder: builderResult.encoder, fps: resolutionFPS, streamNum: i })
 
-      logger.debug('Apply ffmpeg live audio params from %s using %s profile.', builderResult.encoder, profile, builderResult, lTags())
+      logger.debug(
+        'Apply ffmpeg live audio params from %s using %s profile.', builderResult.encoder, profile, builderResult,
+        { fps: resolutionFPS, resolution, ...lTags() }
+      )
 
       command.outputOption(`${buildStreamSuffix('-c:a', i)} ${builderResult.encoder}`)
       applyEncoderOptions(command, builderResult.result)
@@ -622,7 +628,7 @@ async function presetVideo (options: {
     logger.debug(
       'Apply ffmpeg params from %s for %s stream of input %s using %s profile.',
       builderResult.encoder, streamType, input, profile, builderResult,
-      lTags()
+      { resolution, fps, ...lTags() }
     )
 
     if (streamType === 'video') {
index 92971210c2d9e7dfb64cba7990b32a874231778a..34a364415efdcd62a49c65591a98b8421676d004 100644 (file)
@@ -1,6 +1,7 @@
+
 import { logger } from '@server/helpers/logger'
-import { getAverageBitrate } from '@shared/core-utils'
-import { AvailableEncoders, EncoderOptionsBuilder, EncoderOptionsBuilderParams } from '../../../shared/models/videos'
+import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils'
+import { AvailableEncoders, EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '../../../shared/models/videos'
 import { buildStreamSuffix, resetSupportedEncoders } from '../../helpers/ffmpeg-utils'
 import { canDoQuickAudioTranscode, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '../../helpers/ffprobe-utils'
 
@@ -15,10 +16,10 @@ import { canDoQuickAudioTranscode, ffprobePromise, getAudioStream, getMaxAudioBi
  */
 
 const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
-  const { fps, inputRatio, inputBitrate } = options
+  const { fps, inputRatio, inputBitrate, resolution } = options
   if (!fps) return { outputOptions: [ ] }
 
-  const targetBitrate = capBitrate(inputBitrate, getAverageBitrate({ ...options, fps, ratio: inputRatio }))
+  const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
 
   return {
     outputOptions: [
@@ -31,9 +32,9 @@ const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOpt
 }
 
 const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
-  const { streamNum, fps, inputBitrate, inputRatio } = options
+  const { streamNum, fps, inputBitrate, inputRatio, resolution } = options
 
-  const targetBitrate = capBitrate(inputBitrate, getAverageBitrate({ ...options, fps, ratio: inputRatio }))
+  const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
 
   return {
     outputOptions: [
@@ -234,6 +235,20 @@ export {
 
 // ---------------------------------------------------------------------------
 
+function getTargetBitrate (options: {
+  inputBitrate: number
+  resolution: VideoResolution
+  ratio: number
+  fps: number
+}) {
+  const { inputBitrate, resolution, ratio, fps } = options
+
+  const capped = capBitrate(inputBitrate, getAverageBitrate({ resolution, fps, ratio }))
+  const limit = getMinLimitBitrate({ resolution, fps, ratio })
+
+  return Math.max(limit, capped)
+}
+
 function capBitrate (inputBitrate: number, targetBitrate: number) {
   if (!inputBitrate) return targetBitrate
 
index 18c6e2f6cef4ef6c45de5b97cf3b0399959317ad..c1891188f1581dc9fbc4da78b3032695a2012a7a 100644 (file)
@@ -4,6 +4,18 @@ type BitPerPixel = { [ id in VideoResolution ]: number }
 
 // https://bitmovin.com/video-bitrate-streaming-hls-dash/
 
+const minLimitBitPerPixel: BitPerPixel = {
+  [VideoResolution.H_NOVIDEO]: 0,
+  [VideoResolution.H_144P]: 0.02,
+  [VideoResolution.H_240P]: 0.02,
+  [VideoResolution.H_360P]: 0.02,
+  [VideoResolution.H_480P]: 0.02,
+  [VideoResolution.H_720P]: 0.02,
+  [VideoResolution.H_1080P]: 0.02,
+  [VideoResolution.H_1440P]: 0.02,
+  [VideoResolution.H_4K]: 0.02
+}
+
 const averageBitPerPixel: BitPerPixel = {
   [VideoResolution.H_NOVIDEO]: 0,
   [VideoResolution.H_144P]: 0.19,
@@ -50,11 +62,23 @@ function getMaxBitrate (options: {
   return targetBitrate
 }
 
+function getMinLimitBitrate (options: {
+  resolution: VideoResolution
+  ratio: number
+  fps: number
+}) {
+  const minLimitBitrate = calculateBitrate({ ...options, bitPerPixel: minLimitBitPerPixel })
+  if (!minLimitBitrate) return 10 * 1000
+
+  return minLimitBitrate
+}
+
 // ---------------------------------------------------------------------------
 
 export {
   getAverageBitrate,
-  getMaxBitrate
+  getMaxBitrate,
+  getMinLimitBitrate
 }
 
 // ---------------------------------------------------------------------------