aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-05-05 10:53:04 +0200
committerChocobozzz <chocobozzz@cpy.re>2023-05-09 08:57:34 +0200
commite7d8e2b245491c0a8e008fb570037506d729ff04 (patch)
treed850a7f82cc02946f2e87b306d0b281cef5eb73d /shared
parentdd3f99434cc3cb7226d33ffcd888c91d0ce150a9 (diff)
downloadPeerTube-e7d8e2b245491c0a8e008fb570037506d729ff04.tar.gz
PeerTube-e7d8e2b245491c0a8e008fb570037506d729ff04.tar.zst
PeerTube-e7d8e2b245491c0a8e008fb570037506d729ff04.zip
Fix audio transcoding copy
Diffstat (limited to 'shared')
-rw-r--r--shared/core-utils/videos/bitrate.ts12
-rw-r--r--shared/ffmpeg/ffmpeg-default-transcoding-profile.ts61
2 files changed, 63 insertions, 10 deletions
diff --git a/shared/core-utils/videos/bitrate.ts b/shared/core-utils/videos/bitrate.ts
index 30d22df09..6be027826 100644
--- a/shared/core-utils/videos/bitrate.ts
+++ b/shared/core-utils/videos/bitrate.ts
@@ -40,7 +40,7 @@ const maxBitPerPixel: BitPerPixel = {
40 [VideoResolution.H_4K]: 0.14 40 [VideoResolution.H_4K]: 0.14
41} 41}
42 42
43function getAverageBitrate (options: { 43function getAverageTheoreticalBitrate (options: {
44 resolution: VideoResolution 44 resolution: VideoResolution
45 ratio: number 45 ratio: number
46 fps: number 46 fps: number
@@ -51,7 +51,7 @@ function getAverageBitrate (options: {
51 return targetBitrate 51 return targetBitrate
52} 52}
53 53
54function getMaxBitrate (options: { 54function getMaxTheoreticalBitrate (options: {
55 resolution: VideoResolution 55 resolution: VideoResolution
56 ratio: number 56 ratio: number
57 fps: number 57 fps: number
@@ -62,7 +62,7 @@ function getMaxBitrate (options: {
62 return targetBitrate 62 return targetBitrate
63} 63}
64 64
65function getMinLimitBitrate (options: { 65function getMinTheoreticalBitrate (options: {
66 resolution: VideoResolution 66 resolution: VideoResolution
67 ratio: number 67 ratio: number
68 fps: number 68 fps: number
@@ -76,9 +76,9 @@ function getMinLimitBitrate (options: {
76// --------------------------------------------------------------------------- 76// ---------------------------------------------------------------------------
77 77
78export { 78export {
79 getAverageBitrate, 79 getAverageTheoreticalBitrate,
80 getMaxBitrate, 80 getMaxTheoreticalBitrate,
81 getMinLimitBitrate 81 getMinTheoreticalBitrate
82} 82}
83 83
84// --------------------------------------------------------------------------- 84// ---------------------------------------------------------------------------
diff --git a/shared/ffmpeg/ffmpeg-default-transcoding-profile.ts b/shared/ffmpeg/ffmpeg-default-transcoding-profile.ts
index f7fc49465..8a3f32011 100644
--- a/shared/ffmpeg/ffmpeg-default-transcoding-profile.ts
+++ b/shared/ffmpeg/ffmpeg-default-transcoding-profile.ts
@@ -1,5 +1,15 @@
1import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils' 1import { FfprobeData } from 'fluent-ffmpeg'
2import { buildStreamSuffix, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '@shared/ffmpeg' 2import { getAverageTheoreticalBitrate, getMaxTheoreticalBitrate, getMinTheoreticalBitrate } from '@shared/core-utils'
3import {
4 buildStreamSuffix,
5 ffprobePromise,
6 getAudioStream,
7 getMaxAudioBitrate,
8 getVideoStream,
9 getVideoStreamBitrate,
10 getVideoStreamDimensionsInfo,
11 getVideoStreamFPS
12} from '@shared/ffmpeg'
3import { EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '@shared/models' 13import { EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '@shared/models'
4 14
5const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => { 15const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
@@ -34,6 +44,10 @@ const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOp
34const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum, canCopyAudio }) => { 44const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum, canCopyAudio }) => {
35 const probe = await ffprobePromise(input) 45 const probe = await ffprobePromise(input)
36 46
47 if (canCopyAudio && await canDoQuickAudioTranscode(input, probe)) {
48 return { copy: true, outputOptions: [ ] }
49 }
50
37 const parsedAudio = await getAudioStream(input, probe) 51 const parsedAudio = await getAudioStream(input, probe)
38 52
39 // We try to reduce the ceiling bitrate by making rough matches of bitrates 53 // We try to reduce the ceiling bitrate by making rough matches of bitrates
@@ -95,6 +109,45 @@ export function getDefaultEncodersToTry () {
95 } 109 }
96} 110}
97 111
112export async function canDoQuickAudioTranscode (path: string, probe?: FfprobeData): Promise<boolean> {
113 const parsedAudio = await getAudioStream(path, probe)
114
115 if (!parsedAudio.audioStream) return true
116
117 if (parsedAudio.audioStream['codec_name'] !== 'aac') return false
118
119 const audioBitrate = parsedAudio.bitrate
120 if (!audioBitrate) return false
121
122 const maxAudioBitrate = getMaxAudioBitrate('aac', audioBitrate)
123 if (maxAudioBitrate !== -1 && audioBitrate > maxAudioBitrate) return false
124
125 const channelLayout = parsedAudio.audioStream['channel_layout']
126 // Causes playback issues with Chrome
127 if (!channelLayout || channelLayout === 'unknown' || channelLayout === 'quad') return false
128
129 return true
130}
131
132export async function canDoQuickVideoTranscode (path: string, probe?: FfprobeData): Promise<boolean> {
133 const videoStream = await getVideoStream(path, probe)
134 const fps = await getVideoStreamFPS(path, probe)
135 const bitRate = await getVideoStreamBitrate(path, probe)
136 const resolutionData = await getVideoStreamDimensionsInfo(path, probe)
137
138 // If ffprobe did not manage to guess the bitrate
139 if (!bitRate) return false
140
141 // check video params
142 if (!videoStream) return false
143 if (videoStream['codec_name'] !== 'h264') return false
144 if (videoStream['pix_fmt'] !== 'yuv420p') return false
145 if (fps < 2 || fps > 65) return false
146 if (bitRate > getMaxTheoreticalBitrate({ ...resolutionData, fps })) return false
147
148 return true
149}
150
98// --------------------------------------------------------------------------- 151// ---------------------------------------------------------------------------
99 152
100function getTargetBitrate (options: { 153function getTargetBitrate (options: {
@@ -105,8 +158,8 @@ function getTargetBitrate (options: {
105}) { 158}) {
106 const { inputBitrate, resolution, ratio, fps } = options 159 const { inputBitrate, resolution, ratio, fps } = options
107 160
108 const capped = capBitrate(inputBitrate, getAverageBitrate({ resolution, fps, ratio })) 161 const capped = capBitrate(inputBitrate, getAverageTheoreticalBitrate({ resolution, fps, ratio }))
109 const limit = getMinLimitBitrate({ resolution, fps, ratio }) 162 const limit = getMinTheoreticalBitrate({ resolution, fps, ratio })
110 163
111 return Math.max(limit, capped) 164 return Math.max(limit, capped)
112} 165}