-import * as ffmpeg from 'fluent-ffmpeg'
+import { ffprobe, FfprobeData } from 'fluent-ffmpeg'
import { getMaxBitrate } from '@shared/core-utils'
import { VideoFileMetadata, VideoResolution, VideoTranscodingFPS } from '../../shared/models/videos'
import { CONFIG } from '../initializers/config'
*/
function ffprobePromise (path: string) {
- return new Promise<ffmpeg.FfprobeData>((res, rej) => {
- ffmpeg.ffprobe(path, (err, data) => {
+ return new Promise<FfprobeData>((res, rej) => {
+ ffprobe(path, (err, data) => {
if (err) return rej(err)
return res(data)
})
}
-async function getAudioStream (videoPath: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getAudioStream (videoPath: string, existingProbe?: FfprobeData) {
// without position, ffprobe considers the last input only
// we make it consider the first input only
// if you pass a file path to pos, then ffprobe acts on that file directly
}
}
-async function getVideoStreamSize (path: string, existingProbe?: ffmpeg.FfprobeData): Promise<{ width: number, height: number }> {
+async function getVideoStreamSize (path: string, existingProbe?: FfprobeData): Promise<{ width: number, height: number }> {
const videoStream = await getVideoStreamFromFile(path, existingProbe)
return videoStream === null
return `${videoCodec}.${baseProfile}${level}`
}
-async function getAudioStreamCodec (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getAudioStreamCodec (path: string, existingProbe?: FfprobeData) {
const { audioStream } = await getAudioStream(path, existingProbe)
if (!audioStream) return ''
return 'mp4a.40.2' // Fallback
}
-async function getVideoFileResolution (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getVideoFileResolution (path: string, existingProbe?: FfprobeData) {
const size = await getVideoStreamSize(path, existingProbe)
return {
}
}
-async function getVideoFileFPS (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getVideoFileFPS (path: string, existingProbe?: FfprobeData) {
const videoStream = await getVideoStreamFromFile(path, existingProbe)
if (videoStream === null) return 0
return 0
}
-async function getMetadataFromFile (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getMetadataFromFile (path: string, existingProbe?: FfprobeData) {
const metadata = existingProbe || await ffprobePromise(path)
return new VideoFileMetadata(metadata)
}
-async function getVideoFileBitrate (path: string, existingProbe?: ffmpeg.FfprobeData): Promise<number> {
+async function getVideoFileBitrate (path: string, existingProbe?: FfprobeData): Promise<number> {
const metadata = await getMetadataFromFile(path, existingProbe)
let bitrate = metadata.format.bit_rate as number
return undefined
}
-async function getDurationFromVideoFile (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getDurationFromVideoFile (path: string, existingProbe?: FfprobeData) {
const metadata = await getMetadataFromFile(path, existingProbe)
return Math.round(metadata.format.duration)
}
-async function getVideoStreamFromFile (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getVideoStreamFromFile (path: string, existingProbe?: FfprobeData) {
const metadata = await getMetadataFromFile(path, existingProbe)
return metadata.streams.find(s => s.codec_type === 'video') || null
}
-function computeResolutionsToTranscode (videoFileResolution: number, type: 'vod' | 'live') {
+function computeLowerResolutionsToTranscode (videoFileResolution: number, type: 'vod' | 'live') {
const configResolutions = type === 'vod'
? CONFIG.TRANSCODING.RESOLUTIONS
: CONFIG.LIVE.TRANSCODING.RESOLUTIONS
const resolutionsEnabled: number[] = []
// Put in the order we want to proceed jobs
- const resolutions = [
+ const resolutions: VideoResolution[] = [
VideoResolution.H_NOVIDEO,
VideoResolution.H_480P,
VideoResolution.H_360P,
VideoResolution.H_720P,
VideoResolution.H_240P,
+ VideoResolution.H_144P,
VideoResolution.H_1080P,
VideoResolution.H_1440P,
VideoResolution.H_4K
await canDoQuickAudioTranscode(path, probe)
}
-async function canDoQuickVideoTranscode (path: string, probe?: ffmpeg.FfprobeData): Promise<boolean> {
+async function canDoQuickVideoTranscode (path: string, probe?: FfprobeData): Promise<boolean> {
const videoStream = await getVideoStreamFromFile(path, probe)
const fps = await getVideoFileFPS(path, probe)
const bitRate = await getVideoFileBitrate(path, probe)
return true
}
-async function canDoQuickAudioTranscode (path: string, probe?: ffmpeg.FfprobeData): Promise<boolean> {
+async function canDoQuickAudioTranscode (path: string, probe?: FfprobeData): Promise<boolean> {
const parsedAudio = await getAudioStream(path, probe)
if (!parsedAudio.audioStream) return true
// Hard FPS limits
if (fps > VIDEO_TRANSCODING_FPS.MAX) fps = getClosestFramerateStandard(fps, 'HD_STANDARD')
- else if (fps < VIDEO_TRANSCODING_FPS.MIN) fps = VIDEO_TRANSCODING_FPS.MIN
+
+ if (fps < VIDEO_TRANSCODING_FPS.MIN) {
+ throw new Error(`Cannot compute FPS because ${fps} is lower than our minimum value ${VIDEO_TRANSCODING_FPS.MIN}`)
+ }
return fps
}
getVideoFileFPS,
ffprobePromise,
getClosestFramerateStandard,
- computeResolutionsToTranscode,
+ computeLowerResolutionsToTranscode,
getVideoFileBitrate,
canDoQuickTranscode,
canDoQuickVideoTranscode,