Remove the ffmpeg-static npm runtime dependency and download checksum-verified pinned FFmpeg release assets directly

Hop-State: A_06FNNTFDVDZGB2NFDAARAT0
Hop-Proposal: R_06FNNTEE6NDAD98WA9S7VA0
Hop-Task: T_06FNNS0FK2T1TH9QVHG8MSR
Hop-Attempt: AT_06FNNS0FK2MH777VNTJ1530
This commit is contained in:
2026-07-13 02:58:28 -07:00
committed by Hop
parent 73c4eb1857
commit f34266b704
4 changed files with 63 additions and 254 deletions
+59 -23
View File
@@ -4,10 +4,11 @@ import { chmod, copyFile, mkdir, mkdtemp, readFile, rm, writeFile } from "node:f
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import ffmpegPath from "ffmpeg-static";
const VERSION = "0.61.2";
const RELEASE_API = `https://api.github.com/repos/navidrome/navidrome/releases/tags/v${VERSION}`;
const FFMPEG_RELEASE = "b6.1.1";
const FFMPEG_RELEASE_API = `https://api.github.com/repos/eugeneware/ffmpeg-static/releases/tags/${FFMPEG_RELEASE}`;
const targetTriple = execFileSync("rustc", ["--print", "host-tuple"], { encoding: "utf8" }).trim();
const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
@@ -19,9 +20,18 @@ const archives = {
"x86_64-pc-windows-msvc": `navidrome_${VERSION}_windows_amd64.zip`,
};
const ffmpegPlatforms = {
"aarch64-apple-darwin": "darwin-arm64",
"x86_64-apple-darwin": "darwin-x64",
"aarch64-unknown-linux-gnu": "linux-arm64",
"x86_64-unknown-linux-gnu": "linux-x64",
"x86_64-pc-windows-msvc": "win32-x64",
};
const archiveName = archives[targetTriple];
if (!archiveName) {
throw new Error(`Navidrome ${VERSION} is not configured for Rust target ${targetTriple}.`);
const ffmpegPlatform = ffmpegPlatforms[targetTriple];
if (!archiveName || !ffmpegPlatform) {
throw new Error(`Resonant's media sidecars are not configured for Rust target ${targetTriple}.`);
}
const extension = targetTriple.includes("windows") ? ".exe" : "";
@@ -38,6 +48,8 @@ await mkdir(resourceDirectory, { recursive: true });
let binaryReady = false;
let licenseReady = false;
let ffmpegReady = false;
let ffmpegLicenseReady = false;
let ffmpegReadmeReady = false;
try {
await readFile(outputPath);
binaryReady = true;
@@ -54,18 +66,52 @@ try {
await readFile(ffmpegOutputPath);
ffmpegReady = true;
} catch {
// Copy the pinned npm-provided binary below when missing.
// Download the pinned release asset below when missing.
}
if (!ffmpegPath) throw new Error(`ffmpeg-static does not provide a binary for ${process.platform}-${process.arch}.`);
if (!ffmpegReady) {
await copyFile(ffmpegPath, ffmpegOutputPath);
if (!extension) await chmod(ffmpegOutputPath, 0o755);
try {
await readFile(ffmpegLicensePath);
ffmpegLicenseReady = true;
} catch {
// Download the matching binary license below when missing.
}
try {
await readFile(ffmpegReadmePath);
ffmpegReadmeReady = true;
} catch {
// Download the matching binary build information below when missing.
}
await copyFile(join(dirname(ffmpegPath), "ffmpeg.LICENSE"), ffmpegLicensePath);
await copyFile(join(dirname(ffmpegPath), "ffmpeg.README"), ffmpegReadmePath);
const headers = { Accept: "application/vnd.github+json", "User-Agent": "Resonant-sidecar-preparer" };
const verifiedReleaseAsset = async (release, assetName) => {
const asset = release.assets.find((candidate) => candidate.name === assetName);
if (!asset) throw new Error(`The pinned release does not contain ${assetName}.`);
const response = await fetch(asset.browser_download_url, { headers });
if (!response.ok) throw new Error(`Could not download ${assetName} (${response.status}).`);
const bytes = Buffer.from(await response.arrayBuffer());
const actualDigest = createHash("sha256").update(bytes).digest("hex");
const expectedDigest = asset.digest?.replace(/^sha256:/, "");
if (!expectedDigest || actualDigest !== expectedDigest) {
throw new Error(`Checksum verification failed for ${assetName}.`);
}
return bytes;
};
if (!ffmpegReady || !ffmpegLicenseReady || !ffmpegReadmeReady) {
const releaseResponse = await fetch(FFMPEG_RELEASE_API, { headers });
if (!releaseResponse.ok) throw new Error(`Could not read FFmpeg ${FFMPEG_RELEASE} release metadata (${releaseResponse.status}).`);
const release = await releaseResponse.json();
if (!ffmpegReady) {
await writeFile(ffmpegOutputPath, await verifiedReleaseAsset(release, `ffmpeg-${ffmpegPlatform}`));
if (!extension) await chmod(ffmpegOutputPath, 0o755);
}
if (!ffmpegLicenseReady) {
await writeFile(ffmpegLicensePath, await verifiedReleaseAsset(release, `${ffmpegPlatform}.LICENSE`));
}
if (!ffmpegReadmeReady) {
await writeFile(ffmpegReadmePath, await verifiedReleaseAsset(release, `${ffmpegPlatform}.README`));
}
}
if (!licenseReady) {
const licenseResponse = await fetch(`https://raw.githubusercontent.com/navidrome/navidrome/v${VERSION}/LICENSE`, { headers });
if (!licenseResponse.ok) throw new Error(`Could not download the Navidrome license (${licenseResponse.status}).`);
@@ -79,17 +125,7 @@ if (binaryReady) {
const releaseResponse = await fetch(RELEASE_API, { headers });
if (!releaseResponse.ok) throw new Error(`Could not read the Navidrome release metadata (${releaseResponse.status}).`);
const release = await releaseResponse.json();
const asset = release.assets.find((candidate) => candidate.name === archiveName);
if (!asset) throw new Error(`The official Navidrome release does not contain ${archiveName}.`);
const archiveResponse = await fetch(asset.browser_download_url, { headers });
if (!archiveResponse.ok) throw new Error(`Could not download ${archiveName} (${archiveResponse.status}).`);
const archive = Buffer.from(await archiveResponse.arrayBuffer());
const actualDigest = createHash("sha256").update(archive).digest("hex");
const expectedDigest = asset.digest?.replace(/^sha256:/, "");
if (!expectedDigest || actualDigest !== expectedDigest) {
throw new Error(`Checksum verification failed for ${archiveName}.`);
}
const archive = await verifiedReleaseAsset(release, archiveName);
const workingDirectory = await mkdtemp(join(tmpdir(), "resonant-navidrome-"));
try {
@@ -103,4 +139,4 @@ try {
await rm(workingDirectory, { recursive: true, force: true });
}
process.stdout.write(`Downloaded and verified Navidrome ${VERSION}; FFmpeg is ready for ${targetTriple}.\n`);
process.stdout.write(`Downloaded and verified Navidrome ${VERSION}; FFmpeg ${FFMPEG_RELEASE} is ready for ${targetTriple}.\n`);