import fs from 'fs'; import { NextResponse } from 'next/server'; import { transcodeOrchestrator } from '@/lib/transcode/orchestrator'; import { segmentPath } from '@/lib/transcode/playlist'; export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; async function waitForSegment(filePath: string, timeoutMs = 5000): Promise { const startedAt = Date.now(); while (Date.now() - startedAt < timeoutMs) { if (fs.existsSync(filePath)) { const stat = fs.statSync(filePath); if (stat.size > 0) return true; } await new Promise(resolve => setTimeout(resolve, 150)); } return false; } export async function GET(_request: Request, { params }: { params: Promise<{ jobId: string; name: string }> }) { const { jobId, name } = await params; const job = transcodeOrchestrator.get(jobId); if (!job) { return NextResponse.json({ error: 'Transcode job not found' }, { status: 404 }); } const resolvedPath = segmentPath(job.outDir, name); if (!resolvedPath || !(await waitForSegment(resolvedPath))) { return new Response(null, { status: 404 }); } const stat = fs.statSync(resolvedPath); const stream = fs.createReadStream(resolvedPath); return new Response(stream as any, { status: 200, headers: { 'Content-Type': 'video/mp2t', 'Content-Length': stat.size.toString(), 'Cache-Control': 'private, max-age=3600', 'ETag': `"${jobId}-${name}-${stat.size}-${stat.mtimeMs}"`, 'Access-Control-Allow-Origin': '*', }, }); }