import { exec } from 'child_process'
import ffmpeg from 'fluent-ffmpeg'
+/**
+ * @returns FFmpeg version string. Usually a semver string, but may vary when depending on installation method.
+ */
export function getFFmpegVersion () {
return new Promise<string>((res, rej) => {
(ffmpeg() as any)._getFfmpegPath((err, ffmpegPath) => {
return exec(`${ffmpegPath} -version`, (err, stdout) => {
if (err) return rej(err)
- const parsed = stdout.match(/ffmpeg version .?(\d+\.\d+(\.\d+)?)/)
- if (!parsed?.[1]) return rej(new Error(`Could not find ffmpeg version in ${stdout}`))
+ const parsed = stdout.match(/(?<=ffmpeg version )[a-zA-Z\d.-]+/)
+ if (!parsed) return rej(new Error(`Could not find ffmpeg version in ${stdout}`))
- // Fix ffmpeg version that does not include patch version (4.4 for example)
- let version = parsed[1]
- if (version.match(/^\d+\.\d+$/)) {
- version += '.0'
- }
+ res(parsed[0])
})
})
})
import validator from 'validator'
import { getAverageTheoreticalBitrate, getMaxTheoreticalBitrate } from '@peertube/peertube-core-utils'
import { VideoResolution } from '@peertube/peertube-models'
-import { objectConverter, parseBytes, parseDurationToMs } from '@peertube/peertube-server/server/helpers/core-utils.js'
+import { objectConverter, parseBytes, parseDurationToMs, parseSemVersion } from '@peertube/peertube-server/server/helpers/core-utils.js'
describe('Parse Bytes', function () {
}
})
})
+
+describe('Parse semantic version string', function () {
+
+ it('Should parse Node.js version string', function () {
+ const actual = parseSemVersion('v18.16.0')
+
+ expect(actual.major).to.equal(18)
+ expect(actual.minor).to.equal(16)
+ expect(actual.patch).to.equal(0)
+ })
+
+ it('Should parse FFmpeg version string from Debian 12 repo', function () {
+ const actual = parseSemVersion('5.1.3-1')
+
+ expect(actual.major).to.equal(5)
+ expect(actual.minor).to.equal(1)
+ expect(actual.patch).to.equal(3)
+ })
+
+ it('Should parse FFmpeg version string from Arch repo', function () {
+ const actual = parseSemVersion('n6.0')
+
+ expect(actual.major).to.equal(6)
+ expect(actual.minor).to.equal(0)
+ expect(actual.patch).to.equal(0)
+ })
+
+ it('Should parse FFmpeg version from GitHub release', function () {
+ const actual = parseSemVersion('5.1.3')
+
+ expect(actual.major).to.equal(5)
+ expect(actual.minor).to.equal(1)
+ expect(actual.patch).to.equal(3)
+ })
+
+ it('Should parse FFmpeg version from GitHub dev release', function () {
+ const actual = parseSemVersion('5.1.git')
+
+ expect(actual.major).to.equal(5)
+ expect(actual.minor).to.equal(1)
+ expect(actual.patch).to.equal(0)
+ })
+
+ it('Should parse FFmpeg version string with missing patch segment', function () {
+ const actual = parseSemVersion('4.4')
+
+ expect(actual.major).to.equal(4)
+ expect(actual.minor).to.equal(4)
+ expect(actual.patch).to.equal(0)
+ })
+})
// ---------------------------------------------------------------------------
type SemVersion = { major: number, minor: number, patch: number }
+
+/**
+ * Parses a semantic version string into its separate components.
+ * Fairly lax, and allows for missing or additional segments in the string.
+ *
+ * @param s String to parse semantic version from.
+ * @returns Major, minor, and patch version, or null if string does not follow semantic version conventions.
+ */
function parseSemVersion (s: string) {
- const parsed = s.match(/^v?(\d+)\.(\d+)\.(\d+)$/i)
+ const parsed = s.match(/v?(\d+)\.(\d+)(?:\.(\d+))?/i)
+
+ if (!parsed) return null
return {
major: parseInt(parsed[1]),
minor: parseInt(parsed[2]),
- patch: parseInt(parsed[3])
+ patch: parsed[3] ? parseInt(parsed[3]) : 0
} as SemVersion
}
async function checkFFmpegVersion () {
const version = await getFFmpegVersion()
- const { major, minor, patch } = parseSemVersion(version)
+ const semvar = parseSemVersion(version)
+
+ if (!semvar) {
+ logger.warn('Your ffmpeg version (%s) does not use semvar. Unable to determine version compatibility.', version)
+ return
+ }
+
+ const { major, minor, patch } = semvar
if (major < 4 || (major === 4 && minor < 1)) {
logger.warn('Your ffmpeg version (%s) is outdated. PeerTube supports ffmpeg >= 4.1. Please upgrade ffmpeg.', version)