58 lines
2.1 KiB
TypeScript
58 lines
2.1 KiB
TypeScript
// ✅ 수정된 /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
|
|
}
|
|
}; |