diff options
Diffstat (limited to 'shared')
-rw-r--r-- | shared/ffmpeg/ffmpeg-default-transcoding-profile.ts | 134 | ||||
-rw-r--r-- | shared/ffmpeg/index.ts | 1 | ||||
-rw-r--r-- | shared/models/runners/runner-job-payload.model.ts | 4 | ||||
-rw-r--r-- | shared/models/runners/runner-job-private-payload.model.ts | 4 | ||||
-rw-r--r-- | shared/models/runners/runner-job-success-body.model.ts | 4 | ||||
-rw-r--r-- | shared/models/runners/runner-job-type.type.ts | 2 |
6 files changed, 142 insertions, 7 deletions
diff --git a/shared/ffmpeg/ffmpeg-default-transcoding-profile.ts b/shared/ffmpeg/ffmpeg-default-transcoding-profile.ts new file mode 100644 index 000000000..f7fc49465 --- /dev/null +++ b/shared/ffmpeg/ffmpeg-default-transcoding-profile.ts | |||
@@ -0,0 +1,134 @@ | |||
1 | import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils' | ||
2 | import { buildStreamSuffix, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '@shared/ffmpeg' | ||
3 | import { EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '@shared/models' | ||
4 | |||
5 | const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => { | ||
6 | const { fps, inputRatio, inputBitrate, resolution } = options | ||
7 | |||
8 | const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution }) | ||
9 | |||
10 | return { | ||
11 | outputOptions: [ | ||
12 | ...getCommonOutputOptions(targetBitrate), | ||
13 | |||
14 | `-r ${fps}` | ||
15 | ] | ||
16 | } | ||
17 | } | ||
18 | |||
19 | const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => { | ||
20 | const { streamNum, fps, inputBitrate, inputRatio, resolution } = options | ||
21 | |||
22 | const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution }) | ||
23 | |||
24 | return { | ||
25 | outputOptions: [ | ||
26 | ...getCommonOutputOptions(targetBitrate, streamNum), | ||
27 | |||
28 | `${buildStreamSuffix('-r:v', streamNum)} ${fps}`, | ||
29 | `${buildStreamSuffix('-b:v', streamNum)} ${targetBitrate}` | ||
30 | ] | ||
31 | } | ||
32 | } | ||
33 | |||
34 | const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum, canCopyAudio }) => { | ||
35 | const probe = await ffprobePromise(input) | ||
36 | |||
37 | const parsedAudio = await getAudioStream(input, probe) | ||
38 | |||
39 | // We try to reduce the ceiling bitrate by making rough matches of bitrates | ||
40 | // Of course this is far from perfect, but it might save some space in the end | ||
41 | |||
42 | const audioCodecName = parsedAudio.audioStream['codec_name'] | ||
43 | |||
44 | const bitrate = getMaxAudioBitrate(audioCodecName, parsedAudio.bitrate) | ||
45 | |||
46 | // Force stereo as it causes some issues with HLS playback in Chrome | ||
47 | const base = [ '-channel_layout', 'stereo' ] | ||
48 | |||
49 | if (bitrate !== -1) { | ||
50 | return { outputOptions: base.concat([ buildStreamSuffix('-b:a', streamNum), bitrate + 'k' ]) } | ||
51 | } | ||
52 | |||
53 | return { outputOptions: base } | ||
54 | } | ||
55 | |||
56 | const defaultLibFDKAACVODOptionsBuilder: EncoderOptionsBuilder = ({ streamNum }) => { | ||
57 | return { outputOptions: [ buildStreamSuffix('-q:a', streamNum), '5' ] } | ||
58 | } | ||
59 | |||
60 | export function getDefaultAvailableEncoders () { | ||
61 | return { | ||
62 | vod: { | ||
63 | libx264: { | ||
64 | default: defaultX264VODOptionsBuilder | ||
65 | }, | ||
66 | aac: { | ||
67 | default: defaultAACOptionsBuilder | ||
68 | }, | ||
69 | libfdk_aac: { | ||
70 | default: defaultLibFDKAACVODOptionsBuilder | ||
71 | } | ||
72 | }, | ||
73 | live: { | ||
74 | libx264: { | ||
75 | default: defaultX264LiveOptionsBuilder | ||
76 | }, | ||
77 | aac: { | ||
78 | default: defaultAACOptionsBuilder | ||
79 | } | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | export function getDefaultEncodersToTry () { | ||
85 | return { | ||
86 | vod: { | ||
87 | video: [ 'libx264' ], | ||
88 | audio: [ 'libfdk_aac', 'aac' ] | ||
89 | }, | ||
90 | |||
91 | live: { | ||
92 | video: [ 'libx264' ], | ||
93 | audio: [ 'libfdk_aac', 'aac' ] | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | // --------------------------------------------------------------------------- | ||
99 | |||
100 | function getTargetBitrate (options: { | ||
101 | inputBitrate: number | ||
102 | resolution: VideoResolution | ||
103 | ratio: number | ||
104 | fps: number | ||
105 | }) { | ||
106 | const { inputBitrate, resolution, ratio, fps } = options | ||
107 | |||
108 | const capped = capBitrate(inputBitrate, getAverageBitrate({ resolution, fps, ratio })) | ||
109 | const limit = getMinLimitBitrate({ resolution, fps, ratio }) | ||
110 | |||
111 | return Math.max(limit, capped) | ||
112 | } | ||
113 | |||
114 | function capBitrate (inputBitrate: number, targetBitrate: number) { | ||
115 | if (!inputBitrate) return targetBitrate | ||
116 | |||
117 | // Add 30% margin to input bitrate | ||
118 | const inputBitrateWithMargin = inputBitrate + (inputBitrate * 0.3) | ||
119 | |||
120 | return Math.min(targetBitrate, inputBitrateWithMargin) | ||
121 | } | ||
122 | |||
123 | function getCommonOutputOptions (targetBitrate: number, streamNum?: number) { | ||
124 | return [ | ||
125 | `-preset veryfast`, | ||
126 | `${buildStreamSuffix('-maxrate:v', streamNum)} ${targetBitrate}`, | ||
127 | `${buildStreamSuffix('-bufsize:v', streamNum)} ${targetBitrate * 2}`, | ||
128 | |||
129 | // NOTE: b-strategy 1 - heuristic algorithm, 16 is optimal B-frames for it | ||
130 | `-b_strategy 1`, | ||
131 | // NOTE: Why 16: https://github.com/Chocobozzz/PeerTube/pull/774. b-strategy 2 -> B-frames<16 | ||
132 | `-bf 16` | ||
133 | ] | ||
134 | } | ||
diff --git a/shared/ffmpeg/index.ts b/shared/ffmpeg/index.ts index 07a7d5402..1dab292da 100644 --- a/shared/ffmpeg/index.ts +++ b/shared/ffmpeg/index.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | export * from './ffmpeg-command-wrapper' | 1 | export * from './ffmpeg-command-wrapper' |
2 | export * from './ffmpeg-default-transcoding-profile' | ||
2 | export * from './ffmpeg-edition' | 3 | export * from './ffmpeg-edition' |
3 | export * from './ffmpeg-images' | 4 | export * from './ffmpeg-images' |
4 | export * from './ffmpeg-live' | 5 | export * from './ffmpeg-live' |
diff --git a/shared/models/runners/runner-job-payload.model.ts b/shared/models/runners/runner-job-payload.model.ts index 9f0db0dc4..3dda6c51f 100644 --- a/shared/models/runners/runner-job-payload.model.ts +++ b/shared/models/runners/runner-job-payload.model.ts | |||
@@ -8,7 +8,7 @@ export type RunnerJobVODPayload = | |||
8 | export type RunnerJobPayload = | 8 | export type RunnerJobPayload = |
9 | RunnerJobVODPayload | | 9 | RunnerJobVODPayload | |
10 | RunnerJobLiveRTMPHLSTranscodingPayload | | 10 | RunnerJobLiveRTMPHLSTranscodingPayload | |
11 | RunnerJobVideoEditionTranscodingPayload | 11 | RunnerJobStudioTranscodingPayload |
12 | 12 | ||
13 | // --------------------------------------------------------------------------- | 13 | // --------------------------------------------------------------------------- |
14 | 14 | ||
@@ -46,7 +46,7 @@ export interface RunnerJobVODAudioMergeTranscodingPayload { | |||
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | export interface RunnerJobVideoEditionTranscodingPayload { | 49 | export interface RunnerJobStudioTranscodingPayload { |
50 | input: { | 50 | input: { |
51 | videoFileUrl: string | 51 | videoFileUrl: string |
52 | } | 52 | } |
diff --git a/shared/models/runners/runner-job-private-payload.model.ts b/shared/models/runners/runner-job-private-payload.model.ts index c8fe0a7d8..32b837de4 100644 --- a/shared/models/runners/runner-job-private-payload.model.ts +++ b/shared/models/runners/runner-job-private-payload.model.ts | |||
@@ -8,7 +8,7 @@ export type RunnerJobVODPrivatePayload = | |||
8 | export type RunnerJobPrivatePayload = | 8 | export type RunnerJobPrivatePayload = |
9 | RunnerJobVODPrivatePayload | | 9 | RunnerJobVODPrivatePayload | |
10 | RunnerJobLiveRTMPHLSTranscodingPrivatePayload | | 10 | RunnerJobLiveRTMPHLSTranscodingPrivatePayload | |
11 | RunnerJobVideoEditionTranscodingPrivatePayload | 11 | RunnerJobVideoStudioTranscodingPrivatePayload |
12 | 12 | ||
13 | // --------------------------------------------------------------------------- | 13 | // --------------------------------------------------------------------------- |
14 | 14 | ||
@@ -38,7 +38,7 @@ export interface RunnerJobLiveRTMPHLSTranscodingPrivatePayload { | |||
38 | 38 | ||
39 | // --------------------------------------------------------------------------- | 39 | // --------------------------------------------------------------------------- |
40 | 40 | ||
41 | export interface RunnerJobVideoEditionTranscodingPrivatePayload { | 41 | export interface RunnerJobVideoStudioTranscodingPrivatePayload { |
42 | videoUUID: string | 42 | videoUUID: string |
43 | originalTasks: VideoStudioTaskPayload[] | 43 | originalTasks: VideoStudioTaskPayload[] |
44 | } | 44 | } |
diff --git a/shared/models/runners/runner-job-success-body.model.ts b/shared/models/runners/runner-job-success-body.model.ts index 17e921f69..f45336b05 100644 --- a/shared/models/runners/runner-job-success-body.model.ts +++ b/shared/models/runners/runner-job-success-body.model.ts | |||
@@ -12,7 +12,7 @@ export type RunnerJobSuccessPayload = | |||
12 | VODHLSTranscodingSuccess | | 12 | VODHLSTranscodingSuccess | |
13 | VODAudioMergeTranscodingSuccess | | 13 | VODAudioMergeTranscodingSuccess | |
14 | LiveRTMPHLSTranscodingSuccess | | 14 | LiveRTMPHLSTranscodingSuccess | |
15 | VideoEditionTranscodingSuccess | 15 | VideoStudioTranscodingSuccess |
16 | 16 | ||
17 | export interface VODWebVideoTranscodingSuccess { | 17 | export interface VODWebVideoTranscodingSuccess { |
18 | videoFile: Blob | string | 18 | videoFile: Blob | string |
@@ -31,7 +31,7 @@ export interface LiveRTMPHLSTranscodingSuccess { | |||
31 | 31 | ||
32 | } | 32 | } |
33 | 33 | ||
34 | export interface VideoEditionTranscodingSuccess { | 34 | export interface VideoStudioTranscodingSuccess { |
35 | videoFile: Blob | string | 35 | videoFile: Blob | string |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/shared/models/runners/runner-job-type.type.ts b/shared/models/runners/runner-job-type.type.ts index 3b997cb6e..91b92a729 100644 --- a/shared/models/runners/runner-job-type.type.ts +++ b/shared/models/runners/runner-job-type.type.ts | |||
@@ -3,4 +3,4 @@ export type RunnerJobType = | |||
3 | 'vod-hls-transcoding' | | 3 | 'vod-hls-transcoding' | |
4 | 'vod-audio-merge-transcoding' | | 4 | 'vod-audio-merge-transcoding' | |
5 | 'live-rtmp-hls-transcoding' | | 5 | 'live-rtmp-hls-transcoding' | |
6 | 'video-edition-transcoding' | 6 | 'video-studio-transcoding' |