]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
fix: handle git installation of ffmpeg
authorSeth Falco <seth@falco.fun>
Wed, 2 Aug 2023 22:22:36 +0000 (23:22 +0100)
committerChocobozzz <chocobozzz@cpy.re>
Fri, 18 Aug 2023 08:17:16 +0000 (10:17 +0200)
packages/ffmpeg/src/ffmpeg-version.ts
packages/tests/src/server-helpers/core-utils.ts
server/server/helpers/core-utils.ts
server/server/initializers/checker-after-init.ts

index 41d9b2d89f4e39c796ccd24aed62c0f333704be9..f737bc2540dba3dbeb4b96f4796410008b824286 100644 (file)
@@ -1,6 +1,9 @@
 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) => {
@@ -10,14 +13,10 @@ export function getFFmpegVersion () {
       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])
       })
     })
   })
index 06c78591e7877ec0eae06a3caa584a8a4014de50..d61cae85529e4c224cf37e77e1aca5daabc3842b 100644 (file)
@@ -5,7 +5,7 @@ import snakeCase from 'lodash-es/snakeCase.js'
 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 () {
 
@@ -148,3 +148,54 @@ describe('Bitrate', 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)
+  })
+})
index 6dc09d317f6e6d59cb24f6b12a898af8d76903f3..9b40ca5be8082aba69375f25981cd24c65fdbe80 100644 (file)
@@ -183,13 +183,23 @@ function pageToStartAndCount (page: number, itemsPerPage: number) {
 // ---------------------------------------------------------------------------
 
 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
 }
 
index afcf6176b675f4efddd80bda79f11ce7c792dd37..5e7e513f1bebb92efcacd8b1e30a9756577ed2a8 100644 (file)
@@ -78,7 +78,14 @@ async function applicationExist () {
 
 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)