import { FfprobeData } from 'fluent-ffmpeg'
import { getMaxBitrate } from '@shared/core-utils'
import {
+ buildFileMetadata,
ffprobePromise,
getAudioStream,
- getVideoStreamDuration,
getMaxAudioBitrate,
- buildFileMetadata,
- getVideoStreamBitrate,
- getVideoStreamFPS,
getVideoStream,
+ getVideoStreamBitrate,
getVideoStreamDimensionsInfo,
+ getVideoStreamDuration,
+ getVideoStreamFPS,
hasAudioStream
} from '@shared/extra-utils/ffprobe'
import { VideoResolution, VideoTranscodingFPS } from '@shared/models'
}
if (videoCodec === 'av01') {
- const level = videoStream.level
+ let level = videoStream.level.toString()
+ if (level.length === 1) level = `0${level}`
// Guess the tier indicator and bit depth
return `${videoCodec}.${baseProfile}.${level}M.08`
}
- // Default, h264 codec
let level = videoStream.level.toString(16)
if (level.length === 1) level = `0${level}`
+ // Default, h264 codec
return `${videoCodec}.${baseProfile}${level}`
}
if (audioCodecName === 'opus') return 'opus'
if (audioCodecName === 'vorbis') return 'vorbis'
if (audioCodecName === 'aac') return 'mp4a.40.2'
+ if (audioCodecName === 'mp3') return 'mp4a.40.34'
logger.warn('Cannot get audio codec of %s.', path, { audioStream })
// Resolutions
// ---------------------------------------------------------------------------
-function computeLowerResolutionsToTranscode (videoFileResolution: number, type: 'vod' | 'live') {
+function computeResolutionsToTranscode (options: {
+ input: number
+ type: 'vod' | 'live'
+ includeInput: boolean
+ strictLower: boolean
+ hasAudio: boolean
+}) {
+ const { input, type, includeInput, strictLower, hasAudio } = options
+
const configResolutions = type === 'vod'
? CONFIG.TRANSCODING.RESOLUTIONS
: CONFIG.LIVE.TRANSCODING.RESOLUTIONS
- const resolutionsEnabled: number[] = []
+ const resolutionsEnabled = new Set<number>()
// Put in the order we want to proceed jobs
- const resolutions: VideoResolution[] = [
+ const availableResolutions: VideoResolution[] = [
VideoResolution.H_NOVIDEO,
VideoResolution.H_480P,
VideoResolution.H_360P,
VideoResolution.H_4K
]
- for (const resolution of resolutions) {
- if (configResolutions[resolution + 'p'] === true && videoFileResolution > resolution) {
- resolutionsEnabled.push(resolution)
- }
+ for (const resolution of availableResolutions) {
+ // Resolution not enabled
+ if (configResolutions[resolution + 'p'] !== true) continue
+ // Too big resolution for input file
+ if (input < resolution) continue
+ // We only want lower resolutions than input file
+ if (strictLower && input === resolution) continue
+ // Audio resolutio but no audio in the video
+ if (resolution === VideoResolution.H_NOVIDEO && !hasAudio) continue
+
+ resolutionsEnabled.add(resolution)
+ }
+
+ if (includeInput) {
+ resolutionsEnabled.add(input)
}
- return resolutionsEnabled
+ return Array.from(resolutionsEnabled)
}
// ---------------------------------------------------------------------------
const channelLayout = parsedAudio.audioStream['channel_layout']
// Causes playback issues with Chrome
- if (!channelLayout || channelLayout === 'unknown') return false
+ if (!channelLayout || channelLayout === 'unknown' || channelLayout === 'quad') return false
return true
}
computeFPS,
getClosestFramerateStandard,
- computeLowerResolutionsToTranscode,
+ computeResolutionsToTranscode,
canDoQuickTranscode,
canDoQuickVideoTranscode,