diff options
Diffstat (limited to 'server/lib/video-transcoding-profiles.ts')
-rw-r--r-- | server/lib/video-transcoding-profiles.ts | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/server/lib/video-transcoding-profiles.ts b/server/lib/video-transcoding-profiles.ts new file mode 100644 index 000000000..12e22a19d --- /dev/null +++ b/server/lib/video-transcoding-profiles.ts | |||
@@ -0,0 +1,95 @@ | |||
1 | import { getTargetBitrate } from '../../shared/models/videos' | ||
2 | import { AvailableEncoders, buildStreamSuffix, EncoderOptionsBuilder } from '../helpers/ffmpeg-utils' | ||
3 | import { ffprobePromise, getAudioStream, getMaxAudioBitrate, getVideoFileBitrate, getVideoStreamFromFile } from '../helpers/ffprobe-utils' | ||
4 | import { VIDEO_TRANSCODING_FPS } from '../initializers/constants' | ||
5 | |||
6 | // --------------------------------------------------------------------------- | ||
7 | // Available encoders profiles | ||
8 | // --------------------------------------------------------------------------- | ||
9 | |||
10 | // Resources: | ||
11 | // * https://slhck.info/video/2017/03/01/rate-control.html | ||
12 | // * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate | ||
13 | |||
14 | const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = async ({ input, resolution, fps }) => { | ||
15 | let targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS) | ||
16 | |||
17 | const probe = await ffprobePromise(input) | ||
18 | |||
19 | const videoStream = await getVideoStreamFromFile(input, probe) | ||
20 | if (!videoStream) { | ||
21 | return { outputOptions: [ ] } | ||
22 | } | ||
23 | |||
24 | // Don't transcode to an higher bitrate than the original file | ||
25 | const fileBitrate = await getVideoFileBitrate(input, probe) | ||
26 | targetBitrate = Math.min(targetBitrate, fileBitrate) | ||
27 | |||
28 | return { | ||
29 | outputOptions: [ | ||
30 | `-maxrate ${targetBitrate}`, `-bufsize ${targetBitrate * 2}` | ||
31 | ] | ||
32 | } | ||
33 | } | ||
34 | |||
35 | const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = async ({ resolution, fps, streamNum }) => { | ||
36 | const targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS) | ||
37 | |||
38 | return { | ||
39 | outputOptions: [ | ||
40 | `${buildStreamSuffix('-b:v', streamNum)} ${targetBitrate}`, | ||
41 | `-maxrate ${targetBitrate}`, `-bufsize ${targetBitrate * 2}` | ||
42 | ] | ||
43 | } | ||
44 | } | ||
45 | |||
46 | const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum }) => { | ||
47 | const parsedAudio = await getAudioStream(input) | ||
48 | |||
49 | // We try to reduce the ceiling bitrate by making rough matches of bitrates | ||
50 | // Of course this is far from perfect, but it might save some space in the end | ||
51 | |||
52 | const audioCodecName = parsedAudio.audioStream['codec_name'] | ||
53 | |||
54 | const bitrate = getMaxAudioBitrate(audioCodecName, parsedAudio.bitrate) | ||
55 | |||
56 | if (bitrate !== undefined && bitrate !== -1) { | ||
57 | return { outputOptions: [ buildStreamSuffix('-b:a', streamNum), bitrate + 'k' ] } | ||
58 | } | ||
59 | |||
60 | return { copy: true, outputOptions: [] } | ||
61 | } | ||
62 | |||
63 | const defaultLibFDKAACVODOptionsBuilder: EncoderOptionsBuilder = ({ streamNum }) => { | ||
64 | return { outputOptions: [ buildStreamSuffix('-q:a', streamNum), '5' ] } | ||
65 | } | ||
66 | |||
67 | const availableEncoders: AvailableEncoders = { | ||
68 | vod: { | ||
69 | libx264: { | ||
70 | default: defaultX264VODOptionsBuilder | ||
71 | }, | ||
72 | aac: { | ||
73 | default: defaultAACOptionsBuilder | ||
74 | }, | ||
75 | libfdk_aac: { | ||
76 | default: defaultLibFDKAACVODOptionsBuilder | ||
77 | } | ||
78 | }, | ||
79 | live: { | ||
80 | libx264: { | ||
81 | default: defaultX264LiveOptionsBuilder | ||
82 | }, | ||
83 | aac: { | ||
84 | default: defaultAACOptionsBuilder | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | // --------------------------------------------------------------------------- | ||
90 | |||
91 | export { | ||
92 | availableEncoders | ||
93 | } | ||
94 | |||
95 | // --------------------------------------------------------------------------- | ||