feat: refine source video keyframe layout
This commit is contained in:
@@ -1837,13 +1837,13 @@ function AudioIntakePanel({
|
||||
|
||||
<div className="grid gap-2 border-t border-white/8 pt-2">
|
||||
<div className="grid gap-2">
|
||||
<div className="grid gap-3 xl:grid-cols-[300px_minmax(0,1fr)] 2xl:grid-cols-[330px_minmax(0,1fr)]">
|
||||
<div className="grid gap-3 xl:grid-cols-[360px_minmax(0,1fr)] 2xl:grid-cols-[390px_minmax(0,1fr)]">
|
||||
<div className="min-w-0">
|
||||
<div className="mb-2 flex items-center justify-between gap-3">
|
||||
<SectionTitle icon={<Play className="h-4 w-4" />} title="原版视频" />
|
||||
<span className="font-mono text-[11px] text-white/38">{currentTime.toFixed(1)}s</span>
|
||||
</div>
|
||||
<div className="relative mx-auto aspect-[9/16] h-[400px] overflow-hidden rounded-md border border-white/10 bg-black 2xl:h-[460px]">
|
||||
<div className="relative mx-auto aspect-[9/16] h-[450px] overflow-hidden rounded-md border border-white/10 bg-black 2xl:h-[510px]">
|
||||
{job.video_url ? (
|
||||
<video
|
||||
ref={videoRef}
|
||||
@@ -2168,39 +2168,78 @@ function SourceReferenceBuildPanel({
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-[250px] overflow-y-auto rounded-md border border-white/10 bg-black/32 p-2 2xl:h-[290px]">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="text-[10.5px] text-white/34">缩略图完整显示,悬停看大图。</span>
|
||||
<span className="text-[10.5px] text-white/30">不勾选则默认用全部帧</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-2 grid grid-cols-[repeat(auto-fill,minmax(38px,1fr))] gap-1">
|
||||
{frames.map((frame, index) => {
|
||||
const selected = selectedFrames.has(frame.index)
|
||||
return (
|
||||
<MediaAssetTile
|
||||
key={frame.index}
|
||||
src={effectiveFrameUrl(job.id, frame)}
|
||||
alt={`关键帧 ${index + 1}`}
|
||||
label={`参考帧 ${String(index + 1).padStart(2, "0")}`}
|
||||
meta={`${frame.timestamp.toFixed(1)}s`}
|
||||
className="aspect-[9/16]"
|
||||
objectFit="contain"
|
||||
selected={selected}
|
||||
title={`关键帧 ${index + 1} · ${frame.timestamp.toFixed(1)}s`}
|
||||
onClick={() => onToggleFrame(frame.index)}
|
||||
topLeft={<span className="rounded bg-black/72 px-1 font-mono text-[9px] text-white/70">{String(index + 1).padStart(2, "0")}</span>}
|
||||
topRight={<span className="rounded-full bg-black/72 p-0.5">{selected ? <Check className="h-3 w-3 text-emerald-200" /> : <Circle className="h-3 w-3 text-white/50" />}</span>}
|
||||
onDelete={onDeleteFrame ? () => void deleteReferenceFrame(frame.index) : undefined}
|
||||
deleting={deletingFrame === frame.index}
|
||||
deleteLabel={`删除关键帧 ${index + 1}`}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
{!frames.length && (
|
||||
<div className="col-span-full flex h-[106px] items-center justify-center rounded border border-dashed border-white/12 text-[11px] text-white/34">
|
||||
点击“自动抽帧 12 张”,或在原版视频播放器上用“当前点抽帧”补充人物参考。
|
||||
<div className="grid gap-2 xl:grid-cols-[minmax(0,1fr)_138px] 2xl:grid-cols-[minmax(0,1fr)_158px]">
|
||||
<div className="min-w-0">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="text-[10.5px] text-white/34">缩略图完整显示,悬停看大图。</span>
|
||||
<span className="text-[10.5px] text-white/30">不勾选则默认用全部帧</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-2 grid grid-cols-[repeat(auto-fill,minmax(38px,1fr))] gap-1">
|
||||
{frames.map((frame, index) => {
|
||||
const selected = selectedFrames.has(frame.index)
|
||||
return (
|
||||
<MediaAssetTile
|
||||
key={frame.index}
|
||||
src={effectiveFrameUrl(job.id, frame)}
|
||||
alt={`关键帧 ${index + 1}`}
|
||||
label={`参考帧 ${String(index + 1).padStart(2, "0")}`}
|
||||
meta={`${frame.timestamp.toFixed(1)}s`}
|
||||
className="aspect-[9/16]"
|
||||
objectFit="contain"
|
||||
selected={selected}
|
||||
title={`关键帧 ${index + 1} · ${frame.timestamp.toFixed(1)}s`}
|
||||
onClick={() => onToggleFrame(frame.index)}
|
||||
topLeft={<span className="rounded bg-black/72 px-1 font-mono text-[9px] text-white/70">{String(index + 1).padStart(2, "0")}</span>}
|
||||
topRight={<span className="rounded-full bg-black/72 p-0.5">{selected ? <Check className="h-3 w-3 text-emerald-200" /> : <Circle className="h-3 w-3 text-white/50" />}</span>}
|
||||
onDelete={onDeleteFrame ? () => void deleteReferenceFrame(frame.index) : undefined}
|
||||
deleting={deletingFrame === frame.index}
|
||||
deleteLabel={`删除关键帧 ${index + 1}`}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
{!frames.length && (
|
||||
<div className="col-span-full flex h-[106px] items-center justify-center rounded border border-dashed border-white/12 text-[11px] text-white/34">
|
||||
点击“自动抽帧 12 张”,或在原版视频播放器上用“当前点抽帧”补充人物参考。
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside className="min-w-0 rounded-md border border-emerald-300/12 bg-emerald-300/[0.035] p-1.5">
|
||||
<div className="mb-1 flex items-center justify-between gap-1">
|
||||
<span className="text-[10px] font-semibold text-emerald-50/70">已选关键帧</span>
|
||||
<span className="rounded border border-emerald-300/15 bg-black/24 px-1.5 py-0.5 font-mono text-[9px] text-emerald-50/55">{selectedReferenceFrames.length}</span>
|
||||
</div>
|
||||
{selectedReferenceFrames.length ? (
|
||||
<div className="grid max-h-[176px] grid-cols-3 gap-1 overflow-y-auto pr-0.5 2xl:max-h-[210px]">
|
||||
{selectedReferenceFrames.map((frame) => {
|
||||
const order = frames.findIndex((item) => item.index === frame.index)
|
||||
const label = order >= 0 ? String(order + 1).padStart(2, "0") : String(frame.index)
|
||||
return (
|
||||
<MediaAssetTile
|
||||
key={frame.index}
|
||||
src={effectiveFrameUrl(job.id, frame)}
|
||||
alt={`已选关键帧 ${label}`}
|
||||
label={`已选 ${label}`}
|
||||
meta={`${frame.timestamp.toFixed(1)}s`}
|
||||
className="aspect-[9/16]"
|
||||
objectFit="contain"
|
||||
selected
|
||||
title={`点击取消选择 · ${frame.timestamp.toFixed(1)}s`}
|
||||
onClick={() => onToggleFrame(frame.index)}
|
||||
topLeft={<span className="rounded bg-black/72 px-1 font-mono text-[8.5px] text-emerald-100/80">{label}</span>}
|
||||
topRight={<span className="rounded-full bg-black/72 p-0.5"><Check className="h-2.5 w-2.5 text-emerald-200" /></span>}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-[106px] items-center justify-center rounded border border-dashed border-emerald-300/12 px-2 text-center text-[10px] leading-snug text-white/30">
|
||||
左侧点击关键帧后,会直接出现在这里。
|
||||
</div>
|
||||
)}
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<div className="mt-2 border-t border-white/8 pt-2">
|
||||
|
||||
Reference in New Issue
Block a user