From 3494c9a2b3e85349e61a2fa145b9faf341095f83 Mon Sep 17 00:00:00 2001 From: twotalesanimation <80506065+twotalesanimation@users.noreply.github.com> Date: Thu, 16 Jul 2026 23:26:12 +0200 Subject: [PATCH] MP4 on Hetz --- app/api/files/[...key]/route.ts | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/app/api/files/[...key]/route.ts b/app/api/files/[...key]/route.ts index 8f9e69d..a12b9a8 100644 --- a/app/api/files/[...key]/route.ts +++ b/app/api/files/[...key]/route.ts @@ -45,17 +45,31 @@ export async function GET( return new NextResponse("Forbidden", { status: 403 }); } - // ── Local disk first, Hetzner fallback ─────────────────────────────────── - // Serve from local disk if the file exists there (covers unmigrated files). - // If not found locally, redirect to Hetzner object storage. - // Note: "Hetzner first" was attempted but caused 400s from Hetzner on - // presigned URLs — likely a bucket policy/CORS issue to investigate - // separately before re-enabling that path. + // ── Storage routing ─────────────────────────────────────────────────────── + // Videos: check Hetzner first — bypasses ISP throttling for large streams. + // Fallback to local disk if the file hasn't been migrated yet. + // Images / other assets: local disk only — avoids presigned-URL 400 errors + // seen on Hetzner for non-video content. + const videoExts = new Set([".mp4", ".mov", ".avi", ".mxf", ".webm"]); + const isVideo = videoExts.has(path.extname(relativePath).toLowerCase()); + + if (isVideo) { + try { + if (await hetznerKeyExists(relativePath)) { + const hetznerUrl = await generateHetznerStreamUrl(relativePath, 3600); + return NextResponse.redirect(hetznerUrl, 302); + } + } catch { + // Hetzner unavailable — fall through to local disk + } + } + + // Local disk (all non-video files, and video files not yet on Hetzner) let stat: fs.Stats; try { stat = fs.statSync(filePath); } catch { - // Not on local disk — try Hetzner + // Not on local disk and not a video served above — try Hetzner as last resort try { const hetznerUrl = await generateHetznerStreamUrl(relativePath, 3600); return NextResponse.redirect(hetznerUrl, 302);