From ae71acca14e9420646ca7655e64eb9adc13e3006 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 11 Mar 2021 09:51:08 +0100 Subject: Check ffmepg version on startup --- server.ts | 5 ++++- server/helpers/core-utils.ts | 14 +++++++++++++- server/helpers/ffmpeg-utils.ts | 21 ++++++++++++++++++++- server/initializers/checker-after-init.ts | 27 +++++++++++++++++++-------- server/initializers/checker-before-init.ts | 5 ++--- 5 files changed, 58 insertions(+), 14 deletions(-) diff --git a/server.ts b/server.ts index 1cc29209e..a8bd25088 100644 --- a/server.ts +++ b/server.ts @@ -44,7 +44,7 @@ checkFFmpeg(CONFIG) checkNodeVersion() -import { checkConfig, checkActivityPubUrls } from './server/initializers/checker-after-init' +import { checkConfig, checkActivityPubUrls, checkFFmpegVersion } from './server/initializers/checker-after-init' const errorMessage = checkConfig() if (errorMessage !== null) { @@ -252,6 +252,9 @@ async function startApplication () { process.exit(-1) }) + checkFFmpegVersion() + .catch(err => logger.error('Cannot check ffmpeg version', { err })) + // Email initialization Emailer.Instance.init() diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index 7ba7d865a..ceb6a341d 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts @@ -251,6 +251,16 @@ function promisify2 (func: (arg1: T, arg2: U, cb: (err: any, result: A) } } +function parseSemVersion (s: string) { + const parsed = s.match(/^v?(\d+)\.(\d+)\.(\d+)$/i) + + return { + major: parseInt(parsed[1]), + minor: parseInt(parsed[2]), + patch: parseInt(parsed[3]) + } +} + const randomBytesPromise = promisify1(randomBytes) const createPrivateKey = promisify1(pem.createPrivateKey) const getPublicKey = promisify1(pem.getPublicKey) @@ -288,5 +298,7 @@ export { getPublicKey, execPromise2, execPromise, - pipelinePromise + pipelinePromise, + + parseSemVersion } diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index 620025966..69cd397b9 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts @@ -5,7 +5,7 @@ import { dirname, join } from 'path' import { FFMPEG_NICE, VIDEO_LIVE } from '@server/initializers/constants' import { AvailableEncoders, EncoderOptionsBuilder, EncoderProfile, VideoResolution } from '../../shared/models/videos' import { CONFIG } from '../initializers/config' -import { promisify0 } from './core-utils' +import { execPromise, promisify0 } from './core-utils' import { computeFPS, getAudioStream, getVideoFileFPS } from './ffprobe-utils' import { processImage } from './image-utils' import { logger } from './logger' @@ -649,6 +649,24 @@ function getFFmpeg (input: string, type: 'live' | 'vod') { return command } +function getFFmpegVersion () { + return new Promise((res, rej) => { + (ffmpeg() as any)._getFfmpegPath((err, ffmpegPath) => { + if (err) return rej(err) + if (!ffmpegPath) return rej(new Error('Could not find ffmpeg path')) + + return execPromise(`${ffmpegPath} -version`) + .then(stdout => { + const parsed = stdout.match(/ffmpeg version .(\d+\.\d+\.\d+)/) + if (!parsed || !parsed[1]) return rej(new Error(`Could not find ffmpeg version in ${stdout}`)) + + return res(parsed[1]) + }) + .catch(err => rej(err)) + }) + }) +} + async function runCommand (options: { command: ffmpeg.FfmpegCommand silent?: boolean // false @@ -695,6 +713,7 @@ export { TranscodeOptionsType, transcode, runCommand, + getFFmpegVersion, resetSupportedEncoders, diff --git a/server/initializers/checker-after-init.ts b/server/initializers/checker-after-init.ts index 2b00e2047..a93c8b7fd 100644 --- a/server/initializers/checker-after-init.ts +++ b/server/initializers/checker-after-init.ts @@ -1,16 +1,17 @@ import * as config from 'config' -import { isProdInstance, isTestInstance } from '../helpers/core-utils' -import { UserModel } from '../models/account/user' -import { getServerActor, ApplicationModel } from '../models/application/application' -import { OAuthClientModel } from '../models/oauth/oauth-client' +import { uniq } from 'lodash' import { URL } from 'url' -import { CONFIG, isEmailEnabled } from './config' -import { logger } from '../helpers/logger' +import { getFFmpegVersion } from '@server/helpers/ffmpeg-utils' +import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' import { RecentlyAddedStrategy } from '../../shared/models/redundancy' +import { isProdInstance, isTestInstance, parseSemVersion } from '../helpers/core-utils' import { isArray } from '../helpers/custom-validators/misc' -import { uniq } from 'lodash' +import { logger } from '../helpers/logger' +import { UserModel } from '../models/account/user' +import { ApplicationModel, getServerActor } from '../models/application/application' +import { OAuthClientModel } from '../models/oauth/oauth-client' +import { CONFIG, isEmailEnabled } from './config' import { WEBSERVER } from './constants' -import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' async function checkActivityPubUrls () { const actor = await getServerActor() @@ -176,11 +177,21 @@ async function applicationExist () { return totalApplication !== 0 } +async function checkFFmpegVersion () { + const version = await getFFmpegVersion() + const { major, minor } = parseSemVersion(version) + + if (major < 4 || (major === 4 && minor < 1)) { + logger.warn('Your ffmpeg version (%s) is outdated. PeerTube supports ffmpeg >= 4.1. Please upgrade.', version) + } +} + // --------------------------------------------------------------------------- export { checkConfig, clientsExist, + checkFFmpegVersion, usersExist, applicationExist, checkActivityPubUrls diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts index 565e0d1fa..65a019ca6 100644 --- a/server/initializers/checker-before-init.ts +++ b/server/initializers/checker-before-init.ts @@ -1,5 +1,5 @@ import * as config from 'config' -import { promisify0 } from '../helpers/core-utils' +import { parseSemVersion, promisify0 } from '../helpers/core-utils' import { logger } from '../helpers/logger' // ONLY USE CORE MODULES IN THIS FILE! @@ -102,8 +102,7 @@ async function checkFFmpeg (CONFIG: { TRANSCODING: { ENABLED: boolean } }) { function checkNodeVersion () { const v = process.version - const majorString = v.split('.')[0].replace('v', '') - const major = parseInt(majorString, 10) + const { major } = parseSemVersion(v) logger.debug('Checking NodeJS version %s.', v) -- cgit v1.2.3