58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
"use client"
|
|
import { type TranscriptSegment } from "@/lib/api"
|
|
|
|
interface Props {
|
|
segments: TranscriptSegment[]
|
|
loading?: boolean
|
|
onSeek?: (sec: number) => void
|
|
}
|
|
|
|
function formatTs(t: number) {
|
|
const m = Math.floor(t / 60)
|
|
const s = Math.floor(t % 60)
|
|
return `${m}:${s.toString().padStart(2, "0")}`
|
|
}
|
|
|
|
export function TranscriptPanel({ segments, loading, onSeek }: Props) {
|
|
if (segments.length === 0) {
|
|
return (
|
|
<div className="glass-card flex h-64 items-center justify-center text-white/30 text-sm">
|
|
{loading ? "音频转写中…" : "转录将在抽帧后自动开始"}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="glass-card overflow-hidden">
|
|
<div className="grid grid-cols-2 divide-x divide-white/10">
|
|
<div className="p-4">
|
|
<div className="mb-3 text-[11px] uppercase tracking-widest text-white/40">English ASR</div>
|
|
</div>
|
|
<div className="p-4">
|
|
<div className="mb-3 text-[11px] uppercase tracking-widest text-white/40">中文翻译</div>
|
|
</div>
|
|
</div>
|
|
<div className="max-h-[480px] overflow-y-auto">
|
|
{segments.map((seg) => (
|
|
<div
|
|
key={seg.index}
|
|
className="grid grid-cols-2 divide-x divide-white/10 border-t border-white/10 hover:bg-white/[0.02] transition cursor-pointer"
|
|
onClick={() => onSeek?.(seg.start)}
|
|
>
|
|
<div className="p-4">
|
|
<div className="text-[10px] font-mono text-white/40 mb-1">
|
|
{formatTs(seg.start)} → {formatTs(seg.end)}
|
|
</div>
|
|
<div className="text-[14px] leading-relaxed text-white/85">{seg.en}</div>
|
|
</div>
|
|
<div className="p-4">
|
|
<div className="text-[10px] font-mono text-white/40 mb-1"> </div>
|
|
<div className="text-[14px] leading-relaxed text-white/85">{seg.zh || <span className="text-white/30">翻译中…</span>}</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|