auto-save 2026-05-14 10:25 (~13)

This commit is contained in:
2026-05-14 10:25:50 +08:00
parent be1ae80750
commit 7bfbb38289
13 changed files with 118 additions and 52 deletions

View File

@@ -137,7 +137,7 @@ const FRAME_TARGET_OPTIONS: Array<{ value: FrameExtractTarget; label: string; hi
{ value: "expression", label: "表情瞬间", hint: "人物 / 动物表情倾向" },
{ value: "motion", label: "动作峰值", hint: "动作变化更明显" },
]
const FRAME_COUNT_OPTIONS = [3, 5, 8, 12]
const FRAME_COUNT_OPTIONS = [12, 8, 5, 3]
const FRAME_QUALITY_OPTIONS: Array<{ value: FrameExtractQuality; label: string; hint: string }> = [
{ value: "auto", label: "自动", hint: "按电脑性能和视频时长自动选择" },
{ value: "fast", label: "快速", hint: "2fps / 360px长视频省电" },
@@ -573,7 +573,7 @@ export function InputNode({ data, selected }: NodeProps<{ data: NodeData }> | an
const thumbNaturalWidth = ready && j.height ? Math.max(96, Math.round(THUMBNAIL_HEIGHT * j.width / j.height)) : 96
const toolWidth = Math.max(148, thumbNaturalWidth)
const target = d.frameTargets[j.id] ?? "transparent_human"
const count = d.frameCounts[j.id] ?? 5
const count = d.frameCounts[j.id] ?? 12
const quality = d.frameQualities[j.id] ?? "auto"
const jHasFrames = j.frames.length > 0
const jRunning = ["splitting", "transcribing"].includes(j.status)
@@ -813,7 +813,7 @@ export function VideoFramePanelNode({ data }: any) {
const frames = [...panelJob.frames].sort((a, b) => a.timestamp - b.timestamp)
const aspect = panelJob.width && panelJob.height ? `${panelJob.width}/${panelJob.height}` : "9/16"
const panelTarget = d.frameTargets[panelJob.id] ?? "transparent_human"
const panelCount = d.frameCounts[panelJob.id] ?? 5
const panelCount = d.frameCounts[panelJob.id] ?? 12
const panelQuality = d.frameQualities[panelJob.id] ?? "auto"
const panelRunning = ["splitting", "transcribing"].includes(panelJob.status)
const dockText: Record<CanvasPanelDock, string> = {
@@ -1997,7 +1997,7 @@ export function KeyframePanelNode({ data }: any) {
}
/* ============================================================
5. ASRNode — Gemini 转录
5. ASRNode — 音频转写
============================================================ */
export function ASRNode({ data, selected }: any) {
const d: NodeData = data
@@ -2012,7 +2012,7 @@ export function ASRNode({ data, selected }: any) {
onTogglePin={() => d.onToggleNodePin?.("asr")}
>
<div className="text-[11.5px] text-[var(--text-soft)]">
Gemini 2.5 ·
OpenAI-compatible ASR ·
</div>
{d.job && d.job.transcript.length > 0 && (
<div className="mt-2 max-h-24 overflow-y-auto text-[11px] space-y-1 text-[var(--text-strong)]">
@@ -2069,13 +2069,14 @@ export function TranslateNode({ data, selected }: any) {
}
/* ============================================================
7. RewriteNode (placeholder)
7. RewriteNode
============================================================ */
export function RewriteNode({ data, selected }: any) {
const d: NodeData = data
const rewrittenText = d.job?.audio_script?.rewritten_text?.trim() ?? ""
return (
<NodeShell
type="ai" status="pending"
type="ai" status={rewrittenText ? "done" : d.job?.audio_script?.status === "rewriting" ? "running" : "pending"}
icon={<FileEdit className="h-4 w-4" />}
title="产品文案 · Rewrite"
subtitle="STEP 5 · 接 SKG 卖点"
@@ -2083,19 +2084,20 @@ export function RewriteNode({ data, selected }: any) {
pinned={d.pinnedNodes?.has("rewrite")}
onTogglePin={() => d.onToggleNodePin?.("rewrite")}
>
<textarea
placeholder="粘贴 SKG 产品信息 / 关键卖点(可作为视频脚本和镜头动作参考)"
rows={3}
disabled
className="w-full text-[11.5px] px-2.5 py-2 rounded-md bg-white/30 dark:bg-white/[0.03] border border-dashed border-black/15 dark:border-white/10 placeholder:text-[var(--text-faint)] text-[var(--text-strong)] resize-none opacity-70"
/>
<div className="mt-1.5 text-[10px] text-[var(--text-faint)]"></div>
{rewrittenText ? (
<div className="rounded-md border border-emerald-400/25 bg-emerald-400/10 px-2.5 py-2 text-[11.5px] leading-relaxed text-[var(--text-strong)]">
{rewrittenText}
</div>
) : (
<div className="text-[11px] text-[var(--text-soft)]"> SKG </div>
)}
<div className="mt-1.5 text-[10px] text-[var(--text-faint)]">{d.job?.audio_script?.rewrite_model || "AUDIO_REWRITE_MODEL"}</div>
</NodeShell>
)
}
/* ============================================================
5b. AudioNode — 合并 ASR + 翻译 + 改写为一个"音频处理"节点(占位卡片,无填充)
5b. AudioNode — 合并 ASR + 翻译 + 改写 + MiniMax 配音
============================================================ */
export function AudioNode({ data, selected }: any) {
const d: NodeData = data
@@ -2127,7 +2129,7 @@ export function AudioNode({ data, selected }: any) {
<div>
ASR SKG MiniMax <br />
<span className="text-[var(--text-faint)] font-mono">
{audioScript?.rewrite_model || "Gemini 2.5 Pro"} {audioScript?.voice_model || "MiniMax T2A"}
{audioScript?.rewrite_model || "AUDIO_REWRITE_MODEL"} {audioScript?.voice_model || "MiniMax T2A"}
</span>
</div>
{rewrittenText && (