diff --git a/.memory/worklog.json b/.memory/worklog.json
index 0896281..24adfe4 100644
--- a/.memory/worklog.json
+++ b/.memory/worklog.json
@@ -3121,6 +3121,19 @@
"type": "session-heartbeat",
"message": "Claude 会话活跃 · 最近命令:claude · 5 项未提交变更 · 最近提交:auto-save 2026-05-14 03:48 (~1)",
"files_changed": 5
+ },
+ {
+ "ts": "2026-05-14T03:53:51+08:00",
+ "type": "commit",
+ "message": "auto-save 2026-05-14 03:53 (~5)",
+ "hash": "6eb1f98",
+ "files_changed": 5
+ },
+ {
+ "ts": "2026-05-13T19:58:49Z",
+ "type": "session-heartbeat",
+ "message": "Codex 会话活跃 · 最近命令:codex · 3 项未提交变更 · 最近提交:auto-save 2026-05-14 03:53 (~5)",
+ "files_changed": 3
}
]
}
diff --git a/docs/source-analysis.html b/docs/source-analysis.html
index 5e24d79..990017c 100644
--- a/docs/source-analysis.html
+++ b/docs/source-analysis.html
@@ -596,7 +596,7 @@
web/app/page.tsx
-> ReactFlow 节点:web/components/nodes/index.tsx
-> 主画布:Input → VisualLab / Audio → Compose
- -> 画布内视频抽帧面板:InputNode 双击视频缩略图打开 videoFramePanel
+ -> 画布内视频抽帧面板:InputNode 单击视频缩略图打开 videoFramePanel
-> 画布内镜头拆解面板:VisualLabNode 打开 keyframePanel,内嵌 web/components/lightbox.tsx
-> 分镜工作台:web/components/storyboard-workbench.tsx(底层保留)
-> API 契约:web/lib/api.ts
@@ -701,7 +701,7 @@ api/main.py
| 创建任务 | POST /jobs | createJob | 提交 TK 链接,后台开始下载,停在 downloaded 等用户点解析。 |
| 上传视频 | POST /jobs/upload | uploadJob | 保存 source.mp4,然后同样进入下载完成状态。 |
| 删除输入视频 | DELETE /jobs/{id} | deleteJob | 从任务队列、URL 和磁盘 jobs/<id> 目录移除整个 job,包括源视频、关键帧、元素提取图和生成视频。 |
- | 解析视频 | POST /jobs/{id}/analyze | analyzeJob | 拆轨 + 抽关键帧。当前不自动跑 ASR,避免 audio 阻塞视觉管线。 |
+ | 解析视频 | POST /jobs/{id}/analyze?frames=&target= | analyzeJob | 拆轨 + 目标化抽关键帧。target 支持综合、清晰主体、转场变化、表情瞬间、动作峰值;当前不自动跑 ASR,避免 audio 阻塞视觉管线。 |
| 手动加帧 | POST /jobs/{id}/frames?t= | addManualFrame | 按视频时间戳抽一帧,index 递增但 frames 按 timestamp 排序。 |
| Vision 识别 | POST /frames/{idx}/describe | describeFrame | 写入 frame.description,后续可从 objects 加候选元素。 |
| 清洗水印 | POST /frames/{idx}/cleanup | cleanupFrame | 支持全图和区域清洗,生成 cleaned 待应用版本。 |
@@ -723,7 +723,7 @@ api/main.py
| 输入 Input |
- 创建/上传任务,显示视频就绪,触发解析;双击视频缩略图打开画布内抽帧面板。 |
+ 创建/上传任务,显示视频就绪,选择抽帧目标并触发解析;单击视频缩略图打开画布内抽帧面板。 |
不要自动一路跑到 ASR 或生图;用户需要控制解析节奏。 |
page.tsx、InputNode、VideoFramePanelNode、api/main.py |
@@ -817,6 +817,18 @@ api/main.py
变更记录
这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。
+
+
+ 2026-05-14 · 自动抽帧支持目标化扫描
+ Input
+ Frame Target
+
+
+
问题:单一“自动抽帧”无法表达这次要清晰人物、下次要转场变化或表情瞬间的不同目标;但把抽帧做成复杂参数面板会破坏 Input 卡片的轻量工作流。
+
改动:Input 节点新增一个抽帧目标下拉,默认“综合关键帧”,可切换清晰主体、转场变化、表情瞬间、动作峰值。后端 /jobs/{id}/analyze 新增 target 参数,先低清低帧率扫描候选,再按目标评分、pHash 去重、时序分桶,最后只对选中的时间点从原视频抽高质量关键帧。
+
影响:api/main.py、web/lib/api.ts、web/app/page.tsx、web/components/nodes/index.tsx、docs/source-analysis.html。当前“人物/动物表情”是本地近似评分,后续可把候选小图接入视觉模型重排。
+
+
2026-05-14 · 视频抽帧面板默认静音播放
diff --git a/web/app/page.tsx b/web/app/page.tsx
index aa2f22e..590f54d 100644
--- a/web/app/page.tsx
+++ b/web/app/page.tsx
@@ -546,7 +546,7 @@ export default function Home() {
onCopyImage: handleCopyImage,
pinnedNodes,
onToggleNodePin: handleToggleNodePin,
- }), [job, jobs, activeJobId, submitting, analyzing, selectedFrames, expandedFrame, framePanelScale, framePanelPinned, framePanelDock, videoPanelJobId, videoPanelScale, videoPanelDock, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleOpenFramePanel, handleFramePanelScaleChange, handleAddManualFrame, handleAddManualFrameForJob, handleOpenVideoPanel, handleVideoPanelScaleChange, handleSwitchJob, setJob, handleDeleteJob, handleDeleteFrame, handleDeleteFrameForJob, handleDeleteGenerated, handleDeleteVideo, handleDeleteCutout, handleCopyImage, pinnedNodes, handleToggleNodePin])
+ }), [job, jobs, activeJobId, submitting, analyzing, frameTarget, selectedFrames, expandedFrame, framePanelScale, framePanelPinned, framePanelDock, videoPanelJobId, videoPanelScale, videoPanelDock, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleOpenFramePanel, handleFramePanelScaleChange, handleAddManualFrame, handleAddManualFrameForJob, handleOpenVideoPanel, handleVideoPanelScaleChange, handleSwitchJob, setJob, handleDeleteJob, handleDeleteFrame, handleDeleteFrameForJob, handleDeleteGenerated, handleDeleteVideo, handleDeleteCutout, handleCopyImage, pinnedNodes, handleToggleNodePin])
// 用 useNodesState 让 ReactFlow 自己管位置(避免轮询时重置 drag)
const savedSizes = useMemo(() => loadNodeSizes(), [])