]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/lib/transcoding/video-transcoding-profiles.ts
Add minimum bitrate limit
[github/Chocobozzz/PeerTube.git] / server / lib / transcoding / video-transcoding-profiles.ts
index c5ea72a5f6979c224f65feb7490515d145de9c4c..34a364415efdcd62a49c65591a98b8421676d004 100644 (file)
@@ -1,30 +1,25 @@
+
 import { logger } from '@server/helpers/logger'
-import { AvailableEncoders, EncoderOptionsBuilder, getTargetBitrate, VideoResolution } 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,
-  getVideoFileBitrate,
-  getVideoStreamFromFile
-} from '../../helpers/ffprobe-utils'
-import { VIDEO_TRANSCODING_FPS } from '../../initializers/constants'
+import { canDoQuickAudioTranscode, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '../../helpers/ffprobe-utils'
 
 /**
  *
  * Available encoders and profiles for the transcoding jobs
  * These functions are used by ffmpeg-utils that will get the encoders and options depending on the chosen profile
  *
+ * Resources:
+ *  * https://slhck.info/video/2017/03/01/rate-control.html
+ *  * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate
  */
 
-// Resources:
-//  * https://slhck.info/video/2017/03/01/rate-control.html
-//  * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate
+const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
+  const { fps, inputRatio, inputBitrate, resolution } = options
+  if (!fps) return { outputOptions: [ ] }
 
-const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = async ({ input, resolution, fps }) => {
-  const targetBitrate = await buildTargetBitrate({ input, resolution, fps })
-  if (!targetBitrate) return { outputOptions: [ ] }
+  const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
 
   return {
     outputOptions: [
@@ -36,8 +31,10 @@ const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = async ({ input, reso
   }
 }
 
-const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = async ({ resolution, fps, streamNum }) => {
-  const targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS)
+const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
+  const { streamNum, fps, inputBitrate, inputRatio, resolution } = options
+
+  const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
 
   return {
     outputOptions: [
@@ -69,7 +66,7 @@ const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNu
 
   logger.debug('Calculating audio bitrate of %s by AAC encoder.', input, { bitrate: parsedAudio.bitrate, audioCodecName })
 
-  if (bitrate !== undefined && bitrate !== -1) {
+  if (bitrate !== -1) {
     return { outputOptions: [ buildStreamSuffix('-b:a', streamNum), bitrate + 'k' ] }
   }
 
@@ -237,20 +234,26 @@ export {
 }
 
 // ---------------------------------------------------------------------------
-async function buildTargetBitrate (options: {
-  input: string
+
+function getTargetBitrate (options: {
+  inputBitrate: number
   resolution: VideoResolution
+  ratio: number
   fps: number
 }) {
-  const { input, resolution, fps } = options
-  const probe = await ffprobePromise(input)
+  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)
+}
 
-  const videoStream = await getVideoStreamFromFile(input, probe)
-  if (!videoStream) return undefined
+function capBitrate (inputBitrate: number, targetBitrate: number) {
+  if (!inputBitrate) return targetBitrate
 
-  const targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS)
+  // Add 30% margin to input bitrate
+  const inputBitrateWithMargin = inputBitrate + (inputBitrate * 0.3)
 
-  // Don't transcode to an higher bitrate than the original file
-  const fileBitrate = await getVideoFileBitrate(input, probe)
-  return Math.min(targetBitrate, fileBitrate)
+  return Math.min(targetBitrate, inputBitrateWithMargin)
 }