const { spawnSync } = require("child_process"); const fs = require("fs"); const path = require("path"); const os = require("os"); const FFMPEG_REPO = "https://git.ffmpeg.org/ffmpeg.git"; const FFMPEG_TAG = "release/7.1" const FFMPEG_SOURCE_DIR = path.join(__dirname, "_source/FFmpeg"); const FFMPEG_INSTALL_DIR = path.join(__dirname, "FFmpeg"); const isWindows = os.platform() == "win32"; function checkEnv() { if (!process.env.MSYSTEM_PREFIX) throw new Error("Please use msys2 environment to run this script"); const bash = process.env.SHELL; if (!bash || !bash.endsWith("bash.exe")) throw new Error("bash.exe is not found in environments"); } function download() { console.log("Downloading ffmpeg source..."); if (0 != spawnSync("git", [ "clone", FFMPEG_REPO, "-b", FFMPEG_TAG, FFMPEG_SOURCE_DIR ], { stdio: "inherit" }).status) throw new Error("Failed to download ffmpeg"); } function build() { //configure if (!fs.existsSync(path.join(FFMPEG_SOURCE_DIR, "ffbuild/config.mak"))) { console.log("Configuring ffmpeg..."); const args = [ `--prefix=${FFMPEG_INSTALL_DIR}`, "--enable-static", "--enable-small", "--disable-programs", "--disable-x86asm", ...isWindows ? ["--toolchain=msvc"] : [], ]; const configureFile = path.join(FFMPEG_SOURCE_DIR, "configure"); if (isWindows) args.unshift(configureFile); if (0 != spawnSync(isWindows ? process.env.SHELL : configureFile, args, { stdio: "inherit", cwd: FFMPEG_SOURCE_DIR }).status) throw new Error("Failed to configure ffmpeg"); } //make if (0 != spawnSync("make", [ "-j", os.cpus().length.toString(), ], { stdio: "inherit" }).status) throw new Error("Failed to build ffmpeg"); //install if (0 != spawnSync("make", [ "install", ], { stdio: "inherit", cwd: FFMPEG_SOURCE_DIR }).status) throw new Error("Failed to install ffmpeg"); } function resolve() { console.log("Resolving ffmpeg ..."); const libs = []; for (const file of fs.readdirSync(path.join(FFMPEG_INSTALL_DIR, "lib"))) { if (path.extname(file) == ".a") { const libName = file.replace(/\.a$/, "").replace(/^lib/, ""); if (isWindows) fs.renameSync(path.join(FFMPEG_INSTALL_DIR, "lib", file), path.join(FFMPEG_INSTALL_DIR, "lib", libName + ".lib")); libs.push(libName); } } fs.writeFileSync(path.join(FFMPEG_INSTALL_DIR, "config.cmake"), [ "set(FFMPEG_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/include)", "set(FFMPEG_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib)", `set(FFMPEG_LIBS ${libs.join(" ")})`, "", ].join("\n")); } async function main() { fs.mkdirSync(path.dirname(FFMPEG_SOURCE_DIR), { recursive: true }); fs.mkdirSync(path.dirname(FFMPEG_INSTALL_DIR), { recursive: true }); if (isWindows) checkEnv(); if (!fs.existsSync(path.join(FFMPEG_SOURCE_DIR, "configure"))) download(); if (!fs.existsSync(path.join(FFMPEG_INSTALL_DIR, "config.cmake"))) { build(); resolve(); } console.log(`FFmpeg build done !`); } main().catch(err => console.error(err.message));