GhiVideo 소스 복제 — v4 작업 시작 기준

기존 GhiVideo 저장소 HEAD의 트래킹 소스 362개 파일을 복제.
(node_modules·storage·빌드 산출물·대용량 미디어는 .gitignore 규칙대로 제외)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 14:32:51 +09:00
co-authored by Claude Fable 5
commit d38b842e8d
362 changed files with 46358 additions and 0 deletions
@@ -0,0 +1,63 @@
import React, { useState } from 'react';
interface Props {
videoId: string;
onConversionDone: () => void;
}
export default function HlsConversionStatus({ videoId, onConversionDone }: Props) {
const [status, setStatus] = useState<'idle' | 'converting' | 'done' | 'error'>('idle');
const [percent, setPercent] = useState(0);
const startConversion = async () => {
setStatus('converting');
await fetch(`/api/hls/${videoId}/convert`, { method: 'POST' });
const es = new EventSource(`/api/hls/${videoId}/progress`);
es.onmessage = (e) => {
try {
const data = JSON.parse(e.data);
setPercent(Math.round(data.percent ?? 0));
setStatus(data.status);
if (data.status === 'done') {
es.close();
onConversionDone();
} else if (data.status === 'error') {
es.close();
}
} catch {
// ignore parse errors
}
};
es.onerror = () => {
es.close();
setStatus('error');
};
};
return (
<div className="flex items-center gap-2 text-sm">
{status === 'idle' && (
<button
onClick={startConversion}
className="bg-green-700 hover:bg-green-600 text-white px-3 py-1.5 rounded"
>
HLS
</button>
)}
{status === 'converting' && (
<div className="flex items-center gap-2">
<div className="w-24 bg-gray-700 rounded-full h-2">
<div
className="bg-green-500 h-2 rounded-full transition-all"
style={{ width: `${percent}%` }}
/>
</div>
<span className="text-gray-400">{percent}%</span>
</div>
)}
{status === 'done' && <span className="text-green-400">HLS </span>}
{status === 'error' && <span className="text-red-400"> </span>}
</div>
);
}