diff options
author | Chocobozzz <me@florianbigard.com> | 2020-11-24 14:08:23 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2020-11-25 10:07:51 +0100 |
commit | 5a547f69d5dc5867e253f7721513479c754b4f15 (patch) | |
tree | 5ccad0e07d04e24d7a4c0b624a46d3b5a93ebce5 /server/lib/video-transcoding.ts | |
parent | 9252a33d115bba85adcfbc18ab3725924642871c (diff) | |
download | PeerTube-5a547f69d5dc5867e253f7721513479c754b4f15.tar.gz PeerTube-5a547f69d5dc5867e253f7721513479c754b4f15.tar.zst PeerTube-5a547f69d5dc5867e253f7721513479c754b4f15.zip |
Support encoding profiles
Diffstat (limited to 'server/lib/video-transcoding.ts')
-rw-r--r-- | server/lib/video-transcoding.ts | 91 |
1 files changed, 5 insertions, 86 deletions
diff --git a/server/lib/video-transcoding.ts b/server/lib/video-transcoding.ts index 0e6a0e984..aaad219dd 100644 --- a/server/lib/video-transcoding.ts +++ b/server/lib/video-transcoding.ts | |||
@@ -2,30 +2,18 @@ import { copyFile, ensureDir, move, remove, stat } from 'fs-extra' | |||
2 | import { basename, extname as extnameUtil, join } from 'path' | 2 | import { basename, extname as extnameUtil, join } from 'path' |
3 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 3 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' |
4 | import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoWithAllFiles, MVideoWithFile } from '@server/types/models' | 4 | import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoWithAllFiles, MVideoWithFile } from '@server/types/models' |
5 | import { getTargetBitrate, VideoResolution } from '../../shared/models/videos' | 5 | import { VideoResolution } from '../../shared/models/videos' |
6 | import { VideoStreamingPlaylistType } from '../../shared/models/videos/video-streaming-playlist.type' | 6 | import { VideoStreamingPlaylistType } from '../../shared/models/videos/video-streaming-playlist.type' |
7 | import { AvailableEncoders, EncoderOptionsBuilder, transcode, TranscodeOptions, TranscodeOptionsType } from '../helpers/ffmpeg-utils' | 7 | import { transcode, TranscodeOptions, TranscodeOptionsType } from '../helpers/ffmpeg-utils' |
8 | import { | 8 | import { canDoQuickTranscode, getDurationFromVideoFile, getMetadataFromFile, getVideoFileFPS } from '../helpers/ffprobe-utils' |
9 | canDoQuickTranscode, | ||
10 | getAudioStream, | ||
11 | getDurationFromVideoFile, | ||
12 | getMaxAudioBitrate, | ||
13 | getMetadataFromFile, | ||
14 | getVideoFileBitrate, | ||
15 | getVideoFileFPS | ||
16 | } from '../helpers/ffprobe-utils' | ||
17 | import { logger } from '../helpers/logger' | 9 | import { logger } from '../helpers/logger' |
18 | import { CONFIG } from '../initializers/config' | 10 | import { CONFIG } from '../initializers/config' |
19 | import { | 11 | import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../initializers/constants' |
20 | HLS_STREAMING_PLAYLIST_DIRECTORY, | ||
21 | P2P_MEDIA_LOADER_PEER_VERSION, | ||
22 | VIDEO_TRANSCODING_FPS, | ||
23 | WEBSERVER | ||
24 | } from '../initializers/constants' | ||
25 | import { VideoFileModel } from '../models/video/video-file' | 12 | import { VideoFileModel } from '../models/video/video-file' |
26 | import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist' | 13 | import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist' |
27 | import { updateMasterHLSPlaylist, updateSha256VODSegments } from './hls' | 14 | import { updateMasterHLSPlaylist, updateSha256VODSegments } from './hls' |
28 | import { generateVideoStreamingPlaylistName, getVideoFilename, getVideoFilePath } from './video-paths' | 15 | import { generateVideoStreamingPlaylistName, getVideoFilename, getVideoFilePath } from './video-paths' |
16 | import { availableEncoders } from './video-transcoding-profiles' | ||
29 | 17 | ||
30 | /** | 18 | /** |
31 | * Optimize the original video file and replace it. The resolution is not changed. | 19 | * Optimize the original video file and replace it. The resolution is not changed. |
@@ -253,75 +241,6 @@ async function generateHlsPlaylist (options: { | |||
253 | } | 241 | } |
254 | 242 | ||
255 | // --------------------------------------------------------------------------- | 243 | // --------------------------------------------------------------------------- |
256 | // Available encoders profiles | ||
257 | // --------------------------------------------------------------------------- | ||
258 | |||
259 | const defaultX264OptionsBuilder: EncoderOptionsBuilder = async ({ input, resolution, fps }) => { | ||
260 | if (!fps) return { outputOptions: [] } | ||
261 | |||
262 | let targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS) | ||
263 | |||
264 | // Don't transcode to an higher bitrate than the original file | ||
265 | const fileBitrate = await getVideoFileBitrate(input) | ||
266 | targetBitrate = Math.min(targetBitrate, fileBitrate) | ||
267 | |||
268 | return { | ||
269 | outputOptions: [ | ||
270 | // Constrained Encoding (VBV) | ||
271 | // https://slhck.info/video/2017/03/01/rate-control.html | ||
272 | // https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate | ||
273 | `-maxrate ${targetBitrate}`, `-bufsize ${targetBitrate * 2}` | ||
274 | ] | ||
275 | } | ||
276 | } | ||
277 | |||
278 | const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input }) => { | ||
279 | const parsedAudio = await getAudioStream(input) | ||
280 | |||
281 | // we try to reduce the ceiling bitrate by making rough matches of bitrates | ||
282 | // of course this is far from perfect, but it might save some space in the end | ||
283 | |||
284 | const audioCodecName = parsedAudio.audioStream['codec_name'] | ||
285 | |||
286 | const bitrate = getMaxAudioBitrate(audioCodecName, parsedAudio.bitrate) | ||
287 | |||
288 | if (bitrate !== undefined && bitrate !== -1) { | ||
289 | return { outputOptions: [ '-b:a', bitrate + 'k' ] } | ||
290 | } | ||
291 | |||
292 | return { outputOptions: [] } | ||
293 | } | ||
294 | |||
295 | const defaultLibFDKAACOptionsBuilder: EncoderOptionsBuilder = () => { | ||
296 | return { outputOptions: [ '-aq', '5' ] } | ||
297 | } | ||
298 | |||
299 | const availableEncoders: AvailableEncoders = { | ||
300 | vod: { | ||
301 | libx264: { | ||
302 | default: defaultX264OptionsBuilder | ||
303 | }, | ||
304 | aac: { | ||
305 | default: defaultAACOptionsBuilder | ||
306 | }, | ||
307 | libfdkAAC: { | ||
308 | default: defaultLibFDKAACOptionsBuilder | ||
309 | } | ||
310 | }, | ||
311 | live: { | ||
312 | libx264: { | ||
313 | default: defaultX264OptionsBuilder | ||
314 | }, | ||
315 | aac: { | ||
316 | default: defaultAACOptionsBuilder | ||
317 | }, | ||
318 | libfdkAAC: { | ||
319 | default: defaultLibFDKAACOptionsBuilder | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | |||
324 | // --------------------------------------------------------------------------- | ||
325 | 244 | ||
326 | export { | 245 | export { |
327 | generateHlsPlaylist, | 246 | generateHlsPlaylist, |