aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/transcoding
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-05-04 15:55:51 +0200
committerChocobozzz <chocobozzz@cpy.re>2023-05-09 08:57:34 +0200
commitab14f0e0dca878dbaccc8f6a895a68e4269c9873 (patch)
tree078247f8620ee1f3260b8c3e3336059863273eb8 /server/lib/transcoding
parent5e47f6ab984a7d00782e4c7030afffa1ba480add (diff)
downloadPeerTube-ab14f0e0dca878dbaccc8f6a895a68e4269c9873.tar.gz
PeerTube-ab14f0e0dca878dbaccc8f6a895a68e4269c9873.tar.zst
PeerTube-ab14f0e0dca878dbaccc8f6a895a68e4269c9873.zip
Prefer video studio instead of video edition
Clearer and easier to find in the project
Diffstat (limited to 'server/lib/transcoding')
-rw-r--r--server/lib/transcoding/default-transcoding-profiles.ts145
1 files changed, 3 insertions, 142 deletions
diff --git a/server/lib/transcoding/default-transcoding-profiles.ts b/server/lib/transcoding/default-transcoding-profiles.ts
index 5251784ac..8f8fdd026 100644
--- a/server/lib/transcoding/default-transcoding-profiles.ts
+++ b/server/lib/transcoding/default-transcoding-profiles.ts
@@ -1,88 +1,7 @@
1 1
2import { logger } from '@server/helpers/logger' 2import { logger } from '@server/helpers/logger'
3import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils' 3import { FFmpegCommandWrapper, getDefaultAvailableEncoders } from '@shared/ffmpeg'
4import { buildStreamSuffix, FFmpegCommandWrapper, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '@shared/ffmpeg' 4import { AvailableEncoders, EncoderOptionsBuilder } from '@shared/models'
5import { AvailableEncoders, EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '@shared/models'
6import { canDoQuickAudioTranscode } from './transcoding-quick-transcode'
7
8/**
9 *
10 * Available encoders and profiles for the transcoding jobs
11 * These functions are used by ffmpeg-utils that will get the encoders and options depending on the chosen profile
12 *
13 * Resources:
14 * * https://slhck.info/video/2017/03/01/rate-control.html
15 * * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate
16 */
17
18// ---------------------------------------------------------------------------
19// Default builders
20// ---------------------------------------------------------------------------
21
22const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
23 const { fps, inputRatio, inputBitrate, resolution } = options
24
25 // TODO: remove in 4.2, fps is not optional anymore
26 if (!fps) return { outputOptions: [ ] }
27
28 const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
29
30 return {
31 outputOptions: [
32 ...getCommonOutputOptions(targetBitrate),
33
34 `-r ${fps}`
35 ]
36 }
37}
38
39const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
40 const { streamNum, fps, inputBitrate, inputRatio, resolution } = options
41
42 const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
43
44 return {
45 outputOptions: [
46 ...getCommonOutputOptions(targetBitrate, streamNum),
47
48 `${buildStreamSuffix('-r:v', streamNum)} ${fps}`,
49 `${buildStreamSuffix('-b:v', streamNum)} ${targetBitrate}`
50 ]
51 }
52}
53
54const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum, canCopyAudio }) => {
55 const probe = await ffprobePromise(input)
56
57 if (canCopyAudio && await canDoQuickAudioTranscode(input, probe)) {
58 logger.debug('Copy audio stream %s by AAC encoder.', input)
59 return { copy: true, outputOptions: [ ] }
60 }
61
62 const parsedAudio = await getAudioStream(input, probe)
63
64 // We try to reduce the ceiling bitrate by making rough matches of bitrates
65 // Of course this is far from perfect, but it might save some space in the end
66
67 const audioCodecName = parsedAudio.audioStream['codec_name']
68
69 const bitrate = getMaxAudioBitrate(audioCodecName, parsedAudio.bitrate)
70
71 logger.debug('Calculating audio bitrate of %s by AAC encoder.', input, { bitrate: parsedAudio.bitrate, audioCodecName })
72
73 // Force stereo as it causes some issues with HLS playback in Chrome
74 const base = [ '-channel_layout', 'stereo' ]
75
76 if (bitrate !== -1) {
77 return { outputOptions: base.concat([ buildStreamSuffix('-b:a', streamNum), bitrate + 'k' ]) }
78 }
79
80 return { outputOptions: base }
81}
82
83const defaultLibFDKAACVODOptionsBuilder: EncoderOptionsBuilder = ({ streamNum }) => {
84 return { outputOptions: [ buildStreamSuffix('-q:a', streamNum), '5' ] }
85}
86 5
87// --------------------------------------------------------------------------- 6// ---------------------------------------------------------------------------
88// Profile manager to get and change default profiles 7// Profile manager to get and change default profiles
@@ -97,27 +16,7 @@ class VideoTranscodingProfilesManager {
97 live: this.buildDefaultEncodersPriorities() 16 live: this.buildDefaultEncodersPriorities()
98 } 17 }
99 18
100 private readonly availableEncoders = { 19 private readonly availableEncoders = getDefaultAvailableEncoders()
101 vod: {
102 libx264: {
103 default: defaultX264VODOptionsBuilder
104 },
105 aac: {
106 default: defaultAACOptionsBuilder
107 },
108 libfdk_aac: {
109 default: defaultLibFDKAACVODOptionsBuilder
110 }
111 },
112 live: {
113 libx264: {
114 default: defaultX264LiveOptionsBuilder
115 },
116 aac: {
117 default: defaultAACOptionsBuilder
118 }
119 }
120 }
121 20
122 private availableProfiles = { 21 private availableProfiles = {
123 vod: [] as string[], 22 vod: [] as string[],
@@ -242,41 +141,3 @@ class VideoTranscodingProfilesManager {
242export { 141export {
243 VideoTranscodingProfilesManager 142 VideoTranscodingProfilesManager
244} 143}
245
246// ---------------------------------------------------------------------------
247
248function getTargetBitrate (options: {
249 inputBitrate: number
250 resolution: VideoResolution
251 ratio: number
252 fps: number
253}) {
254 const { inputBitrate, resolution, ratio, fps } = options
255
256 const capped = capBitrate(inputBitrate, getAverageBitrate({ resolution, fps, ratio }))
257 const limit = getMinLimitBitrate({ resolution, fps, ratio })
258
259 return Math.max(limit, capped)
260}
261
262function capBitrate (inputBitrate: number, targetBitrate: number) {
263 if (!inputBitrate) return targetBitrate
264
265 // Add 30% margin to input bitrate
266 const inputBitrateWithMargin = inputBitrate + (inputBitrate * 0.3)
267
268 return Math.min(targetBitrate, inputBitrateWithMargin)
269}
270
271function getCommonOutputOptions (targetBitrate: number, streamNum?: number) {
272 return [
273 `-preset veryfast`,
274 `${buildStreamSuffix('-maxrate:v', streamNum)} ${targetBitrate}`,
275 `${buildStreamSuffix('-bufsize:v', streamNum)} ${targetBitrate * 2}`,
276
277 // NOTE: b-strategy 1 - heuristic algorithm, 16 is optimal B-frames for it
278 `-b_strategy 1`,
279 // NOTE: Why 16: https://github.com/Chocobozzz/PeerTube/pull/774. b-strategy 2 -> B-frames<16
280 `-bf 16`
281 ]
282}