diff --git a/.memory/worklog.json b/.memory/worklog.json index 056c1d9..9fcaf1e 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,18 +1,5 @@ { "entries": [ - { - "files_changed": 1, - "hash": "765745d", - "message": "auto-save 2026-05-15 13:40 (~1)", - "ts": "2026-05-15T13:40:11+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-15 13:40 (~1)", - "ts": "2026-05-15T05:44:46Z", - "type": "session-heartbeat" - }, { "files_changed": 1, "hash": "9f1b0bd", @@ -3260,6 +3247,19 @@ "type": "session-heartbeat", "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-17 22:03 (~3)", "files_changed": 1 + }, + { + "ts": "2026-05-17T22:14:21+08:00", + "type": "commit", + "message": "auto-save 2026-05-17 22:14 (~3)", + "hash": "e97dcd9", + "files_changed": 3 + }, + { + "ts": "2026-05-17T14:18:30Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-17 22:14 (~3)", + "files_changed": 1 } ] } diff --git a/docs/source-analysis.html b/docs/source-analysis.html index 00e00c6..5c00ecf 100644 --- a/docs/source-analysis.html +++ b/docs/source-analysis.html @@ -589,7 +589,7 @@ web/next.config.mjsNext.js 构建配置:静态导出、图片不走优化、禁用开发环境左下角 Next Dev Indicator,并移除 Next 16 已不支持的 eslint 顶层配置,避免本地 dev 出现配置 Issue 提示。 web/app/globals.css全局主题变量、登录页视觉样式、ReactFlow 样式引用,以及本地开发态 nextjs-portal 遮挡隐藏规则。 web/app/page.tsx产品工作台主状态:jobs、activeJobId、生成任务状态;主渲染为全屏素材输入列 + 信息流广告复刻工作表;“开始”编排状态只负责在下载完成后自动触发 triggerTranscribe,不再默认触发抽帧、Vision 扫描或分镜初稿保存;底部吸附音频条不再从主界面渲染。 - web/components/ad-recreation-board.tsx信息流广告复刻工作表:左侧素材输入;右侧展示视频下载状态、默认折叠的音频文案依据,以及统一的音频解析结果面板;面板顶部是一行讲话人/节奏/背景音摘要,下方左侧为原视频播放器,中间为“关键帧 / 相似主角”,右侧为较窄的逐句时间轴侧栏,底部横向音频波形用参考图式的连续灰色包络显示响度、停顿和密集爆点。视频播放时通过 requestAnimationFrame 平滑驱动波形播放线,同时同步高亮并滚动当前句;点击音频波形或字幕行会跳转原视频时间。关键帧区一键按人物主体目标重新抽取 12 张源视频关键帧,人工勾选后调用 generateSubjectAssetssource_actor + similar 模式生成 6 张白底相似主角视图;这是新演员重构,不做像素提取或精确复刻源人物身份。音频结果下方是信息流复刻分镜工作台:顶部产品参考区是“同一产品素材池”,不限量上传产品图,不做不同产品身份判断;上传原图推荐长边 1200-2000px、短边至少 600px,但后端会统一生成最长边 1600px、JPEG 92 的 AI 工作副本,并回显尺寸、自动转换和风险标注;上传后按“套在脖子上的 U 形肩颈按摩仪”进行同一产品批量识别,左/右按佩戴者身体左右、上/下按佩戴方向,额外标注内外侧、开口方向、局部结构点、背景类型、用途标签、生成风险和备注,用户只检查备注,鼠标悬停通过固定浮层显示大图预览,能盖过滚动容器和分镜框架;缺视角补图失败时保留重试入口。脚本区在分镜行上方提供“作者想法”和“整片改写”,每行新口播文案可直接编辑并可单段 AI 改写,分镜时间和原内容列压缩为窄摘要列,把横向空间留给新口播、画面规划和视频候选;生成本条视频时使用当前编辑后的新口播文案。每条音频分镜纵向排列,行内从左到右串起原内容、新口播文案、画面规划/产品融入和 6 个候选视频槽;候选视频槽在宽屏下一排显示 6 个竖版预览,避免前面空旷、后面拥挤。单条生成会从全局选中关键帧或 12 张关键帧中取最贴近本句时间点的参考帧。单条生成会从产品素材池按分镜角色、视角优先级、用途标签、置信度和风险自动挑选最多 6 张相关产品图,不会把全部产品图提交给生视频模型,然后把产品坐标系、视角标注、方向、结构点和风险写入 Seedance 提示。旧分镜卡、抽帧控制和视频生成组件仍保留在文件里,但当前主路径不渲染。 + web/components/ad-recreation-board.tsx信息流广告复刻工作表:左侧素材输入;右侧展示视频下载状态、默认折叠的音频文案依据,以及统一的音频解析结果面板;面板顶部是一行讲话人/节奏/背景音摘要,下方左侧为原视频播放器,中间为“关键帧 / 相似主角”,右侧为较窄的逐句时间轴侧栏,底部横向音频波形用参考图式的连续灰色包络显示响度、停顿和密集爆点。视频播放时通过 requestAnimationFrame 平滑驱动波形播放线,同时同步高亮并滚动当前句;点击音频波形或字幕行会跳转原视频时间。关键帧区一键按动作峰值目标重新抽取 12 张源视频参考帧,优先抓手势、表情变化、节奏点和镜头变化;人工勾选后调用 generateSubjectAssetssource_actor + similar 模式生成 6 张白底相似主角视图;这是新演员重构,不做像素提取或精确复刻源人物身份。音频结果下方是信息流复刻分镜工作台:顶部产品参考区是“同一产品素材池”,不限量上传产品图,不做不同产品身份判断;上传原图推荐长边 1200-2000px、短边至少 600px,但后端会统一生成最长边 1600px、JPEG 92 的 AI 工作副本,并回显尺寸、自动转换和风险标注;上传后按“套在脖子上的 U 形肩颈按摩仪”进行同一产品批量识别,左/右按佩戴者身体左右、上/下按佩戴方向,额外标注内外侧、开口方向、局部结构点、背景类型、用途标签、生成风险和备注,用户只检查备注,鼠标悬停通过固定浮层显示大图预览,能盖过滚动容器和分镜框架;缺视角补图失败时保留重试入口。脚本区在分镜行上方提供“作者想法”和“整片改写”,每行新口播文案可直接编辑并可单段 AI 改写,分镜时间和原内容列压缩为窄摘要列,把横向空间留给新口播、画面规划和视频候选;生成本条视频时使用当前编辑后的新口播文案。每条音频分镜纵向排列,行内从左到右串起原内容、新口播文案、画面规划/产品融入和 6 个候选视频槽;候选视频槽在宽屏下一排显示 6 个竖版预览,避免前面空旷、后面拥挤。单条生成会从全局选中关键帧或 12 张关键帧中取最贴近本句时间点的参考帧。单条生成会从产品素材池按分镜角色、视角优先级、用途标签、置信度和风险自动挑选最多 6 张相关产品图,不会把全部产品图提交给生视频模型,然后把产品坐标系、视角标注、方向、结构点和风险写入 Seedance 提示。旧分镜卡、抽帧控制和视频生成组件仍保留在文件里,但当前主路径不渲染。 web/app/login/page.tsx生产登录页:访问账号/访问密钥表单、保持登录、错误/成功状态;当前只在原版 Digital Oasis 动态背景上叠加一个组合登录框,桌面端左侧是动态角色,右侧是图标化登录表单;面板左上角展示官网 SKG 字标和中文“营销内容工作台”系统标识。 web/app/login/layout.tsx登录路由专属 layout:覆盖全站默认网页标题和描述为空,避免 /login 继承工作台 metadata 后在页面源码里继续出现登录界面文字以外的文案。 web/components/login/oasis-canvas.tsx登录页全屏动态视觉层:用 iframe 直接承载下载包 web/public/oasis-source/index.html 的原 WebGPU / Three.js 草场源码;父级登录页只覆盖自己的文案和表单,并在捕获阶段把全局鼠标坐标同时用原生事件和 postMessage 转发给 iframe,避免登录面板或输入框遮挡时草地失去鼠标响应。 @@ -626,7 +626,7 @@ web/app/page.tsx -> 信息流广告复刻工作表:web/components/ad-recreation-board.tsx -> 开始:创建/激活 job → 下载完成后自动触发音频处理 - -> 左侧素材输入列 + 右侧默认折叠的音频文案依据 + 统一音频解析结果面板(声音摘要在上,原视频 / 人物主体 12 张关键帧选择 / 相似主角 6 白底视图 / 较窄逐句时间轴侧栏并排,底部连续响度波形联动) + -> 左侧素材输入列 + 右侧默认折叠的音频文案依据 + 统一音频解析结果面板(声音摘要在上,原视频 / 动作峰值 12 张参考帧选择 / 相似主角 6 白底视图 / 较窄逐句时间轴侧栏并排,底部连续响度波形联动) -> 信息流复刻分镜工作台:同一产品素材池不限量上传 → 自动识别视角 / 背景 / 用途 / 风险 → 人工检查备注 → 单条生成自动挑选最多 6 张相关产品图 → 逐句时间轴 → 原内容 / 新口播文案 / 画面规划与产品融入 / 6 个候选视频槽 -> 底部音频条:不再渲染,音频结果集中到右侧工作表 -> 旧节点/深度素材面板:web/components/nodes/index.tsx、web/components/lightbox.tsx、web/components/storyboard-workbench.tsx(底层保留,当前不作为主入口) @@ -874,7 +874,7 @@ ProductRefStateItem { 创建任务POST /jobscreateJob提交 TK 链接,后台开始下载;前端“开始”队列会在 downloaded 后自动触发音频解析。 上传视频POST /jobs/uploaduploadJob保存 source.mp4,然后同样进入下载完成状态;当前上传后也加入第一步队列,下载完成后自动解析音频。 删除输入视频DELETE /jobs/{id}deleteJob从任务队列、URL 和磁盘 jobs/<id> 目录移除整个 job,包括源视频、关键帧、元素提取图和生成视频。 - 解析视频POST /jobs/{id}/analyze?frames=&target=&mode=&quality=analyzeJob后续阶段保留的抽帧能力。默认 frames=12target 支持透明骨架人、综合、清晰主体、转场变化、表情瞬间、动作峰值。当前第一步主流程不自动调用该接口;原版视频旁的“抽人物 12 帧”会显式用 target=subjectquality=accuratemode=replace 重新生成全局人物主体关键帧池。 + 解析视频POST /jobs/{id}/analyze?frames=&target=&mode=&quality=analyzeJob后续阶段保留的抽帧能力。默认 frames=12target 支持透明骨架人、综合、清晰主体、转场变化、表情瞬间、动作峰值。当前第一步主流程不自动调用该接口;原版视频旁的“抽参考 12 帧”会显式用 target=motionquality=accuratemode=replace 重新生成全局动作/节奏参考帧池。 音频文案轨POST /jobs/{id}/transcribetriggerTranscribe若尚未拆轨,先从 source.mp4 提取 audio.wav 并回填 source_audio_url;随后用 ASR 提取原始文案,翻译成中文,写入 audio_script.source_textsource_zh 和逐句 transcript。远端 ASR_MODEL 失败后先走本机 LOCAL_ASR_BIN/LOCAL_ASR_MODEL(默认 mlx_whisper),再尝试 ASR_FALLBACK_MODEL。后端会拒绝重复文本、逐秒假字幕或覆盖率过低的结果,不再把不可听的多模态输出写进时间轴。再用 ASR_FALLBACK_MODEL 多模态音频分析讲话人、语速节奏、停顿、背景音乐/环境声/音效,写入 speaker_profilerhythm_profilebackground_audio_profile。当前第一步不默认生成 SKG 新口播和 MiniMax 配音。 分镜脚本改写POST /jobs/{id}/script/rewriterewriteStoryboardScript根据原参考文案、当前新口播、分镜角色、时间段和作者想法改写中文口播。mode=segment 只改一段;mode=all 一次改完整片,要求整片前后连贯。接口只返回 items[index,text],前端暂存在当前页面状态里,生成本条视频时写入 StoryboardScene.action。 原始音频文件GET /jobs/{id}/audio.wavsourceAudioUrl返回拆轨得到的 wav;当前主界面不再渲染底部吸附音频条,右侧复刻工作表会读取该文件生成参考图式横向响度波形,并和原视频、逐句时间轴联动。 @@ -1003,6 +1003,18 @@ ProductRefStateItem {

变更记录

这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。

+
+
+

2026-05-17 · 自动抽帧恢复为动作峰值参考帧

+ UI + Workflow +
+
+

问题:上一版把原视频旁的自动抽帧从动作峰值改成人物主体后,结果更偏中心清晰画面,少了之前信息流广告需要的手势、表情、节奏点和镜头变化。

+

改动:SourceReferenceBuildPanel 的按钮改为“抽参考 12 帧”,调用 analyzeJob 时恢复使用 target=motionquality=accuratemode=replace。人物仍然是后续相似主角重构的选择对象,但自动抽帧不再只按清晰主体排序。

+

影响:web/components/ad-recreation-board.tsxdocs/source-analysis.html。后续这里的自动 12 帧应理解为“广告动作/节奏参考帧池”;若某个具体人物画面没抽到,用“当前点抽帧”手动补。

+
+

2026-05-17 · 原版视频放大并支持当前点抽帧删除

@@ -1012,7 +1024,7 @@ ProductRefStateItem {

问题:原版视频区域偏小,只能看和播放;如果需要补某个具体画面,用户必须重新跑 12 帧抽取,并且抽错后缺少直接删除入口。

改动:AudioIntakePanel 放大原视频列和视频高度,并把逐句时间轴压成较窄侧栏;SourceReferenceBuildPanel 接收当前播放秒数,新增“当前点抽帧”按钮,复用 addManualFrame;关键帧缩略图右下角新增删除按钮,复用 deleteFrame,并展示全部已抽帧而不只截取前 12 张。

-

影响:web/components/ad-recreation-board.tsxdocs/source-analysis.html。后续描述这里时,应把原版视频旁的关键帧区理解为“人物参考帧池”,支持自动抽人物、按播放点补帧和单帧删除。

+

影响:web/components/ad-recreation-board.tsxdocs/source-analysis.html。后续描述这里时,应把原版视频旁的关键帧区理解为“广告参考帧池”,支持自动抽参考帧、按播放点补帧和单帧删除。

diff --git a/web/components/ad-recreation-board.tsx b/web/components/ad-recreation-board.tsx index 2ad7e50..b3521b2 100644 --- a/web/components/ad-recreation-board.tsx +++ b/web/components/ad-recreation-board.tsx @@ -1267,9 +1267,9 @@ function SourceReferenceBuildPanel({ for (const frame of job.frames) { if (selectedFrames.has(frame.index)) onToggleFrame(frame.index) } - const updated = await analyzeJob(job.id, 12, "subject", "replace", "accurate") + const updated = await analyzeJob(job.id, 12, "motion", "replace", "accurate") onJobUpdate(updated) - toast.info("已开始按人物主体重新抽取 12 张关键帧,完成后在这里人工选择参考。") + toast.info("已按动作峰值逻辑重新抽取 12 张参考帧,完成后在这里人工选择主角参考。") } catch (e) { toast.error("12 张关键帧抽取失败:" + (e instanceof Error ? e.message : String(e))) } finally { @@ -1356,10 +1356,11 @@ function SourceReferenceBuildPanel({ type="button" onClick={() => void extractKeyframes()} disabled={!job.video_url || extracting || job.status === "splitting"} + title="按之前的动作峰值逻辑抽帧,更偏向手势、表情变化、节奏点和镜头变化" className="inline-flex h-7 items-center justify-center gap-1 rounded-md border border-white/10 bg-white/[0.055] px-2 text-[10.5px] font-semibold text-white/66 transition hover:border-cyan-300/35 hover:text-cyan-100 disabled:cursor-not-allowed disabled:opacity-35" > {extracting || job.status === "splitting" ? : } - 抽人物 12 帧 + 抽参考 12 帧
)} @@ -1927,7 +1928,7 @@ function AudioStoryboardPlanPanel({
- {referenceFrame ? `参考 ${referenceFrame.timestamp.toFixed(1)}s · 可多次生成候选` : "先在原版视频旁抽人物 12 帧"} + {referenceFrame ? `参考 ${referenceFrame.timestamp.toFixed(1)}s · 可多次生成候选` : "先在原版视频旁抽参考 12 帧"}