1 import { FfprobeData } from 'fluent-ffmpeg'
2 import { CONFIG } from '@server/initializers/config'
3 import { VIDEO_TRANSCODING_FPS } from '@server/initializers/constants'
4 import { getMaxBitrate } from '@shared/core-utils'
10 getVideoStreamBitrate,
11 getVideoStreamDimensionsInfo,
13 } from '@shared/ffmpeg'
15 export async function canDoQuickTranscode (path: string, existingProbe?: FfprobeData): Promise<boolean> {
16 if (CONFIG.TRANSCODING.PROFILE !== 'default') return false
18 const probe = existingProbe || await ffprobePromise(path)
20 return await canDoQuickVideoTranscode(path, probe) &&
21 await canDoQuickAudioTranscode(path, probe)
24 export async function canDoQuickAudioTranscode (path: string, probe?: FfprobeData): Promise<boolean> {
25 const parsedAudio = await getAudioStream(path, probe)
27 if (!parsedAudio.audioStream) return true
29 if (parsedAudio.audioStream['codec_name'] !== 'aac') return false
31 const audioBitrate = parsedAudio.bitrate
32 if (!audioBitrate) return false
34 const maxAudioBitrate = getMaxAudioBitrate('aac', audioBitrate)
35 if (maxAudioBitrate !== -1 && audioBitrate > maxAudioBitrate) return false
37 const channelLayout = parsedAudio.audioStream['channel_layout']
38 // Causes playback issues with Chrome
39 if (!channelLayout || channelLayout === 'unknown' || channelLayout === 'quad') return false
44 export async function canDoQuickVideoTranscode (path: string, probe?: FfprobeData): Promise<boolean> {
45 const videoStream = await getVideoStream(path, probe)
46 const fps = await getVideoStreamFPS(path, probe)
47 const bitRate = await getVideoStreamBitrate(path, probe)
48 const resolutionData = await getVideoStreamDimensionsInfo(path, probe)
50 // If ffprobe did not manage to guess the bitrate
51 if (!bitRate) return false
54 if (!videoStream) return false
55 if (videoStream['codec_name'] !== 'h264') return false
56 if (videoStream['pix_fmt'] !== 'yuv420p') return false
57 if (fps < VIDEO_TRANSCODING_FPS.MIN || fps > VIDEO_TRANSCODING_FPS.MAX) return false
58 if (bitRate > getMaxBitrate({ ...resolutionData, fps })) return false