diff --git a/.memory/worklog.json b/.memory/worklog.json
index 3ac8cf0..8d8d89b 100644
--- a/.memory/worklog.json
+++ b/.memory/worklog.json
@@ -1,19 +1,5 @@
{
"entries": [
- {
- "files_changed": 4,
- "hash": "35b3278",
- "message": "auto-save 2026-05-12 16:16 (~4)",
- "ts": "2026-05-12T16:16:52+08:00",
- "type": "commit"
- },
- {
- "files_changed": 1,
- "hash": "7283928",
- "message": "auto-save 2026-05-12 16:22 (~1)",
- "ts": "2026-05-12T16:22:23+08:00",
- "type": "commit"
- },
{
"files_changed": 1,
"hash": "03cd5b4",
@@ -3357,6 +3343,19 @@
"type": "session-heartbeat",
"message": "Codex 会话活跃 · 最近命令:codex · 2 项未提交变更 · 最近提交:auto-save 2026-05-14 05:43 (~3)",
"files_changed": 2
+ },
+ {
+ "ts": "2026-05-14T05:49:26+08:00",
+ "type": "commit",
+ "message": "auto-save 2026-05-14 05:49 (~2)",
+ "hash": "a98639a",
+ "files_changed": 2
+ },
+ {
+ "ts": "2026-05-13T21:53:13Z",
+ "type": "session-heartbeat",
+ "message": "Claude 会话活跃 · 最近命令:claude · 3 项未提交变更 · 最近提交:auto-save 2026-05-14 05:49 (~2)",
+ "files_changed": 3
}
]
}
diff --git a/docs/source-analysis.html b/docs/source-analysis.html
index 08b856e..6f07a08 100644
--- a/docs/source-analysis.html
+++ b/docs/source-analysis.html
@@ -623,7 +623,7 @@ api/main.py
你看到的区域关键帧素材审核面板
-
主要源码FrameLightbox;按“原图/清洗、场景图、主体资产、审核”四个页签组织;清洗页支持一键批量生成待审核清洗版,相关接口包括 cleanupFrame、addElement、generateSceneAsset、generateSubjectAssets。
+
主要源码FrameLightbox;按“原图/清洗、场景图、主体资产、审核”四个页签组织;非主体页采用左侧大图 + 右侧窄状态栏,主体资产页保留较宽右栏;清洗页支持一键批量生成待审核清洗版,相关接口包括 cleanupFrame、addElement、generateSceneAsset、generateSubjectAssets。
适合怎么描述“某张关键帧的水印、场景图、主体多视角/动作/表情图和质量风险应该如何审核”。
@@ -724,7 +724,7 @@ SubjectAsset {
| 解析视频 | POST /jobs/{id}/analyze?frames=&target=&mode=&quality= | analyzeJob | 拆轨 + 目标化抽关键帧。target 支持综合、清晰主体、转场变化、表情瞬间、动作峰值;mode=append 追加新关键帧;quality=auto 根据本机算力和视频时长自动选择快速、精细或极准。多个抽帧请求进入后端队列顺序处理。 |
| 手动加帧 | POST /jobs/{id}/frames?t= | addManualFrame | 按视频时间戳抽一帧,index 递增但 frames 按 timestamp 排序。 |
| Vision 识别 | POST /frames/{idx}/describe | describeFrame | 写入 frame.description,后续可从 objects 加候选元素。 |
-
| 清洗水印 | POST /frames/{idx}/cleanup | cleanupFrame | 支持全图和区域清洗,生成 cleaned 待应用版本;前端批量清洗会顺序调用该接口,不自动覆盖原图。 |
+
| 清洗水印 | POST /frames/{idx}/cleanup | cleanupFrame | 支持全图和区域清洗,生成 cleaned 待应用版本;前端批量清洗会顺序调用该接口,不自动覆盖原图。单帧清洗状态按 frame.index 隔离,清洗某一张不会禁用其他关键帧的清洗按钮。 |
| 应用清洗 | POST /cleanup/apply | applyCleanedFrame | 物理覆盖 frames/{idx}.jpg,并备份原图。 |
| 元素增改删 | POST/PATCH/DELETE /elements | addElement/updateElement/deleteElement | 让用户修正 Vision 错误,避免候选结果锁死。 |
| 元素提取 | POST /elements/{element_id}/cutout | cutoutElement | 调用图像模型生成独立白底素材图,每次累积一张 cutout。 |
@@ -839,6 +839,30 @@ SubjectAsset {
变更记录
这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。
+
+
+ 2026-05-14 · 关键帧素材面板右侧改为紧凑状态栏
+ FrameLightbox
+ Layout
+
+
+
问题:移除旧元素提取和手工加主体入口后,关键帧详情右侧内容变少,继续占用大列会压缩左侧主图和清洗操作区。
+
改动:FrameLightbox 在“原图/清洗、场景图、审核”页把右侧改成固定窄状态栏,左侧主图和操作区获得更大宽度;“主体资产”页仍保留较宽右栏,用于主体识别、主体清单和资产包。
+
影响:web/components/lightbox.tsx、docs/source-analysis.html。
+
+
+
+
+ 2026-05-14 · 单帧清洗不再全局锁住其他帧
+ FrameLightbox
+ Bugfix
+
+
+
问题:单独清洗某一张关键帧时,前端使用全局 cleaning 布尔状态,导致切到其他关键帧后清洗按钮仍被禁用。
+
改动:FrameLightbox 改用 cleaningFrameIds 按 frame.index 记录正在清洗的帧,只禁用当前正在清洗的那一张;其他帧可以继续单独清洗。区域清洗完成时也只在用户仍停留于同一帧时清空当前框选,避免异步完成误清别的帧操作状态。
+
影响:web/components/lightbox.tsx、docs/source-analysis.html。
+
+
2026-05-14 · 清洗页支持一键批量清洗
diff --git a/web/components/lightbox.tsx b/web/components/lightbox.tsx
index 1dfed51..fc2953a 100644
--- a/web/components/lightbox.tsx
+++ b/web/components/lightbox.tsx
@@ -128,6 +128,8 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
...(f.quality_report?.warnings ?? []),
...(latestSceneAsset?.quality_report?.warnings ?? []),
]
+ const isSubjectTab = activeTab === "subject"
+ const isCleanTab = activeTab === "clean"
const handleDescribe = async () => {
setDescribing(true)
@@ -421,12 +423,16 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
- {/* 主体 — 左:大图 + 清洗状态;右:主体识别 + 主体资产 */}
+ {/* 主体 — 左:大图 + 主操作;右:当前页上下文 / 主体资产 */}
{/* 左侧大图区 */}
{/* 上方:主图 + 画框 overlay */}
@@ -482,144 +494,6 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
)}
- {activeTab === "clean" && (
- <>
-
-
-
-
批量清洗
-
- 先批量生成待审核清洗版,不直接覆盖原图
-
-
-
- {cleanedFrameCount}/{frames.length}
-
-
- {batchCleanupProgress && (
-
-
- {batchCleaning ? "清洗中" : "最近批量清洗"}
- {batchCleanupProgress.done}/{batchCleanupProgress.total}{batchCleanupProgress.failed ? ` · 失败 ${batchCleanupProgress.failed}` : ""}
-
-
-
- )}
-
-
-
- {/* 画框工具栏 */}
- {cropMode ? (
-
-
- {regions.length === 0
- ? "在图上拖动鼠标 → 框选要清洗的水印、字幕、平台 UI 或杂物"
- : `已框 ${regions.length} 个 · 继续加框或点击「去掉」批量清洗`}
-
-
-
-
-
-
-
- ) : (
-
- )}
-
- {/* 下方:清洗版(有待应用版本时显示) */}
- {hasCleaned && cleanedSrc && (
-
-
-
-

-
-
- )}
-
- {/* 清洗按钮(全图) */}
-
- >
- )}
-
{activeTab === "scene" && (
@@ -702,6 +576,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
)}
+ {activeTab !== "clean" && (
@@ -711,25 +586,47 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
抽帧留下的关键帧默认都会参与清洗、场景图和主体资产准备,不需要在这里单独选用。
+ )}
{/* 右侧主体识别 + 主体资产 */}
-
+
{activeTab === "clean" && (
-
- 清洗审核
- 可以先一键清洗全部素材帧,系统只生成待审核清洗版,不直接覆盖原图。看到没处理好的帧,再回到这张图用框选区域做局部清洗。
+
+ 清洗状态
+
+
+
当前
+
{f.cleaned_applied ? "已应用" : hasCleaned ? "待审核" : "未清洗"}
+
+
+
全部
+
{cleanedFrameCount}/{frames.length}
+
+
+ 先批量生成清洗版,再对问题帧局部框选补洗。
)}
{activeTab === "scene" && (
-
- 场景资产规则
- 每张已选关键帧只需要一张主场景图。它用于后续生视频的空间、构图和光线参考;生成后仍需人工确认水印和细节是否被误改。
+
+ 场景状态
+
+
当前场景图
+
+ {latestSceneAsset ? `${latestSceneAsset.width}×${latestSceneAsset.height}` : "未生成"}
+
+
+ 每张关键帧保留一张主场景图,用于空间、构图和光线参考。
{f.scene_assets?.length ? (
-
+
{f.scene_assets.slice(-4).map((asset) => (
-
})
+
{asset.width}×{asset.height}
))}
@@ -738,13 +635,25 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
)}
{activeTab === "review" && (
-
- 当前帧状态
-
-
清洗:{f.cleaned_applied ? "已应用" : hasCleaned ? "待确认" : "未处理"}
-
场景图:{latestSceneAsset ? `${latestSceneAsset.width}×${latestSceneAsset.height}` : "未生成"}
-
主体候选:{elements.length} 个
-
主体资产:{subjectAssetCount} 张
+
+ 当前帧状态
+
+
+
清洗
+
{f.cleaned_applied ? "已应用" : hasCleaned ? "待确认" : "未处理"}
+
+
+
场景
+
{latestSceneAsset ? "已生成" : "未生成"}
+
+
+
主体
+
{elements.length} 个
+
+
+
资产
+
{subjectAssetCount} 张
+
)}