diff options
author | Chocobozzz <me@florianbigard.com> | 2021-08-06 10:39:40 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-08-06 10:39:40 +0200 |
commit | c826f34a45757b324a20f71665b44ed10e6953b5 (patch) | |
tree | ff29bdff8b4519bbdbbcd3aa0d68521ce2b06ff5 /server/lib | |
parent | 421ff4618da64f0849353383f690a014024c40da (diff) | |
download | PeerTube-c826f34a45757b324a20f71665b44ed10e6953b5.tar.gz PeerTube-c826f34a45757b324a20f71665b44ed10e6953b5.tar.zst PeerTube-c826f34a45757b324a20f71665b44ed10e6953b5.zip |
Limit live bitrate
Diffstat (limited to 'server/lib')
-rw-r--r-- | server/lib/live/live-manager.ts | 28 | ||||
-rw-r--r-- | server/lib/live/shared/muxing-session.ts | 5 | ||||
-rw-r--r-- | server/lib/transcoding/video-transcoding-profiles.ts | 33 |
3 files changed, 39 insertions, 27 deletions
diff --git a/server/lib/live/live-manager.ts b/server/lib/live/live-manager.ts index f106d69fb..b19ecef6f 100644 --- a/server/lib/live/live-manager.ts +++ b/server/lib/live/live-manager.ts | |||
@@ -1,7 +1,13 @@ | |||
1 | 1 | ||
2 | import { createServer, Server } from 'net' | 2 | import { createServer, Server } from 'net' |
3 | import { isTestInstance } from '@server/helpers/core-utils' | 3 | import { isTestInstance } from '@server/helpers/core-utils' |
4 | import { computeResolutionsToTranscode, getVideoFileFPS, getVideoFileResolution } from '@server/helpers/ffprobe-utils' | 4 | import { |
5 | computeResolutionsToTranscode, | ||
6 | ffprobePromise, | ||
7 | getVideoFileBitrate, | ||
8 | getVideoFileFPS, | ||
9 | getVideoFileResolution | ||
10 | } from '@server/helpers/ffprobe-utils' | ||
5 | import { logger, loggerTagsFactory } from '@server/helpers/logger' | 11 | import { logger, loggerTagsFactory } from '@server/helpers/logger' |
6 | import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' | 12 | import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' |
7 | import { P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, VIEW_LIFETIME } from '@server/initializers/constants' | 13 | import { P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, VIEW_LIFETIME } from '@server/initializers/constants' |
@@ -193,11 +199,20 @@ class LiveManager { | |||
193 | 199 | ||
194 | const rtmpUrl = 'rtmp://127.0.0.1:' + config.rtmp.port + streamPath | 200 | const rtmpUrl = 'rtmp://127.0.0.1:' + config.rtmp.port + streamPath |
195 | 201 | ||
196 | const [ { videoFileResolution }, fps ] = await Promise.all([ | 202 | const now = Date.now() |
197 | getVideoFileResolution(rtmpUrl), | 203 | const probe = await ffprobePromise(rtmpUrl) |
198 | getVideoFileFPS(rtmpUrl) | 204 | |
205 | const [ { videoFileResolution }, fps, bitrate ] = await Promise.all([ | ||
206 | getVideoFileResolution(rtmpUrl, probe), | ||
207 | getVideoFileFPS(rtmpUrl, probe), | ||
208 | getVideoFileBitrate(rtmpUrl, probe) | ||
199 | ]) | 209 | ]) |
200 | 210 | ||
211 | logger.info( | ||
212 | '%s probing took %d ms (bitrate: %d, fps: %d, resolution: %d)', | ||
213 | rtmpUrl, Date.now() - now, bitrate, fps, videoFileResolution, lTags(sessionId, video.uuid) | ||
214 | ) | ||
215 | |||
201 | const allResolutions = this.buildAllResolutionsToTranscode(videoFileResolution) | 216 | const allResolutions = this.buildAllResolutionsToTranscode(videoFileResolution) |
202 | 217 | ||
203 | logger.info( | 218 | logger.info( |
@@ -213,6 +228,7 @@ class LiveManager { | |||
213 | streamingPlaylist, | 228 | streamingPlaylist, |
214 | rtmpUrl, | 229 | rtmpUrl, |
215 | fps, | 230 | fps, |
231 | bitrate, | ||
216 | allResolutions | 232 | allResolutions |
217 | }) | 233 | }) |
218 | } | 234 | } |
@@ -223,9 +239,10 @@ class LiveManager { | |||
223 | streamingPlaylist: MStreamingPlaylistVideo | 239 | streamingPlaylist: MStreamingPlaylistVideo |
224 | rtmpUrl: string | 240 | rtmpUrl: string |
225 | fps: number | 241 | fps: number |
242 | bitrate: number | ||
226 | allResolutions: number[] | 243 | allResolutions: number[] |
227 | }) { | 244 | }) { |
228 | const { sessionId, videoLive, streamingPlaylist, allResolutions, fps, rtmpUrl } = options | 245 | const { sessionId, videoLive, streamingPlaylist, allResolutions, fps, bitrate, rtmpUrl } = options |
229 | const videoUUID = videoLive.Video.uuid | 246 | const videoUUID = videoLive.Video.uuid |
230 | const localLTags = lTags(sessionId, videoUUID) | 247 | const localLTags = lTags(sessionId, videoUUID) |
231 | 248 | ||
@@ -239,6 +256,7 @@ class LiveManager { | |||
239 | videoLive, | 256 | videoLive, |
240 | streamingPlaylist, | 257 | streamingPlaylist, |
241 | rtmpUrl, | 258 | rtmpUrl, |
259 | bitrate, | ||
242 | fps, | 260 | fps, |
243 | allResolutions | 261 | allResolutions |
244 | }) | 262 | }) |
diff --git a/server/lib/live/shared/muxing-session.ts b/server/lib/live/shared/muxing-session.ts index 709d6c615..62708b14b 100644 --- a/server/lib/live/shared/muxing-session.ts +++ b/server/lib/live/shared/muxing-session.ts | |||
@@ -54,6 +54,7 @@ class MuxingSession extends EventEmitter { | |||
54 | private readonly streamingPlaylist: MStreamingPlaylistVideo | 54 | private readonly streamingPlaylist: MStreamingPlaylistVideo |
55 | private readonly rtmpUrl: string | 55 | private readonly rtmpUrl: string |
56 | private readonly fps: number | 56 | private readonly fps: number |
57 | private readonly bitrate: number | ||
57 | private readonly allResolutions: number[] | 58 | private readonly allResolutions: number[] |
58 | 59 | ||
59 | private readonly videoId: number | 60 | private readonly videoId: number |
@@ -83,6 +84,7 @@ class MuxingSession extends EventEmitter { | |||
83 | streamingPlaylist: MStreamingPlaylistVideo | 84 | streamingPlaylist: MStreamingPlaylistVideo |
84 | rtmpUrl: string | 85 | rtmpUrl: string |
85 | fps: number | 86 | fps: number |
87 | bitrate: number | ||
86 | allResolutions: number[] | 88 | allResolutions: number[] |
87 | }) { | 89 | }) { |
88 | super() | 90 | super() |
@@ -94,6 +96,7 @@ class MuxingSession extends EventEmitter { | |||
94 | this.streamingPlaylist = options.streamingPlaylist | 96 | this.streamingPlaylist = options.streamingPlaylist |
95 | this.rtmpUrl = options.rtmpUrl | 97 | this.rtmpUrl = options.rtmpUrl |
96 | this.fps = options.fps | 98 | this.fps = options.fps |
99 | this.bitrate = options.bitrate | ||
97 | this.allResolutions = options.allResolutions | 100 | this.allResolutions = options.allResolutions |
98 | 101 | ||
99 | this.videoId = this.videoLive.Video.id | 102 | this.videoId = this.videoLive.Video.id |
@@ -118,6 +121,8 @@ class MuxingSession extends EventEmitter { | |||
118 | 121 | ||
119 | resolutions: this.allResolutions, | 122 | resolutions: this.allResolutions, |
120 | fps: this.fps, | 123 | fps: this.fps, |
124 | bitrate: this.bitrate, | ||
125 | |||
121 | availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(), | 126 | availableEncoders: VideoTranscodingProfilesManager.Instance.getAvailableEncoders(), |
122 | profile: CONFIG.LIVE.TRANSCODING.PROFILE | 127 | profile: CONFIG.LIVE.TRANSCODING.PROFILE |
123 | }) | 128 | }) |
diff --git a/server/lib/transcoding/video-transcoding-profiles.ts b/server/lib/transcoding/video-transcoding-profiles.ts index c5ea72a5f..2309f38d4 100644 --- a/server/lib/transcoding/video-transcoding-profiles.ts +++ b/server/lib/transcoding/video-transcoding-profiles.ts | |||
@@ -1,14 +1,7 @@ | |||
1 | import { logger } from '@server/helpers/logger' | 1 | import { logger } from '@server/helpers/logger' |
2 | import { AvailableEncoders, EncoderOptionsBuilder, getTargetBitrate, VideoResolution } from '../../../shared/models/videos' | 2 | import { AvailableEncoders, EncoderOptionsBuilder, getTargetBitrate, VideoResolution } from '../../../shared/models/videos' |
3 | import { buildStreamSuffix, resetSupportedEncoders } from '../../helpers/ffmpeg-utils' | 3 | import { buildStreamSuffix, resetSupportedEncoders } from '../../helpers/ffmpeg-utils' |
4 | import { | 4 | import { canDoQuickAudioTranscode, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '../../helpers/ffprobe-utils' |
5 | canDoQuickAudioTranscode, | ||
6 | ffprobePromise, | ||
7 | getAudioStream, | ||
8 | getMaxAudioBitrate, | ||
9 | getVideoFileBitrate, | ||
10 | getVideoStreamFromFile | ||
11 | } from '../../helpers/ffprobe-utils' | ||
12 | import { VIDEO_TRANSCODING_FPS } from '../../initializers/constants' | 5 | import { VIDEO_TRANSCODING_FPS } from '../../initializers/constants' |
13 | 6 | ||
14 | /** | 7 | /** |
@@ -22,8 +15,8 @@ import { VIDEO_TRANSCODING_FPS } from '../../initializers/constants' | |||
22 | // * https://slhck.info/video/2017/03/01/rate-control.html | 15 | // * https://slhck.info/video/2017/03/01/rate-control.html |
23 | // * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate | 16 | // * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate |
24 | 17 | ||
25 | const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = async ({ input, resolution, fps }) => { | 18 | const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = async ({ inputBitrate, resolution, fps }) => { |
26 | const targetBitrate = await buildTargetBitrate({ input, resolution, fps }) | 19 | const targetBitrate = buildTargetBitrate({ inputBitrate, resolution, fps }) |
27 | if (!targetBitrate) return { outputOptions: [ ] } | 20 | if (!targetBitrate) return { outputOptions: [ ] } |
28 | 21 | ||
29 | return { | 22 | return { |
@@ -36,8 +29,8 @@ const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = async ({ input, reso | |||
36 | } | 29 | } |
37 | } | 30 | } |
38 | 31 | ||
39 | const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = async ({ resolution, fps, streamNum }) => { | 32 | const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = async ({ resolution, fps, inputBitrate, streamNum }) => { |
40 | const targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS) | 33 | const targetBitrate = buildTargetBitrate({ inputBitrate, resolution, fps }) |
41 | 34 | ||
42 | return { | 35 | return { |
43 | outputOptions: [ | 36 | outputOptions: [ |
@@ -237,20 +230,16 @@ export { | |||
237 | } | 230 | } |
238 | 231 | ||
239 | // --------------------------------------------------------------------------- | 232 | // --------------------------------------------------------------------------- |
240 | async function buildTargetBitrate (options: { | 233 | |
241 | input: string | 234 | function buildTargetBitrate (options: { |
235 | inputBitrate: number | ||
242 | resolution: VideoResolution | 236 | resolution: VideoResolution |
243 | fps: number | 237 | fps: number |
244 | }) { | 238 | }) { |
245 | const { input, resolution, fps } = options | 239 | const { inputBitrate, resolution, fps } = options |
246 | const probe = await ffprobePromise(input) | ||
247 | |||
248 | const videoStream = await getVideoStreamFromFile(input, probe) | ||
249 | if (!videoStream) return undefined | ||
250 | 240 | ||
251 | const targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS) | 241 | const targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS) |
242 | if (!inputBitrate) return targetBitrate | ||
252 | 243 | ||
253 | // Don't transcode to an higher bitrate than the original file | 244 | return Math.min(targetBitrate, inputBitrate) |
254 | const fileBitrate = await getVideoFileBitrate(input, probe) | ||
255 | return Math.min(targetBitrate, fileBitrate) | ||
256 | } | 245 | } |