From e7d8e2b245491c0a8e008fb570037506d729ff04 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 5 May 2023 10:53:04 +0200 Subject: Fix audio transcoding copy --- .../ffmpeg/ffmpeg-default-transcoding-profile.ts | 61 ++++++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) (limited to 'shared/ffmpeg') 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 @@ -import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils' -import { buildStreamSuffix, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '@shared/ffmpeg' +import { FfprobeData } from 'fluent-ffmpeg' +import { getAverageTheoreticalBitrate, getMaxTheoreticalBitrate, getMinTheoreticalBitrate } from '@shared/core-utils' +import { + buildStreamSuffix, + ffprobePromise, + getAudioStream, + getMaxAudioBitrate, + getVideoStream, + getVideoStreamBitrate, + getVideoStreamDimensionsInfo, + getVideoStreamFPS +} from '@shared/ffmpeg' import { EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '@shared/models' const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => { @@ -34,6 +44,10 @@ const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOp const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum, canCopyAudio }) => { const probe = await ffprobePromise(input) + if (canCopyAudio && await canDoQuickAudioTranscode(input, probe)) { + return { copy: true, outputOptions: [ ] } + } + const parsedAudio = await getAudioStream(input, probe) // We try to reduce the ceiling bitrate by making rough matches of bitrates @@ -95,6 +109,45 @@ export function getDefaultEncodersToTry () { } } +export async function canDoQuickAudioTranscode (path: string, probe?: FfprobeData): Promise { + const parsedAudio = await getAudioStream(path, probe) + + if (!parsedAudio.audioStream) return true + + if (parsedAudio.audioStream['codec_name'] !== 'aac') return false + + const audioBitrate = parsedAudio.bitrate + if (!audioBitrate) return false + + const maxAudioBitrate = getMaxAudioBitrate('aac', audioBitrate) + if (maxAudioBitrate !== -1 && audioBitrate > maxAudioBitrate) return false + + const channelLayout = parsedAudio.audioStream['channel_layout'] + // Causes playback issues with Chrome + if (!channelLayout || channelLayout === 'unknown' || channelLayout === 'quad') return false + + return true +} + +export async function canDoQuickVideoTranscode (path: string, probe?: FfprobeData): Promise { + const videoStream = await getVideoStream(path, probe) + const fps = await getVideoStreamFPS(path, probe) + const bitRate = await getVideoStreamBitrate(path, probe) + const resolutionData = await getVideoStreamDimensionsInfo(path, probe) + + // If ffprobe did not manage to guess the bitrate + if (!bitRate) return false + + // check video params + if (!videoStream) return false + if (videoStream['codec_name'] !== 'h264') return false + if (videoStream['pix_fmt'] !== 'yuv420p') return false + if (fps < 2 || fps > 65) return false + if (bitRate > getMaxTheoreticalBitrate({ ...resolutionData, fps })) return false + + return true +} + // --------------------------------------------------------------------------- function getTargetBitrate (options: { @@ -105,8 +158,8 @@ function getTargetBitrate (options: { }) { const { inputBitrate, resolution, ratio, fps } = options - const capped = capBitrate(inputBitrate, getAverageBitrate({ resolution, fps, ratio })) - const limit = getMinLimitBitrate({ resolution, fps, ratio }) + const capped = capBitrate(inputBitrate, getAverageTheoreticalBitrate({ resolution, fps, ratio })) + const limit = getMinTheoreticalBitrate({ resolution, fps, ratio }) return Math.max(limit, capped) } -- cgit v1.2.3