Initial commit

This commit is contained in:
twotalesanimation
2026-06-11 10:46:09 +02:00
commit 81ad7e4ea9
223 changed files with 39530 additions and 0 deletions
@@ -0,0 +1,72 @@
// app/api/transcoder/download/[videoId]/route.ts
// Streams the original MP4 directly to the remote transcoder worker.
// Never buffers the file in memory.
import { NextResponse } from "next/server";
import * as fssync from "fs";
import * as fs from "fs/promises";
import * as path from "path";
import { Readable } from "stream";
import { prisma } from "@/lib/prisma";
import { verifyTranscoderToken } from "@/lib/transcoder-auth";
// Allow up to 45 minutes for large file transfers.
export const maxDuration = 2700;
const UPLOADS_DIR = process.env.UPLOADS_DIR ?? "/uploads";
const ORIGINALS_DIR = path.join(UPLOADS_DIR, "videos");
// Narrow character set CUIDs are alphanumeric plus underscore/dash.
const SAFE_ID = /^[a-zA-Z0-9_-]{1,64}$/;
export async function GET(
request: Request,
context: { params: Promise<{ videoId: string }> }
) {
if (!verifyTranscoderToken(request)) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const { videoId } = await context.params;
if (!SAFE_ID.test(videoId)) {
return NextResponse.json({ error: "Invalid video ID" }, { status: 400 });
}
const video = await prisma.video.findUnique({ where: { id: videoId } });
if (!video) {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
// Only allow download while the job is actively claimed.
if (video.transcodingStatus !== "processing") {
return NextResponse.json(
{ error: "Video is not in processing state" },
{ status: 409 }
);
}
const filePath = path.join(ORIGINALS_DIR, `${videoId}.mp4`);
// Security: ensure the resolved path stays within ORIGINALS_DIR.
const resolved = path.resolve(filePath);
if (!resolved.startsWith(path.resolve(ORIGINALS_DIR))) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
try {
const stat = await fs.stat(resolved);
const nodeStream = fssync.createReadStream(resolved);
const webStream = Readable.toWeb(nodeStream) as ReadableStream;
return new Response(webStream, {
headers: {
"Content-Type": "video/mp4",
"Content-Length": stat.size.toString(),
"Content-Disposition": `attachment; filename="${videoId}.mp4"`,
},
});
} catch {
return NextResponse.json({ error: "File not found on disk" }, { status: 404 });
}
}