// ✅ 수정된 /api/video-preview/+server.ts (SvelteKit 2.x / Kit 1.x 호환) import { error } from '@sveltejs/kit'; import * as fs from 'fs'; import * as path from 'path'; import { Readable } from 'stream'; // process.mp4 파일이 있는 실제 경로로 수정하세요 const TEMP_BASE_DIR = 'tmp'; // 예시 경로 const videoPath = path.join(TEMP_BASE_DIR, 'process.mp4'); export const GET: import('@sveltejs/kit').RequestHandler = ({ request }) => { let stats: fs.Stats; try { stats = fs.statSync(videoPath); } catch (e) { throw error(404, 'Video file not found'); } const fileSize = stats.size; const range = request.headers.get('Range'); const responseHeaders = { 'Content-Type': 'video/mp4', 'Accept-Ranges': 'bytes' }; if (range) { // Range 요청 처리 (Firefox가 요구하는 부분) const parts = range.replace(/bytes=/, "").split("-"); const start = parseInt(parts[0], 10); const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1; if (start >= fileSize) { return new Response(null, { status: 416, // Range Not Satisfiable headers: { 'Content-Range': `bytes */${fileSize}` } }); } const chunkSize = (end - start) + 1; const fileStream = fs.createReadStream(videoPath, { start, end }); Object.assign(responseHeaders, { 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 'Content-Length': chunkSize.toString(), }); return new Response(Readable.toWeb(fileStream) as ReadableStream, { status: 206, headers: responseHeaders }); // 206 Partial Content } else { // 전체 파일 요청 (Chrome이 fallback하는 부분) Object.assign(responseHeaders, { 'Content-Length': fileSize.toString(), }); const fileStream = fs.createReadStream(videoPath); return new Response(Readable.toWeb(fileStream) as ReadableStream, { status: 200, headers: responseHeaders }); // 200 OK } };