fix: ffmpeg-Binary im Container fehlte (ENOENT bei jedem Video-Upload)
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 3m50s
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 3m50s
Live-Log zeigte: spawn .../ffmpeg-static/ffmpeg ENOENT bei jedem Transcode-Versuch, unabhaengig vom Videoformat (.mov war nur zufaellig der zuletzt getestete Fall). Die ffmpeg-static-Binary aus der migrator-Docker-Stage kam nicht zuverlaessig im finalen Image an. Root-Fix: ffmpeg jetzt per "apk add ffmpeg" als System-Paket in der runner-Stage installiert - liegt fest unter /usr/bin auf PATH, unabhaengig von jeder Node/pnpm-Kopiermechanik. lib/video-transcode.ts versucht zuerst "ffmpeg" ueber PATH und faellt nur bei ENOENT (kein System-ffmpeg vorhanden, typischerweise lokale Windows-/Mac-Entwicklung) auf die per npm mitgelieferte ffmpeg-static-Binary zurueck, damit "npm run dev" weiterhin ohne manuelle Einrichtung funktioniert. Beide Pfade lokal gegen ein synthetisches Testvideo verifiziert. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
a366ffb544
commit
902f818c6e
2 files changed
+51
-43
No files matched your search
+41
-28
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
|
||||
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import ffmpegPath from "ffmpeg-static";
|
||||
import ffmpegStaticPath from "ffmpeg-static";
|
||||
|
||||
/**
|
||||
* Harte Obergrenze fuer einen einzelnen ffmpeg-Lauf: verhindert, dass ein
|
||||
@@ -40,39 +40,52 @@ const TRANSCODE_TIMEOUT_MS = 5 * 60 * 1000;
|
||||
* Magic-Bytes am Dateianfang).
|
||||
*/
|
||||
export async function transcodeVideoForWeb(buffer: Buffer): Promise<Buffer> {
|
||||
if (!ffmpegPath) {
|
||||
throw new Error("ffmpeg-Binary (ffmpeg-static) nicht gefunden.");
|
||||
}
|
||||
|
||||
const dir = await mkdtemp(path.join(tmpdir(), "wabenhain-video-"));
|
||||
const inputPath = path.join(dir, "input");
|
||||
const outputPath = path.join(dir, "output.mp4");
|
||||
const args = [
|
||||
"-y",
|
||||
"-i",
|
||||
inputPath,
|
||||
"-an",
|
||||
"-vf",
|
||||
"scale='min(1920,iw)':-2",
|
||||
"-c:v",
|
||||
"libx264",
|
||||
"-preset",
|
||||
"medium",
|
||||
"-crf",
|
||||
"26",
|
||||
"-maxrate",
|
||||
"3M",
|
||||
"-bufsize",
|
||||
"6M",
|
||||
"-pix_fmt",
|
||||
"yuv420p",
|
||||
"-movflags",
|
||||
"+faststart",
|
||||
outputPath,
|
||||
];
|
||||
|
||||
try {
|
||||
await writeFile(inputPath, buffer);
|
||||
await runFfmpeg(ffmpegPath, [
|
||||
"-y",
|
||||
"-i",
|
||||
inputPath,
|
||||
"-an",
|
||||
"-vf",
|
||||
"scale='min(1920,iw)':-2",
|
||||
"-c:v",
|
||||
"libx264",
|
||||
"-preset",
|
||||
"medium",
|
||||
"-crf",
|
||||
"26",
|
||||
"-maxrate",
|
||||
"3M",
|
||||
"-bufsize",
|
||||
"6M",
|
||||
"-pix_fmt",
|
||||
"yuv420p",
|
||||
"-movflags",
|
||||
"+faststart",
|
||||
outputPath,
|
||||
]);
|
||||
try {
|
||||
// Bevorzugt "ffmpeg" ueber PATH — im Produktions-Image per "apk add
|
||||
// ffmpeg" installiert (siehe Dockerfile "runner"-Stage), fest unter
|
||||
// /usr/bin und unabhaengig von jeder Node/pnpm-Verzeichnisstruktur.
|
||||
await runFfmpeg("ffmpeg", args);
|
||||
} catch (error: unknown) {
|
||||
// ENOENT = Binary ueber PATH nicht gefunden (typischerweise ein
|
||||
// lokaler Windows-/Mac-Rechner ohne System-ffmpeg) — dann auf die per
|
||||
// npm mitgelieferte ffmpeg-static-Binary ausweichen, damit "npm run
|
||||
// dev" ohne manuelle Einrichtung funktioniert. Jeder andere Fehler
|
||||
// (z.B. eine tatsaechlich nicht dekodierbare Datei) soll dagegen
|
||||
// unveraendert durchschlagen, nicht stillschweigend erneut versucht
|
||||
// werden.
|
||||
const isMissingBinary = error instanceof Error && "code" in error && error.code === "ENOENT";
|
||||
if (!isMissingBinary || !ffmpegStaticPath) throw error;
|
||||
await runFfmpeg(ffmpegStaticPath, args);
|
||||
}
|
||||
return await readFile(outputPath);
|
||||
} finally {
|
||||
await rm(dir, { recursive: true, force: true });
|
||||
|
||||
Reference in new issue
Block a user