# SKG TK 二创验证

源码解析与协作地图。用于把产品需求准确映射到代码位置。

Source Analysis · 2026-05-13

## 这个页面是产品协作地图，不是应用功能页。

它把“你看到的界面、你想改的功能、实际要动的源码、可能影响的数据和接口”放在同一个地方。 后续描述需求时，可以直接说“改素材输入列 / 音频解析结果 / 分镜工作台 / 某个接口行为”，这样改动范围会更准，也更容易追踪每次变更带来的影响。

项目路径/Users/kangwan/Projects/business/20260512-20260512-skg-tk-二创验证
前端 Next.js 16 · 端口 4290 · web/app/page.tsx
后端 FastAPI · 端口 4291 · api/main.py
本文档位置 docs/source-analysis.html · 独立文件，不接入应用

## 怎么用它描述需求

### 1. 先说你在改哪个产品区

例如“素材输入列”、“音频解析结果”、“逐句时间轴 / 讲话人分析 / 背景音分析”、“信息流复刻分镜工作台”。不要只说“这里乱”，要指向页面里的功能区。

### 2. 再说这个区应该承担什么职责

例如“Vision 只给候选元素，用户必须能编辑、删除、重新提取”，这会直接落到 `FrameLightbox` 和元素接口。

### 3. 最后说不希望发生什么

例如“点击元素不要跳页面”、“不要直接进入编排打断思路”、“不要把参考视频复刻成一样的东西”。这能约束交互和文案。

建议表达格式：我要改「功能区」；当前问题是「行为」；正确职责是「业务目的」；不要影响「已有流程」。

## 运行与入口

项目 | 命令 / 入口 | 说明
--- | --- | ---
本地后台启动 | `./scripts/start-dev-background.sh` | 不弹出 macOS Terminal 窗口；自动检查 4290 / 4291，缺哪个启动哪个，日志写入 `.logs/`，PID 写入 `.pids/`。
本地后台停止 | `./scripts/stop-dev-background.sh` | 按 `.pids/` 里的 PID 停止后台前端 / 后端进程。
生产站点 | `https://marketing.skg.com` | 公司域名已解析到 VPS `76.13.31.179`。线上由既有 Coolify / Traefik 负责 HTTPS 入口，项目 `web` 容器用 Nginx 承载静态前端；`/login/`、`/_next/`、`/assets/`、`/skg-logo-black.svg`、`/oasis-source/` 为公开登录页资源，未登录访问工作台跳转 `/login/`，`/api/` 通过 `auth_request` 校验 FastAPI 会话 Cookie 后再反代。
生产部署 | `docker compose -f docker-compose.prod.yml --env-file deploy/.env.production up -d --build` | 服务器目录为 `/opt/skg-marketing-studio`；后端任务文件挂载到 `./data/jobs`，全局资源中心挂载到 `./data/asset_library`、`./data/prompt_library` 和 `./data/_trash`，真实 Key 只放服务器 `deploy/.env.production`。Web 上线验收必须按 Docker 静态形态跑 `./scripts/verify-prod-docker.sh`，不能只用本地 `npm run build` 替代。
前端开发服务 | `cd web && npm run dev` | Next.js App Router，主页面是 `web/app/page.tsx`，默认端口 4290。
后端开发服务 | `cd api && source .venv/bin/activate && uvicorn main:app --host 127.0.0.1 --port 4291` | FastAPI，所有任务状态、视频、关键帧、清洗、元素、分镜保存都在 `api/main.py`。长下载 / 抽帧 / 音频处理期间不要带 `--reload`，否则 reload 会等待后台任务结束并让新请求卡住。
测试页面 | `http://localhost:4290/?job=c6767f3a166b` | URL 里可放多个 job id：`?job=id1,id2,id3`，前端会恢复多个任务并激活最后一个。
源码解析页 | `open docs/source-analysis.html` | 独立静态 HTML，不被 Next 构建、不影响产品工作台。

## 业务管线

当前产品方向已收窄为“信息流广告快速复刻”：主界面左侧是素材输入列，右侧是信息流复刻工作表。后台仍按 01-09 流程顺序计算素材任务、源视频、音频文案、抽帧、主体资产、产品资产、分镜文案、三字段规划和视频候选这些状态，但这些判断不再默认显现在工作区顶部，避免状态提示挤占首屏操作空间。用户粘贴 TK 链接或上传视频后点击“开始分析”，系统自动下载源视频；下载完成后并行启动音频文案路和视频视觉路。音频文案路提取原音频文案/字幕，分析讲话人、语速节奏、背景音乐/环境声/音效，并为后续新口播和分镜文案提供时间轴；视频视觉路同步抽取参考帧。源视频工作区右侧主体链路是“参考帧池 → 转换层 → 主体元素”：参考帧池只作为竖向原始参考，转换层收敛为项目内生图对话智能体，不再默认展示真人重构、卡通重构、元素重构、自主描述四个卡片，也不再单独放数量按钮；用户把 1-3 张参考帧拖入同一个参考区，点击“开始分析”后直接在对话里说明方向、数量、风格、服装统一、人物占比和保留/删除元素，后端从对话中识别当前生成模式和张数，再点击生成主体套图。真人/卡通/元素和有文字的自主描述属于参考创新重构，会先识别参考帧再用参考图通道生成；自主描述没有文字时切到源形象锁定模式，按参考帧复刻同一可见主体；旧下方主体模板库不再作为主路径。波形下方的画面胶片由前端临时从源视频截取，密度可调，点击只跳转原视频时间点，双击或拖入参考帧池才调用手动抽帧接口正式写入关键帧；已写入的胶片显示“已添加”，相同素材、相同密度和时长下会复用内存缓存，避免返回页面时重复扫视频。产品图上传后独立形成产品资产包：自动识别视角、左右/上下/内外侧、结构点、比例和风险，并补缺角度。最终分镜规划按逐句时间轴把文案、主体元素和产品资产汇合；每条分镜默认是左侧“文案 / 场景一句话 / 人物+产品+动作”三字段、右侧横向视频候选轨。客户可直接改中文镜像，前端会调用改写/翻译链路自动优化对应英文主值；单条和整片都可选择生成数量，整片按行排队提交。首尾帧、视觉规划、产品出现方式等细节保留在高级抽屉和后端自动展开逻辑里，不再作为客户默认闸门。

01

### 素材输入

有当前素材任务即通过；输入框只负责创建或切换任务。

02

### 源视频下载

`job.video_url` 存在即通过；`created/downloading` 视为运行中。公开视频默认不带 cookies 下载；只有 TikTok 明确要求登录态时才配置 `YTDLP_COOKIES_FILE`，生产容器禁止使用 `YTDLP_COOKIES_FROM_BROWSER=chrome`。

03

### 音频文案

`audio_script.source_text` 或 `transcript` 逐句时间轴有内容即通过。

04

### 抽帧参考

`job.frames.length > 0` 即通过；参考帧只做主体重构证据。

05

### 主体重构

关键帧里存在 `subject_assets` 即通过；真人、卡通、元素和有文字的自主描述走参考创新，自主描述空文本走源形象锁定。

06

### 产品素材池

`product_refs` 有记录即通过；不限量上传，后续按分镜最多挑 6 张。

07

### 分镜文案

逐句时间轴生成后进入分镜；新口播可单段或整片改写。

08

### 三字段规划

客户默认只编辑文案、场景一句话、人物+产品+动作；高级抽屉保留首尾帧和 6 字段。

09

### 视频候选

每行右侧直接显示横向视频轨，数量可选；新候选一直向右追加，不再用 4-grid 撑高行。

## 源码结构地图

### 前端核心

`web/next.config.mjs` | Next.js 构建配置：静态导出、图片不走优化、禁用开发环境左下角 Next Dev Indicator，并移除 Next 16 已不支持的 `eslint` 顶层配置，避免本地 dev 出现配置 Issue 提示。
`web/app/globals.css` | 全局主题变量、登录页视觉样式、信息流工作台同源品牌 token、ReactFlow 样式引用，以及本地开发态 `nextjs-portal` 遮挡隐藏规则。工作台在 `skg-board-theme` 内定义 `--skg-gold-1`、`--skg-gold-2`、`--skg-cream`、`--skg-bg-*`、`--skg-text-*`、`--skg-radius-*` 和按钮阴影等变量，并新增 `skg-board-brand`、`skg-stat-card`、`skg-primary-action`、`skg-secondary-action`、`skg-empty-state` 等样式。暗色工作台复用登录页金色聚焦、米白主按钮和弱暖光氛围；明亮模式通过 `skg-board-theme--light` 复用同一套结构，改成暖白底、白色 panel、黑底主 CTA 和深色文本，不另起一套界面。
`web/app/page.tsx` | 产品工作台主状态：jobs、activeJobId、生成任务状态；主渲染为全屏素材输入列 + 信息流广告复刻工作表；“开始分析”会把 job 放入并行素材分析队列，下载完成后触发 `triggerTranscribe` 解析音频，并触发 `analyzeJob` 自动抽 12 张参考帧，形成“音频文案路 + 视频视觉路”同步推进；音频失败时会忽略失败状态下残留的半成品 transcript，允许再次触发音频解析；底部吸附音频条和旧全局浮动主题按钮不再从主界面渲染，避免和工作台内的明暗模式切换重复。
`web/components/ad-recreation-board.tsx` | 信息流广告复刻工作表：顶部先展示与登录页连续的 SKG brand strip，包含 SKG 字标、“未来健康 · 营销内容工作台”和“营销内容工作台 · TK 二创”；右侧素材/任务/视频/文案统计改为米白 stat 卡片，主动作按钮统一走 `skg-primary-action`，次动作走 `skg-secondary-action`，空状态复用 `AnimatedLoginCharacters`。`buildWorkflowSteps` 仍统一生成 01-09 流程顺序、状态和判定依据，`WorkflowStepBadge` / `PipelineLane` / 分镜列标题也继续共用同一套编号；但完整 `WorkflowOrderBar`、右侧素材/视频/音频/文案/参考帧需求 chips、文案依据下拉和“音频文案、抽帧参考、主体重构、产品素材池”四个状态条不再默认渲染在工作区顶部。左侧素材输入只负责链接/上传和任务切换，不再重复放横版原视频预览；右侧源视频工作区直接进入核心操作。讲话人、节奏和背景音分析仍写入 `AudioScript`，但不再作为“音频解析结果”卡片默认渲染；主工作区左侧宽度调整为 430-460px，上方是按 9:16 显示的竖版原视频播放器，播放器内覆盖“当前点抽帧”，按当前播放秒数手动补参考帧，播放器下方是逐句时间轴，英文和中文都最多显示两行；右侧上方是无标题的波形与切点参考框，下方是三栏主体管线。音频波形用参考图式的连续灰色包络显示响度、停顿和密集爆点，顶部把低/中/高密度按钮和当前播放秒数、总时长、鼠标指针停点秒数直接放在波形上方。视频播放时通过 `requestAnimationFrame` 平滑驱动波形播放线，同时同步高亮并滚动当前句；点击音频波形或字幕行会跳转原视频时间。音频波形下方同框渲染无标题的 `TimelineFilmstrip` 临时画面胶片，前端按低/中/高密度从源视频 canvas 截取预览缩略图，并按 `frame.time / duration` 的百分比定位到和波形同一条时间轴上；波形与胶片之间不显示分隔横线，胶片轨道贴近波形，缩略图轻微上下错落并倾斜重叠排列，hover 时用同一张胶片卡在原位置生成固定顶层克隆，约 4.8 倍放大并自动限制在视口内，避免被工作区、滚动容器或相邻面板遮挡；单击胶片只跳转原视频时间，不写入任务数据，双击胶片或拖进参考帧池时才调用手动抽帧并正式加入 `job.frames`，已加入的胶片显示“已添加”；胶片预览按 job、视频、密度和时长缓存，未切换低/中/高时返回页面不重新扫视频。右侧参考帧池的主入口是“自动抽帧 12 张”，一键按动作峰值目标重新抽取 12 张源视频参考帧，优先抓手势、表情变化、节奏点和镜头变化；缩略图按竖版完整比例显示不裁切，点选状态直接叠在参考帧池缩略图上，鼠标停留会通过固定浮层放大展示完整帧。转换层不再暴露“生成 10 张高清图”、透明骨架/真人、完整/常用视图开关、真人/卡通/元素/自主描述卡片、卡通风格下拉或独立数量按钮；现在是“GPT 套件 / Gemini 套件 + 同一参考区 + 开始分析 + 生图对话 + 当前识别摘要 + 生成”的智能体结构，用户把 1-3 张参考帧拖入同一参考区后，在对话里写方向、数量、风格、服装统一和人物占比，后端 `subject-agent/message` 自动更新 `selected_mode`、`quantity` 和英文 prompt。主体元素区按每次生成的套图文件夹显示结果；缩略图上提供“重新生成这一张”和“删除这一张”，单张重生会用 `replace_views=true` 替换同一视角。前端对卡通重构传 `subject_style=cartoon_subject`，其他方向传 `subject_style=source_actor`；形象锁定或自主描述空文本可走 `reconstruction_mode=same`，其他参考创新走 `similar` 并把参考帧作为 `/images/edits` 的 image refs 一起提交。主体生成完成后会形成 `subject_consensus_brief`。音频结果下方是信息流复刻分镜工作台：顶部产品参考区是“同一产品素材池”，不限量上传产品图，不做不同产品身份判断；上传原图推荐长边 1200-2000px、短边至少 600px，但后端会统一生成最长边 1600px、JPEG 92 的 AI 工作副本，并回显尺寸、自动转换和风险标注；上传后按“套在脖子上的 U 形肩颈按摩仪”进行同一产品批量识别，左/右按佩戴者身体左右、上/下按佩戴方向，额外标注内外侧、开口方向、局部结构点、背景类型、用途标签、生成风险和备注，用户只检查备注，鼠标悬停通过固定浮层显示大图预览，能盖过滚动容器和分镜框架；缺视角补图失败时保留重试入口。脚本区在分镜行上方提供“作者想法”和“整片改写”，每行新口播文案可直接编辑并可单段 AI 改写。每条音频分镜默认是左侧三字段、右侧横向视频候选轨；高级区仍保留首尾帧 prompt、产品出现方式和旧 6 字段。`ModelTrace` 会在音频解析、产品识别/补图、主体重构视图包、脚本改写等入口旁直接展示模型名；生图入口会显示 `gpt-image-2 / gemini-3-pro-image-preview` 链路和短时熔断规则，点击后用固定浮层展示模型链路、输入输出和回退逻辑。旧分镜卡、抽帧控制和视频生成组件仍保留在文件里，但当前主路径不渲染。
`SourceSubjectPipeline` | 源视频工作区右侧主体管线主路径：三栏分别是竖向 参考帧池、转换层 和 主体元素。参考帧池保留自动 12 张、胶片拖入正式成帧、点击勾选和删除；参考帧缩略图保持小尺寸固定宽度、`aspect-[9/16]` 和 `object-contain` 显示，hover 预览通过 `MediaAssetTile` 的左侧紧凑浮层显示。转换层取消旧方向卡片、卡通风格下拉和独立数量按钮，改为项目内生图对话智能体：用户先把 1-3 张参考帧拖入同一个参考区，选择 `GPT 套件` 或 `Gemini 套件`，点击“开始分析”后由后端 `subject-agent/analyze` 识别参考图关键特征、生成中文摘要、英文 generation brief、特征 chip、追问和风险提示。GPT 套件表示 GPT 分析/对话 + `gpt-image-2` 生图；Gemini 套件表示 Gemini 分析/对话 + `gemini-3-pro-image-preview` 生图，默认不跨套件偷偷兜底。转换层对话只处理主体生图需求，允许修改形象锁定、卡通重构、创意复刻、自主描述、数量、服装统一、人物占比、保留/删除元素等；后端 `subject-agent/message` 会从对话自动识别 `selected_mode` 和 `quantity`，界面只展示当前识别摘要，不再要求用户点模式卡或数量按钮。对话和分析写入 `Job.subject_agent`，不再把模型选择作为主状态写入 `localStorage`。点击“生成 N 张”仍调用 `generateSubjectAssets`，按当前对话生成的英文 prompt、参考帧、模式和数量提交主体套图。形象锁定走 `reconstruction_mode=same`，其他参考创新走 `similar` 并把参考帧作为 `/images/edits` 的 image refs 一起提交。后端会为每次主体套图注入同一份 pack bible：参考创新模式锁定同一个全新主体和同一套服装，源形象锁定模式锁定参考帧里的可见主体、体态、发型、服装和配色；后处理会裁出白底主体并允许放大到画布高度上限约 96%，实测典型主体有效高度约 90%，避免模型生成“小人 + 大白边”。主体元素区按每次生成的 `pack_id` 组织成“套图文件夹”：顶部展开当前选中套图，下面是可滚动的套图包列表；同一方向可保留多套，生成中按 pack 显示 `2/6` 这类进度，单张完成就替换对应占位卡。缩略图复用 `MediaAssetTile`，支持 hover 放大、单张重生和删除。旧下方 `SourceReferenceBuildPanel` 不再主路径渲染。
`AudioStoryboardPlanPanel` 三字段候选生成 | 当前分镜主路径：每行是左右双栏，左侧默认显示 `skg_copy_*`、`scene_one_line_*`、`action_one_line_*` 三组中英字段，右侧直接显示视频候选横向轨。用户改中文镜像后，字段失焦会通过 `refineStoryboard` 优化对应英文主值，失败时退回 `translateText`；英文仍是后续 prompt 主值。`quickPlanStoryboard` 把三字段和主体 brief 展开为完整 `StoryboardScene`，`generateStoryboardVideo` 的 `count` 可由单行数字控件选择，候选新生成后持续向右追加，不再用 4-grid 撑高每行。整片生成同样可选择每行数量，并以 `concurrency=1` 按行排队提交。产品素材池、批量控制、每行主体区和高级区都可折叠，高级抽屉仍展示旧 6 字段、首尾帧 prompt 和首尾帧资产槽，但客户默认不用先处理首尾帧。
`web/components/resource-library/library-drawer.tsx` | 全局资源中心浮窗：由工作台顶部“资源库”按钮打开，叠加在工作台上方但不阻塞主界面；尺寸、位置和当前 Tab 写入 `localStorage["skg-resource-library-drawer"]`。提示词 Tab 固定 5 列（场景描述、视频描述、主体描述、SKG 文案、产品角度），每列先显示 use_count 排名前 5 的“常用”，再按月份倒序分组；提示词节点常驻复制按钮，hover 可选英文/中文/双语复制，并调用 use 接口。素材 Tab 固定 4 列（主体、产品、场景、视频），节点不可拖动，按月份倒序硬编码排列；“应用到当前 job”只调用后端复制接口，得到普通 `ImageRef(kind="asset")` 后再写入产品素材池或复制 ID。浮窗顶部最近 24 小时横条混合显示提示词和素材；新建提示词、上传素材、删除前查引用、详情侧栏都在该组件内完成。
`AdRecreationBoard` 主题切换 | 顶部指标区左侧有“明亮/暗色”按钮，使用 `Sun` / `Moon` 图标切换 `skg-board-theme--light` 类名，并把选择写入 `localStorage["skg-board-theme"]`。暗色仍是默认模式；明亮模式只改变工作台外观，不改变任务、素材、分镜、模型调用或接口数据。
`SourceReferenceBuildPanel` | 旧的“相似主体 / 主体模板”大面板代码仍保留在文件里，方便以后恢复模板库复用、入库命名和自定义视图选择；但当前源视频工作区主路径已经由 `SourceSubjectPipeline` 承接，不再在页面下方渲染这块，避免和“参考帧池 → 转换层 → 主体元素”重复。
`web/components/media-asset-tile.tsx` | 项目内媒体素材缩略图基底组件：图片、视频、抽帧、产品图、相似主体图、首尾帧和视频候选默认从这里获得统一交互。组件负责缩略图显示、顶层固定浮层 hover 放大、删除按钮、重新生成等操作按钮、忙碌遮罩和图片/视频共用预览，避免每个新板块重复手写不同的媒体交互。hover 预览支持 `previewPlacement` 和 `previewMaxWidth`，参考帧池用左侧紧凑预览避免遮住转换层；画面胶片是例外：为了保持胶片原位浏览，不使用额外弹出预览，只让胶片缩略图自己在轨道内放大。
`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，避免登录面板或输入框遮挡时草地失去鼠标响应。
`web/public/oasis-source/index.html` | 从下载包 `remix-3d-website-the-digital-o` 复制来的原始视觉源码。嵌入登录页时会隐藏 demo 站自己的导航、文字和设置面板，保留原多段滚动背景变化、WebGPU 草场、景深、风动和鼠标交互源码；末端阶段保留，只禁用原 footer 出现时把 canvas 上移的逻辑，避免底部露黑边。
`web/public/skg-logo-black.svg` | 从官网 `https://cn.skg.com/logo-black.svg` 获取的 SKG 官方黑色 SVG 字标；登录页通过 CSS 反相成白色玻璃标识使用，工作台顶部 brand strip 通过米白 logo chip 直接复用。
`web/components/login/animated-login-characters.tsx` | 登录页四个几何动态角色组件：当前嵌入登录框顶部，去掉独立网格背景，保留鼠标眼神跟随、输入、显示密码、错误和成功状态反馈；工作台低密度空状态通过 `AnimatedLoginCharacters` 复用同一品牌角色，不在高密度分镜区堆叠角色。
`web/components/nodes/index.tsx` | 旧 DAG 节点和深度素材面板定义仍保留，当前主界面不再把这些节点挂到画布上。
`web/components/audio-strip.tsx` | 旧底部吸附音频条组件：当前主界面不再渲染，音频文案、翻译、讲话人、节奏和背景音统一在右侧复刻工作表里查看。
`web/components/lightbox.tsx` | 关键帧素材准备面板：清洗、统一主体候选、参考帧网格、六张主体重绘图、每帧去主体场景图、纵向 6 行产品融合镜头工作表和审核。
`web/components/product-library-picker.tsx` | SKG 内置白底产品图库选择器：搜索、品类筛选、预览尺寸，并把库内图片复制为当前 job 的 `asset`。
`web/components/storyboard-bar.tsx` | 顶部分镜编排条：展示选入编排的关键帧，并作为唯一分镜导航。
`web/components/storyboard-workbench.tsx` | 顶部分镜编排条下方的明细区：4 图槽、改造目标、时长、自动保存。
`web/lib/api.ts` | 前端类型和 API client，是前后端数据契约镜像；`RuntimeHealth` / `RuntimeModels` 读取 `GET /health`，把 ASR、翻译、视觉、图像、视频等模型名作为前端模型标注的真源。资源库相关类型包括 `PromptLibraryItem`、`AssetLibraryItem` 和 `AssetLibraryKind`；API client 新增提示词 CRUD/use、素材 CRUD/refs/copy-to-job、最近 24 小时混合列表等函数。

### 后端核心

`api/main.py` | FastAPI 单文件后端：登录会话、状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、原音频转写/翻译、声音与背景音分析、后续口播改写/TTS、文件返回；同时承载全局 `prompt_library` 和 `asset_library` 的磁盘索引、CRUD、删除保护和复制到 job API。
`api/product_library/skg-products` | 内置 SKG 白底产品图库：`manifest.json` 记录从桌面产品图筛出的 gallery 白底图和桌面 4 张产品角度图，`images/` 存 45 张参考图。
`api/character_library/skg-characters` | 内置相似主体形象库：从桌面 5 套策划形象导入，`manifest.json` 记录运动阳光男、都市型男、优雅白领女、运动辣妹、绅士大叔，每套含 7 张透明骨架参考图和一段 `prompt_brief`。相似主体生成时优先使用文字 brief 作为创意方向，避免把内置图作为强参考图复制。
`asset_library/` | 全局素材库目录，和 `jobs/` 平级，不写入任何 job state。四类目录为 `subjects`、`products`、`scenes`、`videos`；每个素材自带 `manifest.json` 和图片/视频文件，`index.json` 只是启动扫描重建出来的缓存。库素材选用到 job 时必须复制文件到 `jobs/<jobId>/assets` 或 `storyboard-videos`，禁止直接保存 library 引用。
`prompt_library/` | 全局提示词库目录，和 `jobs/` 平级；`items/<id>.json` 是 source of truth，`index.json` 是缓存。提示词只存文本和中英镜像，不涉及 `ImageRef`。
`jobs/<jobId>/state.json` | 运行时状态文件，不在源码列表里，但刷新恢复依赖它。
`jobs/<jobId>/audio.wav` | 拆轨得到的原始音频，当前只作为后端分析和后续必要预览的只读文件来源；主界面不再默认渲染底部音频条。
`jobs/<jobId>/frames` | 关键帧 jpg。注意 frame.index 是稳定 ID，不等于数组下标。
`jobs/<jobId>/cleaned` | 清洗后待应用图片。
`jobs/<jobId>/elements` | 元素提取图，多版本命名：`idx_elementId_cutoutId.jpg`。
`jobs/<jobId>/gen` | 关键帧生图结果。

    前端主链路：
    web/app/page.tsx
      -> 信息流广告复刻工作表：web/components/ad-recreation-board.tsx
      -> 开始分析：创建/激活 job → 下载完成后并行触发视频视觉路 analyzeJob 与音频文案路 triggerTranscribe
      -> 后台流程判定：01 素材输入 → 02 源视频下载 → 03 音频文案 → 04 抽帧参考 → 05 主体重构 → 06 产品素材池 → 07 分镜文案 → 08 三字段规划 → 09 视频候选；每步从 buildWorkflowSteps 取判定依据和状态，但默认不渲染完整状态条
      -> 左侧素材输入列 + 源视频工作区（竖版 9:16 原视频播放器放大并内置当前点抽帧，逐句时间轴移到原版视频下方，英文/中文最多两行显示；右侧上方连续响度波形显示当前/总时长/指针停点，波形下方是可调低/中/高密度的临时画面胶片，单击仅跳转、双击或拖入参考帧池才正式选帧，并复用同密度胶片缓存；右侧下方是三栏主体管线：参考帧池竖排、转换层参考创新生成套图、主体元素展示生成结果；旧相似主体 / 主体模板区不再主路径渲染；讲话人/节奏/背景音分析写入数据但不默认显示成卡片）
      -> 信息流复刻分镜工作台：06 同一产品素材池不限量上传 → 自动识别视角 / 背景 / 用途 / 风险 → 人工检查备注 → 07 逐句时间轴 / 原内容 / 新口播文案 → 08 紧凑三字段（文案、场景一句话、人物+产品+动作；可折叠）→ quick-plan 自动展开高级字段 → 单条生成 4 个视频候选 / 收起态迷你缩略条 / 展开态 4-grid / 追加生成 / 选中候选 → 09 整片一键后台批量提交
      -> 底部音频条：不再渲染，音频结果集中到右侧工作表
      -> 旧节点/深度素材面板：web/components/nodes/index.tsx、web/components/lightbox.tsx、web/components/storyboard-workbench.tsx（底层保留，当前不作为主入口）
      -> API 契约：web/lib/api.ts

    后端主链路：
    api/main.py
      -> Job / KeyFrame / KeyElement / StoryboardScene / AudioScript
      -> 下载 / 上传 / 音频提取 / ASR / 翻译 / 声音背景音分析 / 抽帧 / Vision brief / GPT 图像生成 / 产品视角识别 / 分镜保存 / 首尾帧生成 / 后续 Azure OpenAI 配音预留
      -> jobs/<jobId>/state.json + 图片文件落盘

## 界面区域到源码

你看到的区域信息流广告复刻工作表
主要源码 `AdRecreationBoard` in `web/components/ad-recreation-board.tsx`；品牌 token、暖光背景、主/次按钮、stat 卡片和空状态角色样式在 `web/app/globals.css`；状态、轮询和接口回写仍在 `web/app/page.tsx`。
适合怎么描述“登录页进工作台后的品牌条、米白主按钮、金色选中态、明亮/暗色模式、素材输入列、开始分析后的自动下载、音频文案路和视频视觉路怎样并行、后台状态哪些需要隐藏或露出”。
你看到的区域源视频工作区
主要源码 `AudioIntakePanel` / `SourceSubjectPipeline` in `web/components/ad-recreation-board.tsx`；参考帧、转换层参考图和主体元素缩略图复用 `MediaAssetTile`；后端复用 `triggerTranscribe`、`AudioScript`、`analyzeJob`、`addManualFrame`、`deleteFrame` 和 `generateSubjectAssets`。
适合怎么描述“竖版原视频尺寸、逐句时间轴、连续响度波形、临时画面胶片、参考帧池竖排、拖关键帧到转换层、转换层自动生成主体套图、主体元素重生/删除/hover 放大还需要怎么调整”。
你看到的区域信息流复刻分镜工作台
主要源码 `AudioStoryboardPlanPanel`、`ProductReferenceCard`、`MissingProductViewSlot`、`buildAudioStoryboardRows`、`selectProductItemsForRow`、`subjectAssetRefsForPlanning`、`subjectBriefForEndpoint`、`endpointAssetRef`、`buildEndpointFramePrompt`、`buildStoryboardSceneFromAudioRow`、`generateEndpointFrameForRow`、`saveRowStoryboardDraft`、`saveAllStoryboardDrafts`、`EndpointFrameSlot`、`StoryboardVideoSlots` in `web/components/ad-recreation-board.tsx`；产品图、首尾帧和视频候选缩略图统一复用 `MediaAssetTile`，包括顶层 hover 放大和删除入口。产品白底图上传复用 `uploadStoryboardAsset`，视角自动识别调用 `analyzeProductViews`，缺角度自动补图调用 `generateProductAngleAsset`。当前单条/批量按钮只保存规划；首尾帧按钮调用 `generateSceneAsset`，传 `subject_brief` 和端点选择后的 1-2 张 `product_images`，不再传主体图或 contact sheet，再用 `PUT /frames/{idx}/storyboard` 保存 asset 首尾帧引用；首尾帧删除只移除本条规划中的引用，避免继续误用旧资产。语言策略由 `AudioStoryboardRow` 的英文主字段 + `*Zh` 镜像字段承载：`role` 内部是 `hook/pain/proof/solution/cta/bridge`，`buildEndpointFramePrompt` 和 `StoryboardScene` 主值默认英文，中文只用于团队阅读；首尾帧提交前前端 `translateText` 兜底，后端 `_ensure_english` 再兜底。`web/app/page.tsx` 的视频提交回调有暂停保护，旧入口误触也不会请求 `/storyboard/video`。
适合怎么描述“按音频逐句生成产品分镜、每行怎样改写口播、哪几句不需要产品或人物、首帧/尾帧该怎么停、首尾帧是否已经生成并准确、产品素材池识别/补图后的备注是否准确、哪些分镜后续才值得进入单条视频候选”。
你看到的区域三字段候选生成行 / 可折叠视频候选区 / 高级抽屉
主要源码 `AudioStoryboardPlanPanel`、`CompactStoryboardField`、`StoryboardVideoSlots`、`StoryboardVideoPreview` in `web/components/ad-recreation-board.tsx`；前端接口是 `quickPlanStoryboard`、`refineStoryboard`、`batchGenerateAll`、`generateStoryboardVideo(count)` in `web/lib/api.ts`；后端接口和后台线程在 `api/main.py`。
适合怎么描述“默认行只露三字段，产品/批量/三字段/候选/高级能不能折叠，候选是否默认不占大面积，AI 改写是否先预览、生成 4 个视频是否追加、哪个候选被选中、整片批量生成进度和失败重试、首尾帧细节是否只在高级里出现”。
你看到的区域全局资源中心浮窗
主要源码 `LibraryDrawer` in `web/components/resource-library/library-drawer.tsx`；入口、保存到库和应用回写在 `AdRecreationBoard`、`AudioStoryboardPlanPanel`、`ProductReferenceCard`、`EndpointFrameSlot`；前端接口在 `web/lib/api.ts`；后端目录扫描、索引、CRUD、删除保护和复制到 job 在 `api/main.py`。
适合怎么描述“资源库浮窗的尺寸/位置/Tab 记忆、提示词 5 列、素材 4 列、最近 24 小时条、复制提示词、素材应用到当前 job、保存产品/首尾帧/规划 prompt 到库、删除前引用确认、节点不能拖动这些交互要怎么改”。
你看到的区域旧深度素材面板（当前不作为主路径）
主要源码 `FrameLightbox`；按“原图/清洗、主体资产、首尾帧、产品融合、审核”五个页签组织；左侧只放主图/框选画布，但主体资产页左侧改为全部已清洗/已选参考帧网格，首尾帧页左侧显示全部关键帧并可勾选人物/机位参考。主体识别页会显示透明骨架人目标和 Vision 验收分数。清洗页右侧支持一键清洗未处理帧、单张替换清洗版和一键替换全部待应用清洗版；批量替换顺序调用 `applyCleanedFrame`，不新增后端接口。产品融合页左侧是纵向 6 行镜头工作表：顶部选择 5 个内置透明骨架人角色之一，并常驻显示桌面四张真实 SKG 产品角度图；每行只显示已预填场景/产品使用/享受描述、秒数、生成按钮和可横向追加的视频历史结果，产品图和结果视频都支持鼠标停留放大预览。描述词内置 36 条镜头语言模板，按“建立出场、产品入画、佩戴贴合、使用感受、生活延展、收尾记忆”排列，并且会按角色自动改写场景气质、使用动作和享受状态。每行还内置角色参考图调度：例如正面/半身用于出场，侧面/背部特写用于佩戴贴合，半身/背部特写用于收尾产品记忆点。点击“换一组”只刷新 6 行描述词。四张桌面 SKG 产品图是真实产品真源，所选角色 7 张参考图是人物身份参考，生成时分别通过 `copyProductLibraryAsset` 与 `copyCharacterLibraryAssets` 自动写入当前 job；视频 prompt 要求产品作为外置刚性实物合成到后颈外侧，禁止穿模、融进透明身体或重绘产品。不再暴露产品角度槽、产品融合辅助栏、产品图库选择器或首尾帧槽。主体资产页只确认一个统一主体，后端按参考重绘六张纯背景、占满画面的标准站立透明骨架人资产图；首尾帧页保留给旧流程/单独生图，不再是产品融合必填步骤。相关接口包括 `cleanupFrame`、`applyCleanedFrame`、`addElement`、`generateSubjectAssets`、`generateSceneAsset`、`copyProductLibraryAsset` 和 `copyCharacterLibraryAssets`。
适合怎么描述“这一组关键帧如何共同生成一个统一主体包；某张关键帧的水印、去主体场景图、产品融合镜头组和质量风险应该如何审核”。
你看到的区域旧分镜明细区（底层保留）
主要源码 `StoryboardWorkbench`；保存到 `frame.storyboard`；接口 `PUT /storyboard`。SKG 产品参考区同时支持上传、剪贴板和内置白底产品库。
适合怎么描述“每个分镜需要哪些图片槽、哪些改造说明，哪些 SKG 产品图要作为视频生成参考”。

## 数据模型

### Job

一个视频任务。前端维护多个 `jobs[]`，当前激活的是 `activeJobId`。URL 查询参数会持久化多个 job。

    Job {
      id, url, status, progress, message,
      video_url, source_audio_url, duration, width, height,
      frames: KeyFrame[],
      transcript: TranscriptSegment[],
      audio_script: AudioScript,
      subject_agent: SubjectAgentState,
      storyboard_images?: StoryboardImage[],
      product_refs?: ProductRefStateItem[]
    }

### KeyFrame

关键帧是整个产品的核心单位。`index` 是稳定 ID，手动加帧后不连续，不能用数组下标代替。

    KeyFrame {
      index, timestamp, url,
      description,
      transparent_human_score,
      cleaned_url, cleaned_applied,
      quality_report,
      scene_assets: SceneAsset[],
      elements: KeyElement[],
      storyboard: StoryboardScene,
      generated_images: GeneratedImage[]
    }

### SubjectAgentState

转换层生图对话的项目内记忆。它跟随 `Job` 写入 `state.json`，用于恢复参考帧、模型套件、分析结果、对话、数量和最终英文生图 prompt。

    SubjectAgentState {
      model_bundle: "gpt" | "gemini",
      source_frame_indices: number[],
      analysis?: SubjectAgentAnalysis,
      messages: SubjectAgentMessage[],
      selected_mode: "realistic" | "cartoon" | "elements" | "custom",
      selected_traits: string[],
      requirements_zh,
      generation_prompt_en,
      quantity,
      updated_at
    }

### TransparentHumanFrameScore

透明骨架人主题的抽帧验收结果。只有 `target=transparent_human` 时会在抽帧阶段写入；普通抽帧目标不要求该字段。

    TransparentHumanFrameScore {
      transparent_body_score: 0-25,
      skeleton_visible_score: 0-25,
      human_prominence_score: 0-15,
      clarity_score: 0-15,
      commercial_style_score: 0-10,
      product_usefulness_score: 0-10,
      total_score,
      qualified,
      reject_reason
    }

### KeyElement

从关键帧识别结果里确认出来的主体候选。当前素材准备流程只保留一个统一主体；多张关键帧通过 `source_frame_indices` 作为该主体的参考帧。

    KeyElement {
      id,
      name_zh, name_en, position,
      source: auto | manual | region,
      region,
      cutouts: string[],
      cutout_id,
      subject_kind: object | living,
      subject_assets: SubjectAsset[],
      subject_consensus_brief,
      subject_consensus_brief_zh
    }

### AudioScript

第一步音频解析的结构化产物。`pipeline_transcribe` 提取 `audio.wav` 后先保存原始英文转写、中文翻译、讲话人画像、口播节奏和背景音乐/环境声/音效分析。`rewritten_text` 是英文新口播，`rewritten_text_zh` 只作为团队审稿镜像；`voice_url` 等字段仍保留给后续新配音阶段。

    AudioScript {
      status: idle | rewriting | completed | failed,
      source_text,
      source_zh,
      rewritten_text,
      rewritten_text_zh,
      speaker_profile,
      rhythm_profile,
      background_audio_profile,
      product_brief,
      rewrite_model,
      voice_provider: azure_openai,
      voice_model,
      voice_id,
      voice_url,
      error
    }

### SceneAsset / SubjectAsset

画面工作台素材准备阶段生成的组图资产。实际图片保存在 `jobs/<jobId>/assets`，可作为 `asset` 类型复制到分镜槽位。

    SceneAsset {
      id, label, url,
      width, height, quality, size,
      scene_mode: remove_subject | similar | style,
      scene_style,
      quality_report
    }

    SubjectAsset {
      id, view, label, url,
      background: white | black,
      width, height, size,
      source_frame_indices[],
      status: queued | in_progress | completed | failed,
      progress, error,
      pack_id, pack_label, pack_mode, pack_created_at
    }

`SubjectTemplateItem` 保存用户确认过的主体视图包。`prompt_brief` 是后端从模板图反推的英文文字特征，后续相似生成优先读取它，而不是再次把模板图作为强参考图传给 image-edit；`prompt_brief_zh` 仅用于模板库卡片和团队阅读。

    SubjectTemplateItem {
      id, name, description, note,
      prompt_brief,
      prompt_brief_zh,
      subject_style: transparent_human | source_actor | cartoon_subject,
      primary_image,
      images: SubjectTemplateImage[]
    }

### ProductLibraryItem

内置 SKG 白底图库条目。实际图片保存在 `api/product_library/skg-products/images`，被选中时会复制到 `jobs/<jobId>/assets`，再以普通 `ImageRef(kind="asset")` 进入产品参考组。

    ProductLibraryItem {
      id, handle, title, product_type,
      image_index, filename, url,
      width, height,
      white_score,
      source_path,
      tags[]
    }

### PromptLibraryItem / AssetLibraryItem

全局资源中心的数据模型。提示词库只保存文本和中英镜像，发给模型时使用 `prompt_en`；素材库保存主体、产品、场景和视频四类全局资源。库目录和 job 目录完全平级，索引文件只是缓存，服务启动会扫描目录重建。素材应用到 job 时永远复制文件，返回普通 `ImageRef(kind="asset")` 或 job 内视频引用，不把 `library_*` 引用写入 job state。

    PromptLibraryItem {
      id,
      category: scene_desc | video_desc | subject_desc | skg_script | product_angle,
      name,
      tags[],
      prompt_en,
      prompt_zh,
      use_count,
      source_job_id,
      created_at,
      updated_at
    }

    AssetLibraryItem {
      id,
      kind: subjects | products | scenes | videos,
      name,
      name_zh,
      note,
      tags[],
      source_job_id,
      use_count,
      created_at,
      updated_at,
      is_official,
      prompt_brief,
      prompt_brief_zh,
      subject_style,
      product_type,
      asset_role,
      duration,
      aspect_ratio,
      images: AssetLibraryImage[],
      poster,
      video_url
    }

### ImageRef.asset_meta

产品图上传或从产品图库复制到 job 时，后端会把原图转为统一 AI 工作副本，避免超高清原图拖慢识别、生图和生视频链路。黑底/白底不强行改色；只有透明底会铺白。前端用该字段展示工作图尺寸、自动转换动作和分辨率风险。

    asset_meta {
      standard: "AI工作副本：最长边≤1600px，建议长边≥900px，短边≥600px，JPEG q92",
      original_width, original_height,
      width, height,
      original_bytes, work_bytes,
      max_side, min_long_side, min_short_side, quality,
      actions[],
      warnings[],
      normalized
    }

### ProductViewAnalysisItem

产品素材池识别结果。它不判断不同产品身份，只服务同一款挂脖肩颈按摩仪的生视频选图和方向约束；左/右按佩戴者身体左右，不按图片左右。前端会把上传图、识别标注、AI 补图、备注和删除结果写入 `Job.product_refs`，后端保存到 `state.json`，避免刷新、热更新或服务重启后丢失产品素材池。

    ProductViewAnalysisItem {
      index,
      view: front | left_45 | right_45 | side_thickness | inner_contacts | back_bottom,
      background,
      use_tags[],
      orientation: {
        product_left, product_right,
        top, bottom,
        inner_side, outer_side,
        opening_direction
      },
      landmarks[],
      note,
      risk,
      confidence
    }

    ProductRefStateItem {
      id,
      ref: ImageRef,
      view,
      background,
      useTags[],
      orientation,
      landmarks[],
      note,
      risk,
      source: upload | ai,
      assetMeta,
      confidence
    }

### ProductFusionShot

产品融合镜头组的单行数据。每个关键帧最多 6 行，用户选择一个内置角色后只微调场景/产品使用/享受描述和秒数；四张桌面 SKG 产品角度图会在顶部显式展示为真实产品真源，所选角色 7 张参考图作为人物身份参考，生成时作为 Seedance 参考图提交。

    ProductFusionShot {
      id,
      first_image,
      last_image,
      product_images[4],
      action_text,
      duration,
      image_model: gpt-image-2,
      video_model: seedance,
      // legacy: product_image, person_image, product_region, scene_image, guide_image
    }

### StoryboardScene

分镜编排结果，不是复刻说明。当前主流程里 `first_image`/`last_image` 只接受生成后的 asset 首尾帧；旧 keyframe 首尾帧引用会被前端忽略。`subject_images` 保存相似主体白底视图，`product_images` 保存该行挑选的产品参考。

    StoryboardScene {
      duration,
      visual_mode: person_only | person_product | product_only | environment,
      needs_product,
      needs_subject,
      subject_brief,
      skg_copy_en,
      skg_copy_zh,
      scene_one_line_en,
      scene_one_line_zh,
      action_one_line_en,
      action_one_line_zh,
      selected_video_id,
      first_frame_plan,
      last_frame_plan,
      product_placement,
      first_image,
      last_image,
      product_images[],
      subject_images[],
      subject_image,
      scene_image,
      product_image,
      action_image,
      subject,
      product,
      scene,
      action
    }

## 接口地图

功能 | 接口 | 前端调用 | 说明
--- | --- | --- | ---
网页登录 | `POST /auth/login`、`GET /auth/check`、`POST /auth/logout` | `web/app/login/page.tsx`、Nginx `auth_request` | 登录页提交账号密码到 `/api/auth/login`，后端设置 HttpOnly 会话 Cookie；生产 Nginx 对工作台和 `/api/` 调 `/auth/check` 做统一校验，未登录页面跳 `/login/`，API 返回 JSON 401。
运行配置 / 模型标注 | `GET /health` | `getRuntimeHealth`、`ModelTrace` | 返回 `models`：ASR、`asr_language`、`asr_base_url`、`asr_remote_enabled`、`asr_local_fallback_enabled`、`asr_audio_fallback_enabled`、`faster_whisper`、本机 ASR、ASR fallback、翻译、GPT 改写、GPT 画面理解、产品视角识别 `product_view`、主图像模型 `gpt-image-2`、图片故障兜底 `image_fallbacks`、短时熔断状态 `image_circuit`、主体 6 视图模型链路、Azure OpenAI TTS、视频别名和 Seedance 服务商。当前 `REWRITE_MODEL`、`AUDIO_REWRITE_MODEL` 和 `VISION_MODEL` 默认使用 `gpt-4o`；如果旧环境变量仍写 `gemini-*`，后端会归一化回 `GPT_TEXT_MODEL` / `REWRITE_MODEL`。语音只走 Azure OpenAI TTS，`models.voice_tts_paths` 会回传当前尝试的语音路径，方便区分路径错误和语音服务不可用。前端所有当前主路径里会调用模型的按钮旁显示模型名，点击弹出小窗口查看模型链路和输入输出逻辑；不返回 API Key 或敏感凭证。
历史列表 | `GET /jobs` | `listJobs` | 所有 job 精简列表（id/url/status/thumbnail/mtime…），按 state.json mtime 倒序。前端 URL 无 `?job=` 时拉它回填全部历史；带 `limit` 可截断。
创建任务 | `POST /jobs` | `createJob` | 提交 TK 链接，后台开始下载；前端“开始”队列会在 downloaded 后自动触发音频解析。下载阶段默认不带 cookies；生产环境必须显式保持 `YTDLP_COOKIES_FILE=` 和 `YTDLP_COOKIES_FROM_BROWSER=` 为空，避免容器内误读被打进镜像的开发 `api/.env`。只有 TikTok 明确要求登录态时，才把宿主机 `./secrets/tiktok_cookies.txt` 挂载进容器并设置 `YTDLP_COOKIES_FILE=/run/secrets/tiktok_cookies.txt`。生产容器没有 Chrome cookies 数据库，不能配置 `YTDLP_COOKIES_FROM_BROWSER=chrome`。
重试下载 | `POST /jobs/{id}/download/retry` | `retryJobDownload` | 用于 TK 链接下载失败且没有 `video_url` 的素材；清空错误、重新进入下载状态，并在后台再次执行 `pipeline_download`。上传视频不能重下载，需要重新上传文件。
上传视频 | `POST /jobs/upload` | `uploadJob` | 保存 source.mp4，然后同样进入下载完成状态；当前上传后也加入第一步队列，下载完成后自动解析音频。
删除输入视频 | `DELETE /jobs/{id}` | `deleteJob` | 从任务队列、URL 和磁盘 `jobs/<id>` 目录移除整个 job，包括源视频、关键帧、元素提取图和生成视频。
解析视频 | `POST /jobs/{id}/analyze?frames=&target=&mode=&quality=` | `analyzeJob` | 抽参考帧能力。当前开始流程会在视频下载完成后自动调用一次，默认 `frames=12`、`target=motion`、`quality=accurate`、`mode=replace`，形成全局动作/节奏参考帧池；原版视频旁的“抽参考 12 帧”也会用同一参数显式重跑。`target` 仍支持透明骨架人、综合、清晰主体、转场变化、表情瞬间、动作峰值。
音频文案轨 | `POST /jobs/{id}/transcribe` | `triggerTranscribe` | 若尚未拆轨，先从 `source.mp4` 提取 `audio.wav` 并回填 `source_audio_url`；远端启用时把 `audio.wav` 上传到 `ASR_BASE_URL` 的 OpenAI Audio Transcriptions 兼容接口，用 `ASR_MODEL` 提取原始文案，并传 `ASR_LANGUAGE=en` 降低英文素材延迟。微软官方路径包括 `/openai/deployments/{deployment}/audio/transcriptions?api-version=...` 和 `/openai/v1/audio/transcriptions?api-version=preview`；当前 SKG 网关探测这些路径均未返回可用 ASR，`gpt-4o-transcribe` 返回 `DeploymentNotFound`。当前生产因此复制本地成功策略：`ASR_REMOTE_ENABLED=false`、`ASR_LOCAL_FALLBACK_ENABLED=true`，直接走容器内 CPU 版 `faster-whisper` 生成真实逐句时间轴；`ASR_AUDIO_FALLBACK_ENABLED=false`，避免 Gemini 多模态假字幕。后端会拒绝重复文本、逐秒假字幕或覆盖率过低的结果。中文翻译由 `TRANSLATE_MODEL` 按 ASR 段落补齐，失败时保留原文时间轴且中文可为空。再用 `ASR_FALLBACK_MODEL` 读取 `audio.wav` 和已有转写时间轴，多模态音频分析讲话人、语速节奏、停顿、背景音乐/环境声/音效，写入 `speaker_profile`、`rhythm_profile`、`background_audio_profile`；若模型分析失败，则用转写段落、时长和语速做本地估算兜底。当前第一步不默认生成 SKG 新口播和 Azure OpenAI 配音。失败后只要后台 worker 不在运行，就允许重新触发；前端也不再把失败状态下残留的半成品 transcript 当成音频完成。
分镜脚本改写 | `POST /jobs/{id}/script/rewrite` | `rewriteStoryboardScript` | 根据原英文参考文案、当前英文新口播、英文 role enum、时间段和作者想法改写英文口播；作者想法若含中文，后端会先经 `_ensure_english` 兜底翻译。`mode=segment` 只改一段；`mode=all` 一次改完整片，要求整片前后连贯。后端按 `AUDIO_REWRITE_MODEL`、`ASR_FALLBACK_MODEL`、`TRANSLATE_MODEL` 依次尝试，全部失败时用英文本地模板保留可编辑文案。接口返回 `items[index,text,text_zh]`，其中 `text` 是写入模型链路的英文主值，`text_zh` 只供团队审稿镜像显示；点击保存规划后写入 `StoryboardScene.action`。
原始音频文件 | `GET /jobs/{id}/audio.wav` | `sourceAudioUrl` | 返回拆轨得到的 wav；当前主界面不再渲染底部吸附音频条，右侧复刻工作表会读取该文件生成参考图式横向响度波形，并和原视频、逐句时间轴联动；波形标题栏显示当前播放秒数、总时长和鼠标指针停点秒数。
改写配音文件 | `GET /jobs/{id}/audio-script.mp3` | `apiAssetUrl(job.audio_script.voice_url)` | 后续新配音阶段保留的 TTS 产物；服务端固定走 `VOICE_PROVIDER=azure_openai`，通过 `AZURE_OPENAI_BASE_URL` 的 OpenAI 协议生成 mp3，并按 `AZURE_TTS_PATHS` 依次尝试 `/audio/speech`、`/v1/audio/speech` 等路径。当前第一步不默认生成该文件。
手动加帧 | `POST /jobs/{id}/frames?t=` | `addManualFrame` | 按视频时间戳抽一帧，index 递增但 frames 按 timestamp 排序。当前主界面会把原版视频播放器的播放秒数传给 `AudioIntakePanel` 标题栏右侧的“当前点抽帧”；胶片缩略图双击或拖入参考帧池也调用同一接口，成功后胶片显示已添加。
删除参考帧 | `DELETE /jobs/{id}/frames/{idx}` | `deleteFrame` | 删除单张抽帧参考帧并清掉对应选择态；当前主界面每张缩略图右下角提供删除入口，方便手动抽错后直接修正。接口返回状态消息必须称为“参考帧/关键帧”，不能写成“分镜”，避免和逐句 storyboard 行混淆。
Vision 识别 | `POST /frames/{idx}/describe` | `describeFrame` | 写入 frame.description，后续可从 objects 加候选元素。
清洗水印 | `POST /frames/{idx}/cleanup` | `cleanupFrame` | 支持全图和区域清洗，生成 cleaned 待应用版本；前端批量清洗会顺序调用该接口，不自动覆盖原图。单帧清洗状态按 frame.index 隔离，清洗某一张不会禁用其他关键帧的清洗按钮。
应用清洗版 | `POST /frames/{idx}/cleanup/apply` | `applyCleanedFrame` | 把 cleaned 待应用版本覆盖到原关键帧，并保留首次原图备份；前端“一键替换待应用”会顺序调用该接口应用所有已有清洗版。
应用清洗 | `POST /cleanup/apply` | `applyCleanedFrame` | 物理覆盖 frames/{idx}.jpg，并备份原图。
元素增改删 | `POST/PATCH/DELETE /elements` | `addElement/updateElement/deleteElement` | 让用户修正 Vision 错误，避免候选结果锁死。
元素提取 | `POST /elements/{element_id}/cutout` | `cutoutElement` | 调用图像模型生成独立白底素材图，每次累积一张 cutout。
转换层生图智能体 | `POST /jobs/{id}/subject-agent/analyze` `POST /jobs/{id}/subject-agent/message` | `analyzeSubjectAgent` `sendSubjectAgentMessage` | 项目内主体生图对话状态入口。`analyze` 接收当前转换层同一个参考区里的参考帧和 `model_bundle=gpt/gemini`，调用对应套件的视觉模型输出中文摘要、英文 generation brief、特征 chip、追问和风险提示，并写入 `Job.subject_agent.analysis`。`message` 只处理主体生图需求，把用户对方向、数量、风格、服装统一、人物占比、形象锁定/创意复刻、保留/删除元素的自然语言改成 `selected_mode`、`quantity`、`requirements_zh` 和英文 `generation_prompt_en`。GPT 套件后续生图用 `gpt-image-2`，Gemini 套件后续生图用 `gemini-3-pro-image-preview`。
主体资产包 | `POST /elements/{element_id}/subject-assets` `DELETE /elements/{element_id}/subject-assets/{asset_id}` | `generateSubjectAssets` `deleteSubjectAsset` | 根据转换层同一个参考区和对话状态重新绘制一个统一主体资产包；前端不再拆成多个入口分别管理参考帧，只把最多 3 张参考帧、对话识别出的 `selected_mode`、数量和英文 prompt 提交给生成接口。当前源视频工作区使用 `subject_style=source_actor` 承接形象锁定、创意复刻和自主描述，使用 `subject_style=cartoon_subject` 承接对话识别出的卡通重构；旧 `transparent_human` 仍为兼容类型但不是当前转换层默认入口。`reconstruction_mode=similar` 是参考创新路径：后端先用 `VISION_MODEL` 把关键帧反推成主体 brief；只要有参考帧，就把这些帧作为 `/images/edits` 的 image refs 一起提交，日志会显示 `endpoint=/images/edits` 和 `image_refs>0`，不再偷偷降级为纯文字生图。卡通重构在后端额外加入原创卡通/插画主体约束，明确不输出真实人物复制 likeness。生成完成后，后端会把生成视图反推/写入 `KeyElement.subject_consensus_brief`，作为后续首尾帧的唯一主体身份文字依据。`reconstruction_mode=same` 是源形象锁定路径：自主描述空文本或对话要求形象锁定时可使用该路径，后端把参考帧作为 primary visual evidence，尽量保留同一可见主体、体态、发型、服装和配色。每个 `view` 单独调用一次生图，明确禁止多视图拼图、contact sheet、多主体、多面板、标签或对比排版。单次图片请求受 `IMAGE_REQUEST_TIMEOUT_SECONDS` 控制，默认 60 秒；`gpt-image-2` 超时、429、5xx、DNS 或连接失败时可兜底 `gemini-3-pro-image-preview`，连续 2 次主模型上游类失败后 600 秒内短时熔断。仅当 `image_model_preference=auto` 时才启用兜底和熔断；用户显式选择 GPT 或 Gemini 时只走所选模型，方便已知某个上游不可用时直接切换。主体同一套图内一旦触发 Gemini，后续视图沿用 Gemini，避免风格混杂和重复等待主模型超时。主体 prompt 会要求从参考图继承性别、人种/肤色、年龄体态和角色气质等广义特征，但生成同一个全新主体；多视图必须保持同一脸部设定、发型、体态、服装类型、配色、材质、剪裁和配饰，不允许每个视角换衣服。后端新增 pack bible 固定字段，把主体、发型、肤色、体态、服装、鞋、配饰和禁止换装项注入每个视角；`_normalize_asset_image(fill_subject=true)` 裁白边后会按目标画布放大主体，而不是只用 `thumbnail()` 缩小，目标是让全身主体占画布高度约 88-94%。后端不再要求整包全成功才写入：单个视图失败时会保留已成功生成的主体图，返回“部分生成完成”，只有一张都没生成出来才返回错误。`replace_views=true` 时会替换同一视角旧图；删除接口会移除对应 subject asset 记录并删除本地 jpg 文件。
主体套图状态 | `SubjectAsset.status` `pack_id` | `web/app/page.tsx` `SourceSubjectPipeline` | `generateSubjectAssets` 现在先写入同一个 `pack_id` 下的 queued 占位卡并立即返回，后台按视角逐张生成，单张完成就把该占位替换成 completed 图片。前端轮询会把 queued / in_progress 主体资产纳入运行状态；主体元素区按 pack 显示套图文件夹，点击某个文件夹后展开该套图，其他套图顺位进入下方可滚动列表。
首尾帧资产 | `POST /frames/{idx}/scene-asset` | `generateSceneAsset` | 同一接口兼容旧场景图和新首尾帧；当前信息流复刻流程传 `asset_role=first_frame/last_frame`、`subject_brief` 和最多 1-2 张 `product_images`。首尾帧不再传主体图、不再把主体图和产品图拼成 contact sheet；主体只走文字 brief，允许新动作、新景别、新表情和新环境。若本条需要产品，后端只把产品参考图作为 `gpt-image-2` image-edit 的硬视觉真源；若不需要产品，则走纯文字生图。关键帧只作为行数据承载位置。生成结果保存在 `scene_assets`，前端再写入 `StoryboardScene.first_image/last_image`。
产品图库 | `GET /product-library/skg` | `listProductLibrary` | 读取内置 SKG 白底图库 manifest，返回产品标题、品类、尺寸、白底评分和预览图 URL。
产品图入库到 job | `POST /jobs/{id}/assets`、`POST /jobs/{id}/assets/product-library` | `uploadStoryboardAsset`、`copyProductLibraryAsset` | 上传产品图或把内置产品图库条目复制为当前 job 的普通 asset。后端统一生成最长边 1600px、JPEG 92 的 AI 工作副本，透明底铺白，过大/过小图片会在 `ImageRef.asset_meta` 里返回转换动作和风险；黑底/白底背景本身不强行转换。注意该接口只写图片文件，产品素材池列表另由 `PUT /jobs/{id}/product-refs` 持久化。
产品素材池保存 | `PUT /jobs/{id}/product-refs` | `saveProductRefs` | 把当前 job 的产品素材池列表、识别视角、用途标签、方向、结构点、备注、AI 补图和删除结果保存到 `Job.product_refs` / `state.json`。前端上传、识别完成、补角度、编辑备注和删除时都会同步保存；刷新页面或热更新后从 job 恢复，不再要求重新上传和重新识别。
产品视角识别 | `POST /jobs/{id}/assets/product-views/analyze` | `analyzeProductViews` | 读取同一产品素材池，按批次把多张图一次性提交给 `PRODUCT_VIEW_MODEL=gpt-image-2` 做视角标注，不限制只看前 6 张；识别对象被固定为套在脖子上的 U 形肩颈按摩仪。返回 `view`、`background`、`use_tags`、`orientation`、`landmarks`、中文备注、生成风险和置信度；`orientation` 明确佩戴者左/右、上/下、内外侧和开口方向对应图中哪边，避免把图片左右误当产品左右。批量识别失败会按单图重试，仍失败或文件缺失时写入本地默认视角，并在 `risk`/`note` 标明兜底原因。前端不再要求用户手动选择视角，也不做不同产品身份判断。
产品缺角度补图 | `POST /jobs/{id}/assets/product-angle` | `generateProductAngleAsset` | 用当前同一产品素材池作为参考，通过 `gpt-image-2` 自动补全缺失视角，输出新的 `ImageRef(kind="asset")`。前端不再固定传第一张图，而是按目标视角给已上传/已标注参考图打分，优先选择真实上传图、目标相邻视角、侧厚/触点/底部对应用途标签和低风险高置信图，最多传 6 张；后端通过 `/images/edits` multipart 的多张 `image[]` 直接提交给主模型，不再把参考图拼成一张板，降低模型误解成拼图/多产品的概率。Prompt 会约束白底产品图、左右非对称、厚度、内侧触点和肩颈真实佩戴比例，并禁止输出拼图/多产品；遇到上游 429 / saturated、5xx、超时或网络错误会按熔断规则兜底 `gemini-3-pro-image-preview`；400/401/403/404 和参数错误不兜底。
角色库 | `GET /character-library/skg` | `listCharacterLibrary` | 读取内置 5 个透明骨架人角色 manifest，每个角色含正面、左右 45 度、侧面、背面、半身近景和背部特写 7 张参考图，以及用于相似主体文字生图的 `prompt_brief`。
主体模板库 | `GET /subject-templates` `GET /subject-templates/images/{filename}` `POST /jobs/{id}/subject-templates` | `listSubjectTemplates` `subjectTemplateImageUrl` `saveSubjectTemplate` | 数据库化可复用主体库。前端模板库展示这里保存的主体模板；“保存为主体模板”会把当前 job 的相似主体白底视图按名称、备注、主体类型、原 job/frame/element 和 asset 列表复制到 `JOBS_DIR/_subject_templates`，并由后端用 Vision LLM 从这些图反推 `prompt_brief`。以后相似生成通过 `subject_template_id` 读取这个 brief 作为文字创意方向，不再把模板图直接上传给 image-edit。
全局提示词库 | `GET /prompt-library` `GET /prompt-library/{id}` `POST /prompt-library` `PATCH /prompt-library/{id}` `DELETE /prompt-library/{id}` `POST /prompt-library/{id}/use` | `listPromptLibrary` `createPromptLibraryItem` `usePromptLibraryItem` `deletePromptLibraryItem` | 浮窗提示词 Tab 的 5 类文本资源。`prompt_en` 是实际复制/提交给模型的英文主值，`prompt_zh` 只给团队阅读；点击复制会调用 `/use` 增加使用次数。节点位置由前端按“常用 + 月份倒序”硬编码排列，不接受拖拽或自定义排序。
全局素材库 | `GET /asset-library/{kind}` `GET /asset-library/{kind}/{id}` `POST /asset-library/{kind}` `PATCH /asset-library/{kind}/{id}` `GET /asset-library/{kind}/{id}/refs` `DELETE /asset-library/{kind}/{id}?force=true` `POST /asset-library/{kind}/{id}/copy-to-job/{job_id}` `GET /asset-library/{kind}/{id}/file/{filename}` | `listAssetLibrary` `createAssetLibraryItem` `getAssetLibraryRefs` `deleteAssetLibraryItem` `copyAssetLibraryToJob` | 素材库四类 `subjects/products/scenes/videos`。应用到当前 job 时后端复制文件到 `jobs/<jobId>/assets` 或 `storyboard-videos` 并增加 `use_count`，前端只写普通 job 内引用。删除前必须先查 `/refs`；被 job 引用时不带 `force=true` 返回 409，强删会把库目录移动到 `_trash/asset_library`。
最近资源 | `GET /resource-library/recent?hours=24` | `getResourceLibraryRecent` | 资源中心顶部最近 24 小时横条，混合返回提示词和素材节点。它只做快速定位和新资源提醒，不改变提示词/素材两套库的独立数据边界。
角色图入库到 job | `POST /jobs/{id}/assets/character-library` | `copyCharacterLibraryAssets` | 把所选角色的 7 张参考图复制为当前 job asset，返回 `subject_images`，产品融合生成视频时作为人物身份参考图提交。
产品融合引导图 | `POST /jobs/{id}/product-fusion/guide` | `createProductFusionGuide` | 旧流程兼容接口：读取产品图和白底人物图，按 `product_region` 合成位置引导图。当前内置角色 + 产品 + 描述流程不再主动调用它。
产品融合描述词 | `POST /jobs/{id}/product-fusion/descriptions` | `generateProductFusionDescriptions` | 兼容接口：可生成产品融合动作描述库。当前前端默认直接用本地 36 条镜头语言模板预填 6 行镜头，并通过“换一组”按钮按 6 条一组轮换。
分镜保存 | `PUT /frames/{idx}/storyboard` | `updateStoryboard` | 保存三字段中英镜像、选中视频 ID、4 图槽、时长、改造说明，以及高级抽屉里的镜头类型、人物描述、人物/产品开关、首帧规划、尾帧规划和产品出现方式。当前音频分镜行会额外写 `storyboard_row_idx`，避免多条分镜共用同一参考帧时互相覆盖。
三字段自动展开 | `POST /jobs/{job_id}/frames/{idx}/storyboard/quick-plan` | `quickPlanStoryboard` | 输入 `skg_copy_*`、`scene_one_line_*`、`action_one_line_*` 和 `subject_brief`，用 `REWRITE_MODEL` 展开为完整 `StoryboardScene`，只作为视频 prompt 来源，不直接持久化。
AI 改文案 | `POST /jobs/{job_id}/frames/{idx}/storyboard/refine` | `refineStoryboard` | 输入当前三字段和中文反馈，返回新的三字段中英镜像。前端必须先弹改前/改后预览，用户点应用后才写入行状态。
单条视频候选生成 | `POST /jobs/{job_id}/frames/{idx}/storyboard/video` | `generateStoryboardVideo` | 新增 `count`、`seed` 和 `storyboard_row_idx`，默认一次创建 4 个 `GeneratedVideo` 任务并立即返回 job；每个候选独立排队、生成、失败或成功。前端提交 prompt 前用 quick-plan 展开，高级首尾帧存在时继续带上，不存在时后端用参考帧/主体图/产品图透明兜底。视频候选显示必须优先按 `storyboard_row_idx` 归属到音频分镜行，而不是只按 `frame_idx`。
整片一键生成候选 | `POST /jobs/{job_id}/storyboard/batch-generate-all` | 当前主路径改为逐行调用 `generateStoryboardVideo` | 用户选择“每行 N 条”后，前端按音频分镜逐行提交，确保每个候选都带 `storyboard_row_idx`。后端批量接口保留为兼容能力，默认 `concurrency=1`，但当前 UI 不再用它做主路径。
生图 | `POST /frames/{idx}/generate` | `generateImage` | 基于关键帧或已选生成图做 image-to-image，目前可用。

## 节点职责边界

节点 | 当前职责 | 不该承担 | 改动主要文件
--- | --- | --- | ---
复刻工作表 | 承载当前第一步主路径：素材输入列按文件任务管理素材；点击“开始”后自动下载源视频，下载完成后触发音频提取、原文案转写、中文翻译、讲话人/节奏/背景音分析和抽帧参考；讲话人/节奏/背景音作为后台数据保留，不默认占用主界面。 | 不要在当前开始流程里自动抽帧、自动写分镜、自动生成元素或自动合成视频；不要恢复右侧空白画布占位。 | `web/components/ad-recreation-board.tsx`、`web/app/page.tsx`
旧节点 / 深度素材面板 | `InputNode`、`VisualLabNode`、`AudioNode`、`ComposeNode`、`FrameLightbox` 等底层能力暂保留，避免本次大改同时破坏抽帧、音频、素材处理和历史 job 数据。 | 不要作为当前用户主路径展示；后续迁移时按看板工作流重新整理。 | `web/components/nodes/index.tsx`、`web/components/lightbox.tsx`、`web/components/storyboard-workbench.tsx`
音频条 | 复刻工作表顶部触发音频解析；全文文案依据和音频解析结果摘要不再默认渲染；主展示以源视频工作区为准：竖版原视频在左，逐句时间轴在原视频下方，音频波形和参考帧池在右；底部 `AudioStrip` 当前不渲染。 | 当前第一步不要默认展示底部音频条、新配音播放器、独立原文案提取大卡片，或把未生成的 Azure OpenAI 配音当作已完成结果。 | `web/components/audio-strip.tsx`、`pipeline_transcribe`、`AudioScript`
候选片段 | 当前分镜主路径的视频候选结果：单条可选择生成数量，候选在每行右侧横向持续追加，支持选中最终视频、重生/删除/清空候选；整片一键按每行数量排队提交。 | 不要要求客户先手动生成首帧/尾帧；不要把 prompt 全文塞进默认候选区，除非用户展开高级。 | `/storyboard/video`、`generated_videos`、`AdRecreationBoard`

## 当前已通与阻塞

### 已通

- TK 链接 / 上传创建 job。
- 视频下载或本地保存；后端会检测可用 ffmpeg/ffprobe，PATH 版本不可用时可 fallback 到本机静态 ffmpeg，避免 Homebrew 动态库损坏导致素材输入失败。
- 手动按时间戳加关键帧。
- 关键帧清洗水印，全图或区域清洗。
- Vision 识别关键帧，输出 scene、objects、style、suggested_prompt，并作为主体候选来源。
- “开始”会在下载完成后自动触发音频处理，不再默认自动抽帧、Vision 扫描或保存分镜初稿。
- 主体候选确认、改名、删除和主体资产包生成能力保留在底层旧面板和接口中，当前第一步主界面不主动展示。
- 分镜工作台 4 图槽和改造说明自动保存。
- 音频文案轨：点击开始或提取音频后提取原文案、中文翻译、讲话人、语速节奏、背景音乐/环境声/音效；结果集中在右侧工作表展示。
- GPT Image 生图；当前 `IMAGE_MODEL` 和主体 6 视图链路默认使用 `gpt-image-2`，单次图片网关请求默认 60 秒超时；主模型超时、429、5xx 或网络错误时允许 `gemini-3-pro-image-preview` 兜底，并有 2 次失败 / 600 秒短时熔断。
- 三字段分镜候选生成：默认行左侧露文案、场景一句话、人物+产品+动作，右侧直接展示横向视频轨；中文镜像失焦后会自动优化英文主值；支持 AI 改写预览、单条选择数量生成、追加生成、选中候选和整片按行排队提交。
- 全局资源中心：提示词库和素材库可从顶部“资源库”打开；提示词可复制并计数，素材应用到 job 时会复制成本 job 内普通 asset。

### 阻塞 / 占位

- ASR：优先走当前 OpenAI-compatible 音频转写入口；如果该网关没有 `/audio/transcriptions`，自动 fallback 到 `ASR_FALLBACK_MODEL`（默认 `gemini-2.5-flash`）的多模态音频识别。
- Voice：当前语音通道固定是 `VOICE_PROVIDER=azure_openai`，通过 `AZURE_OPENAI_BASE_URL=https://ai.skg.com/azure` 的 OpenAI 协议生成 TTS；后端按 `AZURE_TTS_PATHS` 依次尝试路径。第一步暂不默认调用。
- Audio Product Brief：默认是通用 SKG 放松产品卖点；当前第一步只保留配置，后续分镜/新配音阶段再使用。
- Video Gen：当前视频通道固定优先 Seedance；`VIDEO_API_BASE_URL=https://ai.skg.com/doubao` 走 content JSON 异步任务，提交后写入候选片段并轮询到完成。
- Compose：还没做本地 ffmpeg 字幕/TTS 合成。

最重要的产品判断：当前先把“链接/上传 → 下载 → 音频原文案与声音背景音分析”跑顺；视觉抽帧、分镜和视频生成不要再反过来挤进第一步。

## 需求描述模板

### 改复刻工作表

“我在素材输入列或右侧复刻工作表，开始后下载、转写、翻译、讲话人/节奏/背景音、分镜行和生成结果哪些状态要怎么展示。”

### 改音频字段

“每条音频解析结果需要哪些字段，例如原文案、中文翻译、说话人、语速、停顿、BGM、环境声、音效、置信度。”

### 进入下一步

“音频解析完成后，什么时候才进入抽帧、分镜规划、产品融入、关键元素 6 视图或视频生成。”

### 改数据/接口

“这个动作需要持久化到 state.json，字段加在 Job/KeyFrame/KeyElement/StoryboardScene 哪一层，刷新后要恢复。”

### 改工作区语义

“这个工作区的业务职责要改，不只是 UI 文案；请同步更新标题、说明、可点击行为、状态推导和本源码解析页。”

## 变更记录

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

### 2026-05-20 · 转换层方向和数量并入对话

UI API Workflow

问题：转换层已经是生图智能体，但界面仍保留四个方向卡片、卡通风格下拉和数量按钮，用户需要在“对话”和“控件”之间来回确认，违背“模糊需求通过对话收口”的目标。

改动：`SourceSubjectPipeline` 删除方向卡片和独立数量控件，只显示当前识别出的方向与张数摘要；用户在对话里写“形象锁定 / 卡通重构 / 创意复刻 / 自主描述”和“生成几张”，后端 `subject-agent/message` 会解析并更新 `selected_mode`、`quantity`、中文需求和英文生成 prompt。

影响：数量、方向和风格以后都通过转换层对话完成；点击“生成 N 张”时使用对话状态，不再要求用户点卡片或另选数量。卡通风格若在对话里说明，会进入英文 prompt，不再被前端默认 3D 风格硬覆盖。

### 2026-05-20 · 转换层改为项目内生图对话智能体

UI API Workflow

问题：旧多方向卡片加 textarea 的转换层不适合“参考图先分析、再边聊边确定生图需求”的模糊决策流程；同时 GPT/Gemini 切换必须成套影响分析对话模型和生图模型，不能只切图片模型。

改动：`Job` 新增 `subject_agent` 状态，保存当前项目的模型套件、参考帧、AI 分析、对话消息、选中方向、特征 chip、数量和英文生成 prompt。后端新增 `POST /jobs/{job_id}/subject-agent/analyze` 与 `POST /jobs/{job_id}/subject-agent/message`；`SourceSubjectPipeline` 的转换层改成“GPT 套件 / Gemini 套件 + 参考图 + 开始分析 + 生图对话 + 数量 + 生成”结构。选 GPT 时分析/对话走 GPT、图片走 `gpt-image-2`；选 Gemini 时分析/对话走 Gemini、图片走 `gemini-3-pro-image-preview`。

影响：转换层不再把生图模型偏好写入浏览器全局或 job-scoped `localStorage` 作为主状态；当前项目的生图记忆跟随 `state.json`。用户可以在对话里改“生成几张、保留什么、删除什么、人物放大、服装统一、形象锁定/创意复刻/卡通/自主描述”，确认后仍复用 `generateSubjectAssets` 逐张生成并进入右侧主体元素套图文件夹。

### 2026-05-20 · 转换层参考帧改为项目隔离和图像参考生图

UI API Workflow

问题：转换层提示词记忆和生图模型选择用全局 `localStorage` key，切换不同项目时会带入上一项目的偏好；同时 `reconstruction_mode=similar` 虽然提交了参考帧，但最终走纯文字 `/images/generations`，导致不同项目容易生成同一套泛化人物。

改动：`SourceSubjectPipeline` 把主体提示词记忆和生图模型偏好改为按 `job.id` 存储；自主描述为空且已拖入参考帧时，前端切到 `reconstruction_mode=same` 并提交源形象锁定 prompt。`generateSubjectAssets` 对有参考帧的 `similar` 路径先生成 source brief，再把参考帧作为 `/images/edits` 的 image refs 一起提交；`same` 路径使用源形象 pack bible，锁定参考帧中的可见主体、体态、发型、服装和配色。

影响：不同项目之间不会再共享转换层提示词 chip 或模型选择；真人/卡通/元素重构仍是参考创新，但参考帧会真正进入生图请求；自主描述不写字时表示按拖入参考帧复刻同一主体，而不是随机生成新人。

### 2026-05-20 · 主体 6 视图增加 pack bible 和主体占比放大

API Workflow

问题：Gemini 显式生图时，6 个视角是 6 次独立 `/images/generations` 请求，容易每张自行脑补服装；模型也可能输出“小人 + 大白边”，即使最终文件是 2048 高也显得主体很小。

改动：`generateSubjectAssets` 在每套主体图中注入同一份 pack bible，固定同一新主体、发型、肤色、体态、服装、鞋、配饰和禁止换装项；全身视图 prompt 明确要求主体占画布高度 88-94%。`_normalize_asset_image(fill_subject=true)` 裁出白底主体后改为可放大 resize 到目标画布上限，不再只用 `thumbnail()` 导致小人保持原比例。

影响：显式 Gemini 仍然是逐视角独立生成，但每次调用收到同一份具体主体/服装约束；保存后的主体资产会尽量贴近画布高度，减少大白边。

### 2026-05-20 · 转换层增加模型选择、提示词记忆和主体服装锁定

UI Workflow API

问题：用户已经知道某个生图模型不可用时，需要能在转换层直接切换；同时主体 6 视图容易出现不同衣服、不同人设，提示词每次也要重复输入。

改动：`SourceSubjectPipeline` 新增自动 / GPT / Gemini 三档生图模型选择，当时偏好写入全局 `localStorage["skg:subject-image-model:v1"]`，后续已改为当前 job 作用域；提示词输入当时保存到全局 `localStorage["skg:subject-prompt-memory:v1"]`，后续也已改为当前 job 作用域。后端 `_image_model_candidates` 支持显式模型偏好，`auto` 保留 gpt-image-2 主模型、Gemini 兜底和短时熔断，显式 GPT / Gemini 只走所选模型。

影响：主体重构默认继承参考图里的性别、人种/肤色、年龄体态和角色气质这些广义特征，但生成同一个全新主体；六视图 prompt 强制统一脸部设定、发型、体态、服装类型、配色、材质、剪裁和配饰，避免一套图里每张衣服都不同。

### 2026-05-19 · 生图增加 Gemini 故障兜底和短时熔断

API Reliability Config UI

问题：`gpt-image-2` 当前上层通道会读超时，但完全禁用兜底会导致主体套图和补图无法继续；同时不能把主模型直接改成 Gemini。

改动：`api/main.py` 保持 `gpt-image-2` 为主模型，新增 `IMAGE_FALLBACK_MODEL=gemini-3-pro-image-preview`、`IMAGE_FALLBACK_ENABLED`、`IMAGE_CIRCUIT_FAILURE_THRESHOLD` 和 `IMAGE_CIRCUIT_COOLDOWN_SECONDS`。只有主模型超时、429、5xx 或网络错误时才兜底；400/401/403/404 和参数错误不兜底。连续 2 次主模型上游类失败后，600 秒内直接走 Gemini；主模型成功后自动清空失败计数。主体同一套图内一旦触发 Gemini，后续视图沿用 Gemini。

影响：`/health` 返回 `image_fallbacks` 和 `image_circuit`；`ModelTrace` 显示 `gpt-image-2 / gemini-3-pro-image-preview` 和熔断规则。该变更是故障兜底，不是默认改模型。

### 2026-05-19 · gpt-image-2 请求超时改为快速失败

API Reliability Config

问题：`gpt-image-2` 上游图片网关无响应时，文字生图仍通过 SDK 默认等待，编辑生图也按 120 秒重复尝试；主体 6 视图第一张卡住后，用户侧长时间看不到逐张失败或后续进度。

改动：`api/main.py` 新增 `IMAGE_REQUEST_TIMEOUT_SECONDS`，默认 60 秒；`_image_text_call` 统一改为直接调用 `/images/generations`，`_image_edit_call` 和旧分镜生图也复用同一超时。超时、DNS、连接失败这类传输错误不再盲目重试三轮，会把当前视图标失败并继续处理后续视图。`/health` 回传当前图片超时配置。

影响：当时不改模型，所有图片入口仍固定只使用 `gpt-image-2`；后续已增加 Gemini 故障兜底和短时熔断，但错误仍会明确指向当前 `IMAGE_BASE_URL` 上的主模型通道超时或不可用。

### 2026-05-19 · 主体元素改为套图文件夹并逐张回填

UI Workflow API

问题：主体 6 视图生成一次性等待太久，且多次生成后所有图片平铺会迅速挤满主体元素区。

改动：`SubjectAsset` 新增 `status/progress/error` 和 `pack_id/pack_label/pack_mode/pack_created_at`；`generateSubjectAssets` 先写 queued 占位卡并后台按视角逐张生成。`web/app/page.tsx` 轮询主体资产运行态，`SourceSubjectPipeline` 按 pack 显示套图文件夹，点击文件夹在最上层展开该套，其他套图进入下方可滚动列表。

影响：用户可以连续生成多套真人/卡通/元素/自主描述主体图，不会被平铺图片淹没；生成过程会逐张出现，单张失败不阻塞其他视角。

### 2026-05-19 · 转换层拖入参考不再自动生成

UI Workflow

问题：拖入第一张参考帧就立即开始生成，会打断用户继续补第二、第三张参考帧和填写方向文字。

改动：`SourceSubjectPipeline` 的 `addConversionFrame` 只更新对应重构入口的参考队列和提示，不再调用 `generateSubjectPack`；旧版本曾保留独立生成按钮，用户放好参考后再手动提交。

影响：当前正确操作是“拖入 1-3 张参考帧 → 可写方向文字/选卡通风格 → 点击生成 6 视图”。

### 2026-05-19 · 转换层改为四类主体重构入口

UI Workflow API

问题：旧转换层暴露“透明骨架 / 真人、完整 10 / 常用 4”等生成参数，和当前“参考创新生产套图、避免侵权”的目标不一致；用户更需要把少量参考帧拖到明确方向上，右侧马上看到生成结果。

改动：`SourceSubjectPipeline` 的转换层曾改成多方向入口；文字描述会参与 prompt，卡通重构可选择风格。主体元素区按重构类型分组展示结果。`web/lib/api.ts` 和 `api/main.py` 扩展 `subject_style=cartoon_subject`，后端对卡通主体额外加入原创卡通/插画约束。

影响：后续描述这块应说“把参考帧拖到某个重构方向，生成全新主体 6 视图”，不要再说“抠图”“模仿”“透明骨架/真人开关”或“10 张/4 张选择”。

### 2026-05-19 · 胶片双击加帧和音频失败重试

UI Workflow

问题：胶片只能拖入参考帧池，不能双击快速加入；回到同一素材时胶片会重新扫视频；音频解析失败后如果留下半成品 transcript 或 transcribing 状态，开始队列和解析按钮可能不再真正触发重试。

改动：`TimelineFilmstrip` 支持双击调用 `addManualFrame`，已加入的胶片显示“已添加”；胶片预览按 job、视频、密度和时长做内存缓存，未切换低/中/高时复用已有截图。`web/app/page.tsx` 用音频失败状态排除半成品结果，`api/main.py` 的 `trigger_transcribe` 只按实际 worker 和 `audio_script.status=rewriting` 判定忙碌，失败后可重新提交。

影响：用户可以双击胶片快速选参考帧；返回素材或切回同密度时不重复扫视频；音频失败后可直接点击解析音频或开始分析重试。

### 2026-05-19 · 优化参考帧池预览和多参考转换

UI

问题：参考帧池默认 hover 大图向右弹出，遮挡转换层；竖版缩略图用完整 contain 显示后仍然偏大；转换层拖入多张参考帧后也可能挤占生成控制区。

改动：`MediaAssetTile` 新增 `previewPlacement` 和 `previewMaxWidth`；`SourceSubjectPipeline` 的参考帧池改为左侧紧凑 hover 预览，参考帧池和转换层缩略图固定为约 72-80px 宽，同时保持 `aspect-[9/16]` 和 `object-contain`，转换层参考列表增加滚动上限。

影响：参考帧仍可点击多选、拖入转换层和删除；多张参考会在转换层内滚动，不会把下方生成按钮挤走。

### 2026-05-19 · 右侧改为参考帧池到主体元素管线

UI Workflow

问题：旧下方“相似主体 / 主体模板库”过重，用户实际只想从少量关键帧里挑 1-2 张作为参考，直接生成新的主体套图。

改动：`AudioIntakePanel` 右侧新增 `SourceSubjectPipeline`，把主体流程改为三栏：竖向参考帧池、转换层和主体元素。参考帧池可从胶片正式加帧，也可拖关键帧到转换层；转换层拖入后自动调用 `generateSubjectAssets` 参考创新生成套图，保留透明骨架/真人、完整 10 / 常用 4、统一方向和手动重生；主体元素区展示生成结果并支持单张重生、删除和 hover 放大。

影响：旧 `SourceReferenceBuildPanel` 不再主路径渲染，主体模板库入口从首屏移除；后续描述这里时，应按“参考帧池 → 转换层 → 主体元素”来提需求。

### 2026-05-19 · 逐句时间轴移到原版视频下方

UI

问题：逐句时间轴放在右侧会和波形、胶片、参考帧池抢空间，且单行截断导致文案内容看不全。

改动：`AudioIntakePanel` 把左侧原版视频列调整为 430-460px，并把逐句时间轴放到原版视频下方；时间轴抽成 `TranscriptTimelinePanel`，英文和中文字段由单行 `truncate` 改为最多两行 `line-clamp-2`，时间列收窄为 68px。

影响：视频、字幕、波形播放线仍联动；右侧下方只保留参考帧池。后续描述源视频工作区时，应把“逐句时间轴”理解为原版视频下方的字幕审片面板。

### 2026-05-19 · 音频波形下新增临时画面胶片

UI Workflow

问题：用户通常只需要 1-2 张关键帧，但只靠自动抽帧或当前播放点补帧，浏览大量候选画面不够快，直接抽很多帧又会污染正式关键帧池。

改动：`AudioIntakePanel` 在 `AudioWaveform` 下方同框新增无标题 `TimelineFilmstrip`，前端从源视频临时截取低/中/高密度胶片缩略图，并按 `frame.time / duration` 的百分比定位到和波形一致的横向时间点；低/中/高密度按钮上移到波形上方，波形和胶片之间不再显示分隔横线，缩略图增加轻微上下错落。hover 时关闭额外弹出预览，改为在原胶片坐标生成固定顶层克隆，使用同一张胶片卡放大到约 4.8 倍；当前单击只跳转视频时间点，双击或拖进参考帧池才调用现有手动抽帧入口。

影响：临时胶片不会写入 `job.frames`，只有拖入后才成为正式关键帧；胶片轨道和波形共用同一个无标题框架，基线更贴近波形，并显示同一条当前播放线；胶片 hover 克隆挂到 `document.body`，避免被工作区、滚动容器或相邻面板裁切。后续如果要调摆放密度、倾斜角度、上下错落或放大倍率，改 `FILMSTRIP_DENSITIES`、`FILMSTRIP_TILT_CLASSES`、`FILMSTRIP_VERTICAL_OFFSET_CLASSES` 和 `FILMSTRIP_HOVER_SCALE`。

### 2026-05-19 · 逐句时间轴改为窄版面板

UI

问题：宽屏下逐句时间轴占满右侧剩余空间，表格过宽、阅读距离过长，也挤压源视频拆解区的密度。

改动：`AudioIntakePanel` 给逐句时间轴容器增加桌面最大宽度，约束在 620-680px 范围内；参考帧池、波形、字幕点击跳转和当前句滚动逻辑不变。

影响：时间轴视觉宽度约减半，后续若要再调整只改该容器的 `max-width`。

### 2026-05-19 · 隐藏音频解析摘要卡

UI Workflow

问题：源视频工作区顶部的“音频解析结果”折叠条和讲话人/节奏/背景音三张摘要卡仍占据首屏，和用户当前要看的原视频、波形、参考帧和逐句时间轴重复抢空间。

改动：`AudioIntakePanel` 移除“音频解析结果”details 和三张 `ProfileTile` 摘要卡。`AudioScript` 里的讲话人、节奏和背景音数据仍由后端生成并保留，主界面不再默认展示这组诊断信息。

影响：源视频工作区打开后直接进入原视频、波形、参考帧池和逐句时间轴；需要排查模型分析时再从数据或后续专门详情入口查看。

### 2026-05-19 · 隐藏工作区顶部状态提示条

UI Workflow

问题：源视频工作区顶部同时展示 01-09 流程条、素材/视频/音频/文案/参考帧 chips、文案依据下拉和 03-06 四个状态卡，占用过多首屏空间，用户需要的是直接进入视频、音频文案、抽帧和分镜操作。

改动：`AdRecreationBoard` 不再渲染 `WorkflowOrderBar`，并移除右侧源视频区顶部的需求 chips、文案依据 details 和四个 `PipelineLane` 状态卡。后台状态计算、步骤编号和后续分镜/生成逻辑保持不变。

影响：这些状态仍可作为代码里的判定依据，但默认不在此工作区显现；首屏高度让给真实操作内容。

### 2026-05-19 · 视频候选按音频分镜行隔离

API Video Storyboard

问题：多条音频分镜会映射到同一张参考帧，旧视频候选只按 `frame_idx` 过滤，导致第一行生成的视频也出现在后面共用参考帧的分镜行里。

改动：`StoryboardScene`、`GeneratedVideo` 和 `/storyboard/video` 请求增加 `storyboard_row_idx`；前端显示候选和读取已保存分镜时优先按该行号隔离，旧无行号候选只归到同参考帧的第一条兼容行。

影响：点击某一行生成视频后，只会在该音频分镜行右侧出现候选；整片生成也改为逐行提交，避免候选跨行串位。

### 2026-05-19 · 分镜行改成左文字右视频轨

Storyboard Video UX

问题：三字段和视频候选上下堆叠时，每条分镜一展开就占用大量纵向空间；4-grid 候选区也让长分镜列表很难连续操作。

改动：`AudioStoryboardPlanPanel` 改为每条分镜左侧编辑三字段、右侧直接显示视频候选横向轨。候选生成数量可按单行选择，整片生成也可选择每行数量并按行排队。中文镜像字段失焦后会调用 AI 改写链路优化对应英文主值，失败时退回翻译。

影响：用户可以按行扫文案、按行横向看所有候选，生成新候选会持续向右追加，不再撑高分镜行；英文仍是视频 prompt 主值，中文作为团队编辑入口和镜像。

### 2026-05-19 · 云端音频解析复制本地真实转写路径

API Audio Deploy

问题：本地音频解析成功时实际链路是远端失败后落到 `mlx_whisper`，而生产强制 `ASR_BASE_URL=https://ai.skg.com/azure/v1` + `ASR_MODEL=gpt-4o-transcribe` 且关闭本地兜底。生产探测官方 Azure OpenAI 音频路径 `/openai/v1/audio/transcriptions?api-version=preview` 和 `/openai/deployments/{deployment}/audio/transcriptions?api-version=...` 仍不可用，当前部署名返回 `DeploymentNotFound`。

改动：远端 ASR 请求新增 `ASR_LANGUAGE`，默认 `en`，用于按官方建议降低英文素材延迟；翻译请求也套用 `ASR_TIMEOUT_SECONDS`。生产配置临时改成 `ASR_REMOTE_ENABLED=false`、`ASR_LOCAL_FALLBACK_ENABLED=true`、`ASR_AUDIO_FALLBACK_ENABLED=false`，云端用容器内 `faster-whisper tiny.en` 复制本地“真实本机转写”路径。

影响：音频解析不再卡在不存在的 Azure deployment；当前云端 CPU 实测同一失败 job 的 `audio.wav` 可在约 13.6 秒转出 17 段。等 SKG 网关提供真实 Azure ASR deployment 后，再把 `ASR_REMOTE_ENABLED=true` 并恢复对应部署名。

### 2026-05-19 · 删除抽帧状态文案改为参考帧

API Source Video

问题：用户在参考帧池删除自动抽出来的帧时，后端 `DELETE /jobs/{job_id}/frames/{idx}` 返回的 job message 写成“删除分镜”，让人误以为删掉了逐句分镜。

改动：`delete_frame` 的状态消息改为“已删除参考帧 N”。前端按钮本来就是“删除关键帧”，删除逻辑仍只移除 `job.frames` 里的抽帧参考帧和对应文件。

影响：删除抽帧不会被误报成删除分镜；分镜行和参考帧池在用户提示和文档里继续保持清晰边界。

### 2026-05-19 · 视频候选文案改为生成 4 个视频

UI Storyboard

问题：旧文案里的“抽卡”容易被理解成图片、抽帧或只生成缩略图，不够明确。

改动：前端按钮、候选区标题、Toast、空状态和后端 job message 统一改为“生成 4 条视频 / 4 个视频候选”。接口逻辑不变：`count=4` 表示一次创建 4 个独立 `GeneratedVideo` 视频任务。

影响：用户看到的是“生成候选视频”，不是“抽图片”；后续不再用“张”描述视频候选数量。

### 2026-05-19 · 固化生产 Docker Web 验收

Deploy UI

问题：线上 Web 不是开发态 Next 服务，而是 Docker 内 Nginx 承载的 `next export` 静态产物。只在本地跑 `npm run build` 或 dev server，无法覆盖 Nginx 登录跳转、`/api` 反代、静态资源路径、生产构建参数和镜像内环境污染。

改动：新增 `scripts/verify-prod-docker.sh`，直接在 VPS 的 `skg-marketing-web` / `skg-marketing-api` 容器内检查路由状态、静态包是否残留本地 API 地址、API health、`/app/.env` 是否泄漏，以及 yt-dlp cookies 参数是否被开发环境污染。`RULES.md` 明确 Web 改动部署后必须跑该脚本。

影响：后续前端上线验收以生产 Docker 形态为准；本地 dev 只用于开发预览，不能作为生产适配结论。

### 2026-05-19 · 修正生产 TikTok 下载 cookies 污染

Deploy Source Video

问题：生产 API 镜像把本地开发 `api/.env` 复制进 `/app/.env`，其中 `YTDLP_COOKIES_FROM_BROWSER=chrome` 被 `load_dotenv()` 读入。容器没有 Chrome cookies 数据库，导致公开视频也在下载阶段失败，错误为 `could not find chrome cookies database`。

改动：`.dockerignore` 明确排除 `api/.env`、`api/.env.local`、`api/.env.production`，生产 env 显式保持 `YTDLP_COOKIES_FILE=`、`YTDLP_COOKIES_FROM_BROWSER=` 为空。需要登录态时只允许配置服务器 cookies 文件，不允许在生产容器使用 `YTDLP_COOKIES_FROM_BROWSER=chrome`。

影响：公开视频下载恢复为无 cookies 直连；受限视频仍可通过服务器私有 cookies 文件处理。后续 rsync / Docker build 必须排除本地 `api/.env`，否则开发代理、cookies 或 API 配置会污染生产镜像。

### 2026-05-19 · 分镜工作台折叠化和候选区紧凑化

UI Storyboard

问题：三字段候选生成改造后，候选区默认直接铺开 4-grid，占用每条分镜的大量纵向空间；产品素材池、批量控制、三字段和候选区也缺少统一折叠入口，长列表操作时很难快速扫分镜。

改动：`AudioStoryboardPlanPanel` 新增板块折叠状态：产品素材池、批量控制 / 作者想法、每行三字段、每行视频候选和高级抽屉都可独立收起。视频候选默认不展开；无候选且未展开时不渲染大区域，有候选时只显示横向迷你缩略条和已选 / 生成中状态，点“候选”或候选标题后才展开 4-grid 大预览。

影响：默认工作台从“每条都展示候选面板”改为“行头控制 + 按需展开”。客户仍可一键生成 4 个视频候选、追加生成、选中、删除或清空候选，但长分镜列表不会被空候选槽撑高；高级用户展开高级区时继续看到完整视频候选和首尾帧细节。

### 2026-05-19 · 分镜生成简化为三字段候选生成流

API UI Storyboard

问题：原分镜行把新口播、画面规划、人物描述、首帧、尾帧、产品出现方式和视频槽全部摊开，客户要先理解 6 字段和首尾帧闸门才能生成视频，单条也只能按旧候选逻辑慢慢提交。

改动：默认行改为三字段：文案、场景一句话、人物+产品+动作；每行提供 AI 改写、生成 4 条视频和高级抽屉。高级抽屉保留原 6 字段、首尾帧 prompt 和首尾帧资产槽。候选区改为 4-grid，支持生成中状态、hover 视频预览、选中、追加生成、单条重生、删除和清空。顶部新增整片一键生成候选，默认每条 4 个候选并后台提交。

影响：`StoryboardScene` 新增 `skg_copy_*`、`scene_one_line_*`、`action_one_line_*` 和 `selected_video_id`。后端新增 `quick-plan`、`refine`、`batch-generate-all`，并让 `/storyboard/video` 支持 `count`/`seed`。默认 prompt 仍以英文主值提交，中文只作为镜像显示。

### 2026-05-18 · 新增全局资源中心和复制式跨 job 素材库

API UI Library

问题：主体、产品、首尾帧、视频候选和常用 prompt 都散落在单个 job 里，跨任务复用时容易重新上传、重新生成或误把旧 job 文件当公共引用，后续也缺少删除保护和使用次数记录。

改动：后端新增和 `jobs/` 平级的 `asset_library/` 与 `prompt_library/`，服务启动扫描目录重建索引；提示词提供 CRUD、复制计数和 5 类分类；素材提供主体/产品/场景/视频四类 CRUD、引用检查、强删移入 `_trash/` 和 `copy-to-job`。前端新增 `LibraryDrawer` 浮窗，顶部“资源库”按钮打开；浮窗记忆尺寸、位置和 Tab，提示词按“常用 + 月份”分列，素材按月份分列，节点不能拖动；提示词支持一键复制英文/中文/双语，素材应用到当前 job 时只走复制模式。生产 compose 同步挂载 `/data/asset_library`、`/data/prompt_library` 和 `/data/_trash`，避免容器重建后库文件丢失。

影响：后续保存产品图、首尾帧、主体模板和分镜 prompt 时优先进入资源中心。库素材永远不要直接写成 job 引用，必须通过 `POST /asset-library/{kind}/{id}/copy-to-job/{job_id}` 复制成普通 job asset；删除库素材前必须查 `/refs` 并让用户确认。

### 2026-05-18 · 工作台视觉统一到登录页品牌语言

UI Theme

问题：登录页已经形成 SKG 卡通角色、暖橘光晕、金色聚焦色、米白主按钮和“未来健康 · 营销内容工作台”的品牌承诺，但进入信息流工作台后仍是纯黑高密度界面，主 CTA 和选中态混用 cyan、emerald、rose、violet 等颜色，视觉上像两个产品。

改动：`web/app/globals.css` 把登录页的金色、米白、暖光、8px 圆角、按钮阴影和明暗模式中性色抽成 `skg-board-theme` token，并新增 `skg-board-brand`、`skg-stat-card`、`skg-primary-action`、`skg-secondary-action`、`skg-empty-state` 等复用类。`AdRecreationBoard` 顶部改为 SKG brand strip，右侧统计改成米白 stat 卡片，开始分析、生成主体、整片改写、保存规划等主动作统一为登录页同源按钮；主体模板选中、处理中状态和重点输入焦点收敛到品牌金色，空状态复用 `AnimatedLoginCharacters`。

影响：后续描述工作台视觉时应按“登录页同源 SKG 营销内容工作台”理解，不再把它当成独立黑色工具页；新增图片/视频/表格板块时，主动作优先用 `skg-primary-action`，次动作用 `skg-secondary-action`，选中和聚焦用 SKG 金色，功能色只留给明确成功、等待、失败、信息语义。

### 2026-05-18 · 模型 prompt 语言策略切到英文主值

Prompt UI API

问题：最终产物是英文 TikTok 二创广告，但前端默认分镜规划、首尾帧 prompt 和用户可编辑规划字段里混入中文，导致 `gpt-image-2`、脚本改写和后续视频模型收到中英混杂指令。

改动：`AudioStoryboardRow.role` 改为 `hook/pain/proof/solution/cta/bridge` 英文枚举，UI 仍显示中文角色标签。`buildAudioStoryboardRows`、`buildVisualPlan`、`buildFirstFramePlan`、`buildLastFramePlan`、`buildSubjectDescription`、`buildEndpointFramePrompt` 和 `buildStoryboardSceneFromAudioRow` 的模型主字段改为英文，并新增 `*Zh` 镜像用于团队阅读。首尾帧提交前前端会对含中文 prompt 调 `translateText` 兜底，后端新增 `_ensure_english` 并挂到 `generate_scene_asset`、`generate_subject_assets`、脚本改写和音频分析入口。

影响：发给 LLM / 生图 / 视频模型的主 prompt 默认全英文；中文只作为团队审稿镜像、UI 标签和 toast。`AudioScript` 新增 `rewritten_text_zh`，`KeyElement` 新增 `subject_consensus_brief_zh`，`SubjectTemplateItem` 新增 `prompt_brief_zh`。`POST /jobs/{id}/script/rewrite` 返回 `text` 英文主值和 `text_zh` 中文镜像。

### 2026-05-18 · 首尾帧改为主体 brief + 产品少量硬参考

Prompt API UI

问题：首尾帧旧链路把 5 张主体图和 6 张产品图拼成 contact sheet 再做 image-edit，主体姿态和景别被参考图锁死，模型还容易把拼图布局误认为输出布局。

改动：`KeyElement` 新增 `subject_consensus_brief`；主体视图生成后由 Vision LLM 从 10 张图或模板 `prompt_brief` 写入统一主体 brief。`generateEndpointFrameForRow` 生成首尾帧时只传 `subject_brief` 和最多 1-2 张产品图，不再传 `subject_images`；`generate_scene_asset` 在首/尾帧里只对产品图走 image-edit，没有产品图时走纯文字生图。前端状态栏改成“依据：主体 brief · N 张产品参考”，首尾帧 slot 的 info 图标可查看 brief 全文。

影响：主体可以在首尾帧里演新动作、新景别和新场景，但仍保持同一人设；产品结构继续由少量硬参考图锁住左右非对称、按键、触点、厚度和真实佩戴比例。

### 2026-05-18 · 主体生成加入随机/手动人设控制

UI Prompt API

问题：“生成主体视图”只有自由文本方向，用户想控制男女老少、着装、地域人种、肤色等人设时必须手写，而且随机生成容易在多张视图里漂移。

改动：`SourceReferenceBuildPanel` 新增“主体设定”控件：默认随机组合，也可手动指定性别表现、年龄段、着装风格、地域人种、肤色、体型比例、发型和气质场景。点击生成时前端把随机项解析成一套固定 profile，传入 `generateSubjectAssets` 的 `subject_profile`；后端 `GenerateSubjectAssetsReq` 新增 `SubjectProfilePreference`，并把这套设定写入 `gpt-image-2` prompt，要求整包视图统一使用同一人设。

影响：用户可以快速得到有差异但稳定的人物设定；随机模式仍省操作，手动模式可精确控制 casting，后续生成首尾帧时也更容易从主体库里挑到明确类型的人物。

### 2026-05-18 · 相似主体生成结果可见性修复

API UI

问题：相似主体默认一次生成 10 张，旧后端只在整包全部成功后才写入 `subject_assets`；只要其中某个视角失败，前面已生成的图也不会显示。前端默认“不用模板”时仍渲染整块模板网格，也会把生成按钮和结果区域压到可视区域下方。

改动：`generate_subject_assets` 改为逐视角容错：单张失败时继续生成下一张，并把已成功的主体图写回 state，返回“部分生成完成”；只有一张都没成功才返回错误。`SourceReferenceBuildPanel` 在“不用模板”模式收起模板网格，已有主体缩略图优先显示在生成区顶部，并在生成中显示锁定的素材 ID，明确切换其他模块不会改变本次请求。

影响：用户不再因为一个视角失败而看到空结果；默认源视频创新路径下，生成按钮和主体缩略图更容易在当前屏幕内看到。

### 2026-05-18 · 模型链路描述对齐真实后端

Model Docs

问题：前端模型弹窗和状态文档对音频、产品、相似主体、脚本改写和视频入口的描述过于简化，容易误解为所有模型调用都会成功、都会上传参考图或会直接提交视频。

改动：`ModelTrace` 文案改成真实链路：ASR 是远端 whisper、本机 mlx_whisper、Gemini 多模态三级；翻译失败会保留原文时间轴；音频画像使用 `audio.wav` + 转写时间轴并有本地估算兜底；产品识别批量失败会单图重试再写本地默认视角；相似主体先用 GPT 视觉 brief，有参考帧时再带参考图走 `/images/edits`；脚本改写全部模型失败后用本地模板；视频入口当前主工作台暂停直接提交。

影响：`web/components/ad-recreation-board.tsx`、`web/components/dashboard.tsx`、`api/README.md`、`.project.json`、`.memory/status.md` 和本页同步按实际后端行为描述，后续排查模型问题时优先看弹窗里的“兜底/失败行为”。

### 2026-05-18 · 删除个人语音通道残留

API Model

问题：旧个人语音通道虽然已不再作为活动路径，但仓库里仍有健康检查字段、前端类型、环境注释和文档历史文字残留，容易被误认为可用模型方案。

改动：`/health` 不再返回旧语音通道相关字段；`web/lib/api.ts` 删除对应类型；`api/.env.example`、`deploy/.env.production.example`、`RULES.md`、`.memory/status.md` 和本页移除相关名称和配置引用。语音只保留 Azure OpenAI TTS。

影响：后续模型分工里只描述 Azure OpenAI TTS；不要再把个人语音通道作为候选、fallback 或环境变量方案。

### 2026-05-18 · 语音通道固定 Azure OpenAI TTS

API Model

问题：语音生成测试失败时无法区分是 Azure OpenAI TTS 路径配置不对，还是整条语音服务不可用；同时 TTS 分支仍可能被环境变量或前端文案误导。

改动：后端固定 `VOICE_PROVIDER=azure_openai`，删除旧 TTS 活动配置和 fallback；`_azure_openai_tts_sync` 改为按 `AZURE_TTS_PATHS` 依次尝试多个 OpenAI-compatible 语音路径，失败时返回每个 URL 的 HTTP 状态或连接错误。`/health` 新增 `models.voice_tts_paths`。

影响：后续排查语音时先看失败信息里的路径和状态码：如果所有路径 404/405，优先调 `AZURE_TTS_PATHS`；如果连接/鉴权/上游错误，则按 Azure 语音服务可用性或 Key 排查。前端和状态文档不再展示旧语音方案。

### 2026-05-18 · 画面理解和文案改写改用 GPT

API Model

问题：关键帧画面理解和分镜/口播改写仍可能被旧环境变量覆盖到 Gemini，不符合后端模型分工。

改动：`api/main.py` 新增 `GPT_TEXT_MODEL` / `gpt_model_env`，默认 `VISION_MODEL`、`REWRITE_MODEL` 和 `AUDIO_REWRITE_MODEL` 为 `gpt-4o`；旧 `gemini-*` 覆盖值会自动归一化回 GPT。

影响：`/health` 会向前端模型标注暴露 GPT 模型名；Gemini 仅保留在 ASR fallback / 翻译链路。

### 2026-05-18 · 相似主体改为文字 brief 创新生成

API UI

问题：相似主体生成把最多 10 张源视频帧或模板图作为 `image[]` 上传给 `/images/edits`，参考图视觉权重过强，结果容易变成源视频人物或内置模板的复刻品。

改动：`generate_subject_assets` 当时在 `reconstruction_mode=similar` 时先用 `VISION_MODEL` 把关键帧、内置形象或数据库模板转成非身份化文字 brief，再调用 `gpt-image-2` 的文字生图路径；后续当前转换层已有参考帧时会改走 `/images/edits` 图像参考路径。`same` 模式保留 image-edit 源形象锁定路径。`SubjectTemplateItem` 和内置形象 manifest 新增 `prompt_brief`，保存模板时会从生成视图反推 brief。前端 `SourceReferenceBuildPanel` 改成“用模板 / 不用模板”模式开关、120px 竖排模板卡、底部一行保存表单，以及独立的“生成主体视图”区域，支持全部 10 / 常用 4 / 自定义视图。

影响：后续说“相似主体”应理解为文字 brief 驱动的创新生图，不是把关键帧或模板图送去 image edit 复制。需要精确复刻时必须显式走 `reconstruction_mode=same`。

### 2026-05-18 · 主工作台增加明亮模式

UI Style

问题：工作台已对齐登录页暗色质感，但长时间编辑分镜、产品图和首尾帧时，需要一个更亮的检查环境，方便看表格、缩略图和文案密度。

改动：`AdRecreationBoard` 顶部增加“明亮/暗色”切换按钮，使用 `localStorage["skg-board-theme"]` 记住用户选择；`globals.css` 增加 `skg-board-theme--light`，把暗场玻璃面板映射为暖白底、浅绿金色光感、深色文本和浅色边框，保留登录页同源的材质感。

影响：只改变工作台视觉模式，不改变素材下载、音频解析、抽帧、主体模板、产品素材池、首尾帧或模型链路；`web/app/page.tsx` 同步移除旧全局浮动主题按钮，避免右下角出现第二套不相关的主题入口。后续新增图片/视频板块仍应复用同一套媒体悬停放大和删除逻辑。

### 2026-05-19 · 微软 ASR 强制模式

API Ops

问题：生产验收要求音频解析走微软 Azure OpenAI，而不是远端失败后静默落到容器内 `faster-whisper` 或 Gemini 多模态兜底。

改动：`api/main.py` 增加 `ASR_LOCAL_FALLBACK_ENABLED` 和 `ASR_AUDIO_FALLBACK_ENABLED` 两个运行期开关；`GET /health` 回传这两个值。生产示例把 `ASR_BASE_URL` 固定为 `https://ai.skg.com/azure/v1`，`ASR_MODEL` 固定为 `gpt-4o-transcribe`，并关闭本地 / 多模态兜底。

影响：微软 ASR 未部署或部署名不匹配时，音频步骤会直接暴露 Azure 的错误，例如 `DeploymentNotFound`；不会再用其它通道生成看似成功的逐句时间轴。

### 2026-05-19 · 独立 ASR 上传网关配置

API Ops

问题：生产只配置 `LLM_BASE_URL=https://ai.skg.com/ezlink/v1`，文本网关不一定提供 `/audio/transcriptions` 文件上传接口，导致音频文案步骤无法真实转写。

改动：`api/main.py` 新增 `ASR_BASE_URL` / `ASR_API_KEY` 和独立 ASR OpenAI client；音频转写只通过该 client 上传 `audio.wav`，不再绑死 `LLM_BASE_URL`。`deploy/.env.production.example` 增加生产 ASR 网关示例。

影响：文本/视觉模型仍走 `LLM_BASE_URL`，音频文件上传可单独切换到支持 Audio Transcriptions 的网关；`/health` 会回传 `asr_base_url` 供排障。

补充：当云端音频网关不兼容 OpenAI Audio Transcriptions 时，可设置 `ASR_REMOTE_ENABLED=false`，直接使用容器内 `faster-whisper` 做 CPU 转写。

### 2026-05-19 · ASR 客户端级超时硬化

API Ops

问题：云端全流程中远端 `whisper-1` 转录可能长期停在“转录中”，页面没有 transcript，也不会进入后续分镜。

改动：`api/main.py` 的远端 ASR、Gemini 音频转写兜底和音频画像调用改为 `llm().with_options(timeout=ASR_TIMEOUT_SECONDS)` 后再发起请求，避免只在调用参数里传 `timeout` 时被兼容网关或 SDK 路径忽略。

影响：远端 ASR 超时后应进入本机 ASR 或多模态音频兜底，并最终给出成功 transcript 或明确失败状态；不会无限占用“音频文案”步骤。

### 2026-05-19 · 云端 TikTok cookies 文件挂载

Deploy Ops

问题：生产环境没有桌面浏览器，不能依赖 `YTDLP_COOKIES_FROM_BROWSER` 读取本机 Chrome 登录态；受限 TikTok 链接仍会在云端返回“Log in for access”。

改动：`docker-compose.prod.yml` 将宿主机 `./secrets/tiktok_cookies.txt` 挂载到 API 容器 `/run/secrets/tiktok_cookies.txt`；`deploy/.env.production.example` 默认设置 `YTDLP_COOKIES_FILE=/run/secrets/tiktok_cookies.txt`；`.gitignore` 忽略 `secrets/`，避免 cookies 入库。

影响：云端只需要维护一个服务器私有 cookies 文件，配置后可对失败素材执行“重新下载”；`yt-dlp` 会在任务结束时回写 cookies，因此该挂载不能设为只读。cookies 过期时更换该文件并重启 API 容器即可。

### 2026-05-18 · TK 受限视频支持 cookies 和失败重试

API UI

问题：部分 TikTok 链接会返回“Log in for access”，后端已经接到任务并创建 job，但裸 `yt-dlp` 下载没有登录态，任务只能失败；失败素材再次点击“开始分析”也没有重新触发下载。

改动：`api/main.py` 新增 `YTDLP_COOKIES_FILE` / `YTDLP_COOKIES_FROM_BROWSER` 和 `POST /jobs/{id}/download/retry`。`web/lib/api.ts` 新增失败文案格式化和 `retryJobDownload`；`web/app/page.tsx` 在失败素材上清掉自动触发标记，无 `video_url` 时重新下载，有 `video_url` 时重新跑音频和视觉路；`AdRecreationBoard` 按状态显示“重新下载 / 重新解析”。

影响：用户无需删除素材再粘贴同一链接；配置 cookies 后可直接对原失败素材重新下载。cookies 属于敏感登录态，只能放本机或服务器私有路径。

### 2026-05-18 · 主工作台视觉质感对齐登录页

UI Style

问题：登录页已经形成黑底、草场绿、SKG 金色和玻璃登录卡片的质感，但进入工作台后仍偏黑红/青色，前后像两个不同系统。

改动：`AdRecreationBoard` 根节点增加 `skg-board-theme`，顶部、流程条、素材列和主工作区使用 `skg-board-panel` / `skg-board-topbar`；`globals.css` 增加暗场径向光、细网格、金绿边框、玻璃阴影和金色 focus 状态。流程状态和主按钮从玫红/高饱和青色收敛到登录页同源的 SKG 金色与草绿色。

影响：这次只改颜色、质感和系统感觉，不改变素材输入、抽帧、音频解析、主体模板、分镜规划等功能链路。

### 2026-05-18 · 相似主体区接入主体模板数据库

UI Workflow

问题：“相似主体 / 主体模板”之前把内置模板选择和本次生成结果混在同一块里；后端主体数据库可用后，前端需要真的支持“已有模板可复用、新生成主体可人工命名后入库”。

改动：`SourceReferenceBuildPanel` 拆成“主体模板库”和“本次生成 / 入库草稿”两块：左侧同时读取 `GET /subject-templates` 数据库模板和 `GET /character-library/skg` 内置形象；右侧可填写模板名称、备注，并通过 `POST /jobs/{id}/subject-templates` 把本次生成主体视图保存入库。`generateSubjectAssets` 新增 `subject_template_id`，可用数据库模板继续生成新的相似主体。

影响：后续主体复用流程应理解为：先从数据库模板库选已有形象或用源视频关键帧生成新主体；新主体只有在人工确认、命名和备注后，才进入主体模板库供其他二创任务复用。

### 2026-05-18 · 去除参考帧池右侧已选重复栏

UI Workflow

问题：参考帧池和右侧“已选关键帧”展示同一批图，造成重复占位；后续主体生成本来就是读取 `selectedFrames`，不需要第二套图片列表。

改动：`SourceKeyframePicker` 删除右侧已选栏，把空间还给参考帧池。参考帧缩略图自身用勾选状态表示是否已选，顶部只显示“已选 X / 默认全部”的数量提示。

影响：后续调用逻辑不变：有勾选就只传勾选帧，没有勾选就默认使用全部参考帧。

### 2026-05-18 · 关键帧移到逐句时间轴左侧

UI Workflow

问题：关键帧和已选关键帧放在源视频工作区下方，用户看字幕时间轴时还要上下跳，下面主体生成区也被关键帧池占掉太多空间。

改动：`AudioIntakePanel` 在逐句时间轴左侧新增 `SourceKeyframePicker`，把参考帧池、已选关键帧、自动抽帧 12 张、删除关键帧和 hover 放大都放到时间轴旁。`SourceReferenceBuildPanel` 去掉下方重复关键帧池，改成只展示“相似主体 / 主体模板”、内置形象选择、主体类型、统一方向和生成后的相似主体白底视图。

影响：后续这里应理解为“上方完成源视频观看、字幕对齐和关键帧选择；下方只做主体模板和主体资产生成”。

### 2026-05-18 · 放大原版视频并右侧显示已选关键帧

UI Workflow

问题：原版视频预览偏小，用户看人物动作和手动抽帧点不够直观；关键帧勾选后只在原网格里变状态，不方便确认实际会传给相似主体重构的帧。

改动：`AudioIntakePanel` 把原版竖屏视频列和播放器高度放大一档。`SourceReferenceBuildPanel` 在关键帧网格右侧新增“已选关键帧”窄列，点击左侧关键帧会同步出现在右侧，点击右侧缩略图可取消选择；没有选择时仍默认用全部关键帧。

影响：后续描述这里时，可以把左侧理解为“全部参考帧池”，右侧理解为“本次主体重构将使用的已选帧”。

### 2026-05-18 · 前端流程编号改为状态判定驱动

UI Workflow

问题：页面里的 01、02 只是硬编码视觉标签，用户无法判断编号代表什么流程，也看不出每一步是按什么条件通过、运行、阻塞或暂停。

改动：`AdRecreationBoard` 新增 `buildWorkflowSteps`，统一定义 01 素材输入、02 源视频下载、03 音频文案、04 抽帧参考、05 相似主体、06 产品素材池、07 分镜文案、08 画面首尾帧、09 视频候选。顶部新增 `WorkflowOrderBar` 展示顺序、状态和判定依据；素材输入、源视频区、四路状态条、产品素材池、分镜文案、画面规划和视频候选列共用 `WorkflowStepBadge` / `PipelineLane` 的同一编号。

影响：以后说“改 03 音频文案”或“08 首尾帧怎么判定”时，可以直接定位到这套步骤配置；编号不再散落在 JSX 里。

### 2026-05-18 · 首尾帧按人物描述选择主体视角

UI API Workflow

问题：首尾帧不能直接把全部主体视图和产品图丢给模型；每条视频真正需要先确定场景、人、产品和动作，再按需求选择人物参考视角。产品特写不需要人物时，也不能被后端默认强加透明骨架人。

改动：`AudioStoryboardPlanPanel` 的每条分镜补充可编辑人物描述；没有描述时按分镜角色自动补统一相似主体说明。`selectSubjectRefsForRow` 会根据人物描述、镜头类型、首尾帧状态、佩戴/后颈/近景等关键词，从已生成的 6/10 张主体视图里自动选择最多 5 张最相关视角。后端 `generate_scene_asset` 只有收到主体图时才加人物身份约束；没有主体图时不会给产品特写硬塞透明骨架人。

影响：后续描述需求时应把人物理解为“主体资产池里按镜头需求调度视角”，不是“每条首尾帧都传全部人物图”。

### 2026-05-18 · 媒体素材交互收口为统一组件

UI Contract

问题：每新增图片/视频板块都临时写缩略图，导致 hover 放大、删除按钮、预览浮层层级和图片完整显示规则反复不一致。

改动：新增 `web/components/media-asset-tile.tsx` 作为项目内媒体素材基底组件，并把当前主路径的关键帧、相似主体图、产品素材图、首尾帧和历史视频候选接入同一套缩略图、顶层 hover 预览、删除/重生按钮和忙碌遮罩逻辑；`AGENTS.md` 与 `RULES.md` 同步新增媒体素材 UI Contract。

影响：以后当前项目凡是图片、视频、抽帧、产品图、AI 生成图、首尾帧或视频候选，默认不能再手写孤立交互；只允许在统一组件参数上调整尺寸和显示内容。

### 2026-05-18 · 暂停直接视频提交，改为首尾帧闸门

UI API Workflow

问题：分镜还没有真实首尾帧时直接一键提交视频，会把几十上百条视频任务一次性打到 Seedance，成本不可控；同时旧逻辑还会把关键帧继续当作后续视频参考，偏离“关键帧只用于主体重构”的新流程。

改动：`AudioStoryboardPlanPanel` 取消当前主路径里的“生成本条 · Seedance”和“一键提交全部”，改成“保存本条规划 / 保存全部规划”。画面规划列新增 `EndpointFrameSlot` 首尾帧闸门，按行生成首帧和尾帧；`endpointAssetRef` 忽略旧的 `keyframe` 首尾帧，只认可 asset 类型首尾帧。`generateEndpointFrameForRow` 调用 `generateSceneAsset`，传相似主体白底视图和按行挑选的产品图。`web/app/page.tsx` 加暂停保护，旧视频回调误触也不会请求视频接口。

影响：后续正确链路是“抽帧选主体 → 生成相似主体视图 → 上传/识别产品 → 写新口播和画面规划 → 逐条生成首尾帧 → 人工审核首尾帧 → 再开放单条视频生成”。历史视频候选仍展示，但不会继续自动追加。

### 2026-05-18 · 开始分析改为音频与视觉并行资产流

UI Workflow

问题：信息流复刻不应该等音频字幕完成后才抽帧；字幕是分镜文案前置条件，但主体参考帧和产品资产可以并行准备。旧体验让用户感觉流程线性且复杂。

改动：`web/app/page.tsx` 新增并行启动逻辑：视频下载完成后触发 `triggerTranscribe` 解析音频，同时触发 `analyzeJob` 自动抽 12 张参考帧。`api/main.py` 允许抽帧在音频转写状态下排队执行，并在音频路已运行时跳过重复拆音轨，避免并发写同一个 `audio.wav`。`AdRecreationBoard` 顶部新增音频文案路、视频视觉路、主体资产和产品资产状态条，素材输入按钮改成“开始分析”。

影响：当时 `AudioStoryboardPlanPanel` 新增“一键提交全部”以验证批量提交思路；该视频提交入口已在后续“首尾帧闸门”改动中暂停，当前主流程只保存规划并先生成首尾帧。

### 2026-05-18 · 分镜画面规划加入首尾帧和人物/产品开关

UI API Workflow

问题：“画面规划 / 产品融入”默认把每句都理解成产品 + 人物视频，导致痛点铺垫、场景过渡和产品特写无法按信息流广告真实节奏拆开。

改动：`AudioStoryboardPlanPanel` 每行新增镜头类型、人物/产品开关、首帧规划、尾帧规划和产品出现方式；默认按角色把开场/痛点设为人物情绪、利益证明设为人物+产品、转化收口设为产品特写。`StoryboardScene` 新增 `visual_mode`、`needs_product`、`needs_subject`、`first_frame_plan`、`last_frame_plan` 和 `product_placement`，后端保存到 `state.json`。

影响：`web/components/ad-recreation-board.tsx`、`web/app/page.tsx`、`web/lib/api.ts`、`api/main.py`、`RULES.md`、`docs/source-analysis.html`。单条生成时，只有勾选产品才会自动选最多 6 张产品图；只有勾选人物才会传相似主体参考图，避免不需要产品/人物的镜头被硬塞错内容。

### 2026-05-18 · 生图网关增加显式代理和网络错误提示

API Ops

问题：相似主体高清视图包调用 `gpt-image-2` 时出现 `ConnectError: nodename nor servname provided`。排查确认 `IMAGE_BASE_URL` 配置正确、模型列表可访问，错误发生在连接层；本地 launchd 启动的 API 进程没有稳定继承交互 shell 的代理环境。

改动：`api/main.py` 新增 `AI_HTTP_PROXY` / `IMAGE_HTTP_PROXY` 支持，OpenAI-compatible client 和所有图片 `/images/edits` / 图片 URL 下载统一走 `ai_http_client`。`/health` 新增 `models.ai_proxy_configured`，只显示是否配置代理，不暴露代理地址。图片 DNS、ConnectError、连接拒绝、网络不可达等传输层失败会归类为 503，并提示检查本机网络或在 `api/.env` 配置代理后重启后端。

影响：`api/main.py`、`api/.env.example`、`deploy/.env.production.example`、`RULES.md`、`docs/source-analysis.html`。后续如果生图失败但模型名仍是 `gpt-image-2`，先区分 429 上游饱和、400 参数错误和 503 网络/代理错误，不要直接改 prompt 或换模型。

### 2026-05-18 · 相似主体升级为内置形象 + 肩颈高清视图包

API UI Workflow

问题：相似主体仍按“6 视图”理解，只覆盖全身角度；肩颈按摩设备需要更清晰的脖颈、肩线、后颈和上背特写。桌面已有 5 套策划好的透明骨架形象，但主工作表没有提供内置形象选择。

改动：`SourceReferenceBuildPanel` 在“相似主体白底视图”中加入 5 套内置形象选择，默认仍可走源视频相似，选择内置形象后把 `character_id` 传给 `generateSubjectAssets`。主体生成默认请求 10 张 `2048` 高清图，包含全身多视角、肩颈正/左右近景和后颈肩背特写。后端不再把主体多参考图拼成参考板，而是把内置形象图和关键帧作为独立 `image[]` 交给 `gpt-image-2`，并在 prompt 中明确“创新变体，不照抄”。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`RULES.md`、`docs/source-analysis.html`。后续描述这个功能时应叫“相似主体高清视图包”，不要再只说 6 视图。

### 2026-05-18 · 产品视角识别切到 gpt-image-2 并重做补图参考选择

API UI Workflow

问题：同一产品素材池的视角标注仍显示通用 Vision 模型；缺角度补图固定拿第一张产品图作为参考，少侧面或内侧时容易用错误视角硬推，生成结果偏离产品真实结构。

改动：`api/main.py` 新增 `PRODUCT_VIEW_MODEL=gpt-image-2`，`analyze_product_view` / `analyze_product_views_batch` 改用该模型并在 `/health` 返回 `models.product_view`。`generateProductAngleAsset` 前端请求新增 `source_refs` 和 `source_notes`；`AudioStoryboardPlanPanel` 按目标视角给产品图打分，优先真实上传图、相邻视角、用途标签、置信度和低风险图，最多传 6 张。后端把多张参考图作为独立 `image[]` 提交给 `gpt-image-2` 生成目标角度，避免只照抄第一张，也避免参考板被模型当成拼图格式。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`RULES.md`、`api/.env.example`、`deploy/.env.production.example`、`docs/source-analysis.html`。后续补产品角度必须从同一产品素材池里挑多张证据图，不要再默认第一张。

### 2026-05-18 · gpt-image-2 图生图改用 edits 并处理上游饱和

API Reliability

问题：产品补角度遇到 `gpt-image-2` 上游 429 saturated 时，后端只间隔 1 秒重试 3 次，很容易直接失败；相似主体重构还把参考图作为 JSON `image` 参数提交到 `/images/generations`，在 GPT 图片接口下会返回 `Unknown parameter: 'image'`。

改动：`_image_edit_call` 和旧分镜图生图入口改为调用 `/images/edits`，用 multipart `image` 文件传参考图，继续固定模型 `gpt-image-2`。图像调用新增 429 / saturated 识别和退避重试；产品补角度单次请求提高到 5 次尝试，耗尽后返回 503 和“上游负载饱和，请稍后重试”的可读错误。`web/lib/api.ts` 对产品补角度和主体资产接口解析 FastAPI `detail`，不再把整段 JSON 原样堆进 toast。

影响：`api/main.py`、`web/lib/api.ts`、`docs/source-analysis.html`。后续生图仍然只走 `gpt-image-2`，但图生图必须走 edits 形态，不能再往 generations JSON 里传 `image`。

### 2026-05-18 · 相似主体缩略图压缩并支持单张重生/删除

UI API Workflow

问题：关键帧和相似主体白底视图缩略图仍偏大；主体 6 视图只能整组重生，某一张不准时无法单独替换；白底视图也缺少删除入口。竖版视频参考生成的主体图还需要明确保持竖版画布。

改动：`SourceReferenceBuildPanel` 把关键帧网格改成更小的自适应列，把白底主体视图改成 9:16 固定小缩略图；每个主体视图新增重生和删除按钮。前端只展示每个 view 的最新一张；单张重生调用 `generateSubjectAssets` 并传 `views=[当前 view]` 与 `replace_views=true`，不会追加成第 7 张。后端 `GenerateSubjectAssetsReq` 新增 `replace_views`，并新增 `DELETE /subject-assets/{asset_id}`；竖屏参考帧会把 9:16 竖版画布要求写入 prompt，输出继续按源帧纵横比归一化。

影响：`web/components/ad-recreation-board.tsx`、`web/lib/api.ts`、`api/main.py`、`docs/source-analysis.html`。后续“重新生成某张主体图”应走同视角替换，不要追加多套六视图。

### 2026-05-18 · 生图模型统一锁定为 gpt-image-2

API UI Config

问题：部分生图路径仍保留 `gpt-image-1.5` 或 Gemini 图片模型 fallback，旧分镜生图区也还能选择 Gemini 模型；这会导致同一流程里不同图片入口走不同模型。

改动：`api/main.py` 把 `GPT_IMAGE_MODEL`、`IMAGE_MODEL`、`SUBJECT_ASSET_IMAGE_MODEL` 和 `SUBJECT_ASSET_IMAGE_MODELS` 全部锁定为 `gpt-image-2`；`_image_edit_call`、`_image_text_call` 和 `/frames/{idx}/generate` 即使收到旧前端 model 字段或旧 models 列表，也只使用 `gpt-image-2`。旧 Dashboard 生图选择器改成只展示 `gpt-image-2`，模型链路标注不再显示图片模型 fallback。

影响：`api/main.py`、`web/components/ad-recreation-board.tsx`、`web/components/dashboard.tsx`、`api/.env.example`、`deploy/.env.production.example`、`RULES.md`、`docs/source-analysis.html`。该阶段凡是“生图”，包括清洗、元素提取、主体 6 视图、产品补角度、首尾帧/场景图和旧分镜生图，都只能走 `gpt-image-2`；后续在保持 `gpt-image-2` 主模型不变的前提下增加了 Gemini 故障兜底。

### 2026-05-18 · 主体 6 视图改为单图预览和单视角生成

UI API Workflow

问题：相似主体 6 视图生成后只能点击打开原图，不能像参考帧和产品图一样鼠标停留看大图；同时后端单张生成 prompt 里仍提到 six-view pack，容易让图片模型把多个视角拼进同一张图。

改动：`SourceReferenceBuildPanel` 给生成后的白底主体视图增加 `createPortal` 顶层悬停预览，缩略图保持小尺寸密排，停留时显示大图、视角标签和尺寸。`generateSubjectAssets` 把身份锁定说明改为“六视图属于同一主体，但每个输出文件只展示当前请求视角”，并为每次 view 生成加入单图规则，禁止 contact sheet、六视图拼图、多主体、多面板、标签或对比排版。

影响：`web/components/ad-recreation-board.tsx`、`api/main.py`、`docs/source-analysis.html`。后续用户说“6 视图”，应理解为 6 个独立图片文件，而不是一张六宫格大图。

### 2026-05-18 · 模型链路拆分为 GPT 生图、Azure 语音和 Seedance 视频

API Workflow Config

问题：之前图片、文本、音频分析共用 `LLM_BASE_URL`，语音通道不够清晰，视频虽然已接豆包/Seedance，但模型标注没有把“生图 GPT / 语音 Azure / 视频 Seedance”三条高优先级链路清楚拆开。

改动：`api/main.py` 新增 `IMAGE_BASE_URL`、`IMAGE_API_KEY`、`VOICE_PROVIDER`、`AZURE_OPENAI_BASE_URL`、`AZURE_OPENAI_API_KEY`、`AZURE_TTS_MODEL` 等配置；图片调用改走图片专用 OpenAI-compatible client，文字生图走 `/images/generations`，图生图后续已收敛到 `/images/edits`，默认 `gpt-image-2`；TTS 新增 Azure OpenAI 协议 `/audio/speech` 通道，默认 `VOICE_PROVIDER=azure_openai`；`GET /health` 回传图片、主体、语音和视频的实际模型与 base URL 供前端模型标注使用。

影响：`api/main.py`、`web/lib/api.ts`、`RULES.md`、`.project.json`、`docs/source-analysis.html`。真实 key 仍只写本地 `api/.env` / 生产环境变量，不能入库。

### 2026-05-18 · 6 视图改用 GPT 图片模型并修复前端展示

UI Workflow API

问题：“相似透明骨架主体”实际已经在后端生成并写入 job，但前端的相似主体识别只匹配“相似主体 / similar subject”等窄名称，无法命中“相似透明骨架主体 / similar transparent skeleton humanoid subject”，所以界面仍显示 `0/6`，重复点击还会新增重复元素。同时 6 视图模型链路仍跟随通用 `IMAGE_MODEL`，默认显示 Gemini 图片模型，不符合主体资产必须走 GPT 图片模型的要求。

改动：`api/main.py` 新增 `GPT_IMAGE_MODEL`、`SUBJECT_ASSET_IMAGE_MODEL` 和 `SUBJECT_ASSET_IMAGE_MODELS`，当时把 `generateSubjectAssets` 切到 GPT 图片链路；后续已进一步收敛为所有生图入口都只使用 `gpt-image-2`。`GET /health` 返回 `subject_image` 和 `subject_image_fallbacks`。`web/components/ad-recreation-board.tsx` 扩大相似主体元素匹配规则，并在优先帧找不到时回退到全局关键帧里查找已生成主体资产，避免图片被当前选择集隐藏；模型标注改为显示主体专用 GPT 图片链路。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续主体 6 视图不应复用通用补图模型链，必须走主体资产专用 GPT 图片模型配置。

### 2026-05-17 · 模型调用入口增加模型名和链路说明

UI Workflow API

问题：音频解析、产品识别、补图、6 视图、脚本改写和生视频都会调用模型，但界面没有明确显示当前使用哪个模型，也看不到调用链路和回退逻辑。

改动：`api/main.py` 的 `GET /health` 扩展返回 `local_asr`、`vision`、`image` 和 `image_fallbacks`；`web/lib/api.ts` 新增 `RuntimeHealth`、`RuntimeModels` 和 `getRuntimeHealth`；`web/components/ad-recreation-board.tsx` 新增 `ModelTrace`，在主路径每个模型动作旁直接显示模型名，点击后弹出小窗口显示逻辑链路。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续任何新增模型动作都必须同时接入 `ModelTrace`，不要只在代码里隐藏模型名。

### 2026-05-17 · 6 视图改为相似主体并默认使用全部关键帧

UI Workflow API

问题：“生成 6 视图”只有在用户先手动勾选关键帧后才可点击；但当前流程里自动抽出的 12 张帧本身就是相似主体参考池。生成提示也偏普通广告演员，没有锁定透明骨架人这类主体的透明皮肤、可见骨架和统一身份。

改动：`SourceReferenceBuildPanel` 改为有关键帧即可生成：未勾选时默认使用全部关键帧，勾选后只用已选帧；生成区新增“透明骨架 / 普通真人”主体类型和统一方向输入。`generateSubjectAssets` 后端提示词新增 identity lock，要求六视图先锁定同一个主体设定，再保持同一性别表现、年龄段、体型、材质、风格和视觉身份；透明骨架模式必须保持透明皮肤包裹白色骨架，且排除普通真人、纯骷髅和恐怖/医疗解剖风。

影响：`web/components/ad-recreation-board.tsx`、`api/main.py`、`docs/source-analysis.html`。后续这块不要再理解成“抽帧后复制人物”，而是“抽帧提供主体证据，再生成统一的新相似主体六视图”。

### 2026-05-17 · 竖版源视频工作区重排并恢复自动抽帧主入口

UI Workflow

问题：顶部“音频文案依据 / 当前步骤 / 音频解析结果”仍然抢占主操作空间；左侧素材列重复放横版原视频预览，竖版视频会产生大黑边；“自动抽帧”入口不够显眼，用户会误以为能力被去掉。

改动：`AdRecreationBoard` 把状态压成紧凑标签，文案依据保持默认折叠；`MaterialColumn` 不再重复显示原视频预览；`AudioIntakePanel` 把音频解析结果改成默认折叠，主区域改为左侧 9:16 竖版播放器、右侧音频波形 + 逐句时间轴，播放器内覆盖“当前点抽帧”；`SourceReferenceBuildPanel` 保留并强化“自动抽帧 12 张”主按钮，缩略图更小更密，下面再放相似主角 6 视图。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续源视频分析先看竖版播放器、波形和逐句时间轴；参考帧池负责自动 12 帧、手动补帧后的删除和相似主角选择。

### 2026-05-17 · 时间轴贴近原视频并压小参考帧

UI Workflow

问题：参考帧区占在原视频和逐句时间轴中间，导致视频和字幕联动不直观；抽帧缩略图仍偏大，一屏可比较的帧数少；“生成 6 视图”和抽参考按钮平齐，语义上像同一级操作。

改动：`AudioIntakePanel` 改成上层“原版视频 + 逐句时间轴”左右排列，下层 `SourceReferenceBuildPanel` 横向铺开参考帧；时间轴侧栏改成时间 + 原文/中文双行，减少宽度占用；参考帧缩略图用 6/8/12 列响应式排列；“生成 6 视图”移动到相似主角白底视图区。`AudioWaveform` 新增鼠标悬停时间回传，标题栏显示当前播放、总时长和指针停点秒数。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续查看原片时先看视频和右侧逐句时间轴；参考帧池是下一行横向候选区。

### 2026-05-17 · 当前点抽帧移回视频区并补悬停预览

UI Workflow

问题：“当前点抽帧”放在关键帧池顶部不符合操作路径；抽出来的竖版画面被小缩略图裁切，用户无法快速判断整张帧是否适合做主角/动作参考。

改动：`AudioIntakePanel` 把“当前点抽帧”移动到原版视频标题栏右侧，并扩大原视频、参考帧和时间轴这组区域高度；`SourceReferenceBuildPanel` 只保留批量抽参考、生成 6 视图和删除，缩略图改为 `aspect-[9/16]` + `object-contain` 完整显示，鼠标停留时用 `createPortal` 在最上层展示放大完整帧。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续需要补某一秒画面时从视频播放器操作；需要判断帧内容时直接悬停缩略图看大图。

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

UI Workflow

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

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

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

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

UI Workflow

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

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

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

### 2026-05-17 · 主动抽帧改成人物主体并压缩时间轴侧栏

UI Workflow

问题：原版视频旁的主动抽帧仍按动作变化优先，不符合当前“主体是人物”的相似主角流程；逐句时间轴侧栏也占用过多横向空间，挤压原视频和关键帧区。

改动：`SourceReferenceBuildPanel` 的“抽取 12 帧”改为“抽人物 12 帧”，调用 `analyzeJob` 时使用 `target=subject`、`quality=accurate`、`mode=replace`；`AudioIntakePanel` 的三列布局把逐句时间轴固定成较窄侧栏，把空间让给原视频和关键帧 / 相似主角区域。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续这里的 12 张关键帧默认是人物主体参考，不再按纯动作峰值理解。

### 2026-05-17 · 分镜行前窄后宽重新分配

UI Workflow

问题：分镜行前面的“分镜 / 原内容”信息量很少，却占了过多横向空间；右侧 6 个视频候选槽被压成拥挤的 2x3 小格。

改动：`AudioStoryboardPlanPanel` 的行 grid 改为前两列固定窄列，宽屏下视频列固定放大；`StoryboardVideoSlots` 从 3 列 2 行改为一排 6 个竖版候选预览。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续这个区域按“工作表高密度排版”处理，低信息字段不再占大列宽。

### 2026-05-17 · 产品素材池持久化到 job

API UI Workflow

问题：产品图文件虽然已写入 `jobs/<jobId>/assets`，但产品素材池列表、识别结果、备注和 AI 补图只存在前端 React state；代码热更新、刷新或切换任务后会清空，用户需要重新上传和重新计算。

改动：`Job` 新增 `product_refs`；后端新增 `PUT /jobs/{id}/product-refs`，前端新增 `saveProductRefs`。`AudioStoryboardPlanPanel` 在上传、识别、补图、备注编辑和删除时同步保存产品素材池，组件重新挂载时从 `job.product_refs` 恢复。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续更新 UI 或重启本地服务不应再清掉用户已上传的产品图和标注。

### 2026-05-17 · 参考帧改为原视频旁全局关键帧与相似主角

API UI Workflow

问题：分镜行里的“参考帧 / 关键元素”会把抽帧、人物参考和单条生成混在每一行里，占空间，也容易让用户误解为要逐行抽取并复刻源视频人物。

改动：`AudioIntakePanel` 在原版视频旁新增 `SourceReferenceBuildPanel`：一键重新抽取 12 张关键帧，人工选择主角参考后生成 6 张白底相似主角视图；`AudioStoryboardPlanPanel` 移除每行参考帧/关键元素列，生成视频时按全局关键帧池匹配当前句时间点。`generateSubjectAssets` 新增 `subject_style=source_actor` 与 `reconstruction_mode=similar`，用于生成类似但不复刻的正常广告演员。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。旧透明骨架人主体资产仍保留默认模式；信息流主流程的相似主角不走透明骨架人 prompt，也不做像素提取或精确身份复刻。

### 2026-05-17 · 分镜脚本支持单段和整片 AI 改写

API UI Workflow

问题：“原内容 / 新口播文案”两列占用空间偏多，并且新口播只是固定模板，不能按作者想法或原片节奏继续改写；单条生成前也无法微调文案。

改动：`AudioStoryboardPlanPanel` 在脚本区上方新增作者想法输入、整片改写和还原初稿；每行新口播改成可编辑 `textarea`，并提供“单段改写”。新增 `POST /jobs/{id}/script/rewrite` 和前端 `rewriteStoryboardScript`，后端根据原参考文案、当前新文案、分镜角色、时间段和作者想法返回中文口播。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。当前改写结果是页面级脚本状态，保存规划或生成首尾帧时会写入对应 `StoryboardScene.action`；后续如果要刷新后保留，应新增 job 级脚本草稿持久化字段。

### 2026-05-17 · 产品图识别加入肩颈按摩仪坐标系

API UI Workflow

问题：旧识别只要求模型在“正面/左45/右45/侧厚/触点/背底”里选一类，没有说明这是套在脖子上的 U 形肩颈按摩仪，也没有定义佩戴者左/右、上/下、贴颈内侧和外壳外侧，容易把图片左右当成产品左右，后续生视频会把局部细节和方向搞乱。

改动：`api/main.py` 将 `analyzeProductViews` 改为同一产品多图批量识别，prompt 固定产品为挂脖肩颈按摩仪，并新增 `orientation` 和 `landmarks` 输出；单图兜底 prompt 也同步要求产品坐标系。`web/lib/api.ts` 扩展 `ProductViewAnalysisItem`；`ProductReferenceCard` 展示“方向已识别”和结构点，悬停预览显示方向、结构和风险。

影响：首尾帧生成和后续单条视频生成时，`buildStoryboardSceneFromAudioRow` 会把“左/右按佩戴者身体左右，上/下按佩戴方向，内侧=贴颈触点，外侧=外壳按键”作为硬规则写入产品提示，并把每张选中产品图的方向和结构点一并交给模型。

### 2026-05-17 · 产品图悬停预览改为大尺寸顶层浮层

UI Workflow

问题：产品素材池底部图片悬停时，放大预览仍在滚动容器内部，容易被产品区或分镜框架裁掉；预览尺寸也偏小，不利于检查肩颈产品厚度、触点和左右差异。

改动：`ProductReferenceCard` 将悬停预览从卡片内绝对定位改为 `createPortal(document.body)` 渲染的固定浮层，宽度提升到最多 380px，并根据鼠标位置自动避开视口底部和右侧。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续产品图检查应继续使用该顶层预览，避免把预览重新放回带 `overflow` 的滚动容器里。

### 2026-05-17 · 产品图上传统一生成 AI 工作副本

API UI Workflow

问题：同事容易把“上传最高清”理解为最好，但超大原图会拖慢上传、识别和后续生图/生视频，而且并不会让模型更稳定；低分辨率图也需要被标出来，避免后面误以为细节可靠。

改动：`api/main.py` 新增 `normalize_product_asset_image`，产品图上传和产品图库复制都会生成统一 AI 工作副本：最长边 1600px、JPEG 92，推荐原图长边 1200-2000px、短边至少 600px。超大图自动压缩，低分辨率图自动放大并标风险，透明底铺白；黑底/白底背景本身不强行转换。接口返回 `ImageRef.asset_meta` 记录原尺寸、工作图尺寸、自动动作和警告。

影响：`web/lib/api.ts` 增加 `asset_meta` 类型；`ProductReferenceCard` 展示工作图尺寸、“已标准化”和“需留意”标签，悬停预览里显示规格风险。后续视频/图片生成应优先使用该工作副本，不把超高清原图直接交给模型。

### 2026-05-17 · 同一产品素材池增加生视频选图标注

UI Workflow API

问题：产品图识别不能只知道“正面/侧面”，下一步生视频需要知道哪些图适合作为主外观、佩戴比例、触点、厚度、按键或材质参考；同时用户已确认上传图属于同一产品，不需要做不同产品身份识别。

改动：`POST /jobs/{id}/assets/product-views/analyze` 扩展返回 `background`、`use_tags`、`risk`。前端 `ProductReferenceCard` 展示背景、用途标签和风险标记；`selectProductItemsForRow` 从单纯按视角轮转改为按分镜角色、视角优先级、用途标签、置信度和风险评分，自动挑选最多 6 张产品参考图。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续接入图库时，图库只负责确定同一产品身份；这里继续负责该产品多图的角度、背景、用途和生视频风险标注。

### 2026-05-17 · 产品视角识别容错解析

API Workflow

问题：视觉模型有时能判断视角，但返回的 JSON 含换行、引号或尾部格式问题，后端直接 `json.loads` 会失败，导致整张图被标成“识别失败”。

改动：`api/main.py` 新增 `parse_product_view_response`：先按严格 JSON 解析，失败后从原始输出里容错提取 `view`、`note` 和 `confidence`。同时收紧产品视角识别 prompt，要求模型输出单行 JSON。

影响：`POST /jobs/{id}/assets/product-views/analyze` 在模型输出不完全规范时也能保留视角结果，减少无意义 fallback；真正无法识别时才按上传顺序兜底。

### 2026-05-17 · 产品素材池取消数量上限，单条生成自动选图

UI Workflow API

问题：产品白底图不能固定最多 6 张。后续分镜很多，产品参考图应作为可持续扩充的素材池；但单条视频生成时也不能把素材池里的全部图片都提交给 AI。

改动：`AudioStoryboardPlanPanel` 移除上传数量上限，产品参考区改为不限量素材池，并用滚动网格承载更多图片。`analyzeProductViews` 和后端 `POST /jobs/{id}/assets/product-views/analyze` 不再只处理前 6 张；自动补缺失视角也不再因为已有 6 张素材而停止。新增 `selectProductItemsForRow`，单条分镜生成时按分镜角色、视角优先级和行号轮转，从素材池中自动挑选最多 6 张相关产品图写入 `StoryboardScene.product_images`。

影响：`api/main.py`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续需求应区分“产品素材池可无限上传”和“单条生成实际提交的产品参考图集合”。

### 2026-05-17 · 产品图上传后自动识别视角并补齐缺角度

UI Workflow API

问题：产品图上传后还让用户手动选择正面、45 度、侧面等视角，操作成本高，也容易把后续生视频的产品结构约束标错；缺失角度也不应该再让用户逐个判断后点击。

改动：新增 `POST /jobs/{id}/assets/product-views/analyze` 和前端 `analyzeProductViews`。`AudioStoryboardPlanPanel` 在上传产品白底图后自动识别每张图的视角、写入中文备注和置信度，再自动调用 `generateProductAngleAsset` 补齐缺失视角。`ProductReferenceCard` 移除视角下拉，改为只读“自动识别/自动补图”标签，用户只检查备注；`MissingProductViewSlot` 只作为自动补图失败后的重试入口。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续描述需求时应说“自动识别/补图后的备注是否准确”，不要再按“手选产品视角”理解这个区域。

### 2026-05-17 · 产品白底图加入视角备注和 AI 补角度

UI Workflow API

问题：只上传产品白底图还不够，生成视频前需要明确每张图是什么视角、有哪些结构重点；如果某些视角没拍到，也需要通过 AI 先补出可用参考图。

改动：`AudioStoryboardPlanPanel` 的产品参考区升级为产品视角工作台：每张图都有视角下拉和备注输入，鼠标悬停显示放大预览；缺失视角显示独立占位，并提供“AI 补角度”。新增 `POST /jobs/{id}/assets/product-angle` 和前端 `generateProductAngleAsset`，基于已有产品图生成缺失的白底产品视角。单条视频生成会把每张产品图的视角备注写入 `StoryboardScene.product`，用于约束左右非对称、厚度、内侧触点和肩颈佩戴比例。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。AI 补角度生成的新图保存在 `jobs/<jobId>/assets`，作为普通 `ImageRef(kind="asset")` 参与后续分镜视频生成。

### 2026-05-17 · 压缩分镜行并加入产品白底图与多候选视频槽

UI Workflow

问题：分镜行前半段占用横向空间偏多，右侧视频候选位太少；同时肩颈产品不是完全对称结构，只靠默认产品图容易生成左右一致、比例不准或佩戴尺寸跑偏。

改动：`AudioStoryboardPlanPanel` 顶部新增产品白底图上传条，建议上传 5 张、最多 6 张：正面、左 45、右 45、侧面厚度、内侧触点/佩戴比例，非对称明显时补背面或底部。分镜行前几列压缩宽度、字号和缩略图高度；右侧视频区改为 6 个候选槽，便于多次生成和筛选。生成本条时会把上传的产品图写入 `StoryboardScene.product_images`，并把“保留左右非对称、肩颈真实比例”加入产品融合提示。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。产品白底图当前作为当前页面会话内的复刻参考，单条生成时持久化进对应关键帧分镜；后续如果要跨刷新保留全局产品图组，应新增 job 级产品参考字段。

### 2026-05-17 · 新增信息流复刻分镜工作台

UI Workflow

问题：信息流复刻不应该先全量抽帧和提元素，也不能空写分镜；主线应先按音频内容规划产品分镜，再按每条分镜定向抽参考帧，并把生成出的视频回挂到对应分镜。

改动：`web/components/ad-recreation-board.tsx` 新增 `AudioStoryboardPlanPanel`：从 `job.transcript` 生成纵向分镜行，每行内部从左到右展示时间/结构、原内容、新口播文案、画面规划/产品融入、参考帧/关键元素和生成视频。每行“抽参考帧”调用现有手动加帧接口，在对应时间段中点抽取原视频参考帧；“生成本条”会把该行规划保存到对应关键帧分镜，并复用现有 `onGenerateVideo` 提交 Seedance 候选，候选视频按 `frame_idx` 回显在该行右侧。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。当前不新增后端字段，继续复用 `KeyFrame.storyboard` 和 `GeneratedVideo.frame_idx`；后续模型改写、关键元素 6 视图和完整合成可以在该分镜行内继续接入。

### 2026-05-17 · 平滑音频波形播放线

UI Workflow

问题：波形上的播放线只跟随 `video.timeupdate` 刷新，浏览器触发频率较低，播放时会一顿一顿。

改动：`web/components/ad-recreation-board.tsx` 在原视频播放期间启用 `requestAnimationFrame` 同步 `currentTime`，暂停、结束和卸载时停止帧循环；波形 SVG 点位用 `useMemo` 缓存，避免播放时重复计算整条包络。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续调整波形交互时，播放线应继续走帧同步，不要只依赖 `timeupdate`。

### 2026-05-17 · 增加原视频与连续波形联动审片

UI Workflow

问题：只有逐句时间轴难以判断原视频节奏、停顿和爆点位置；普通柱状条也看不出高低音变化，无法辅助判断口播抬升、下沉和爆点。

改动：`web/components/ad-recreation-board.tsx` 在音频解析结果面板中加入原视频播放器和横向音频波形，布局为左侧原视频、右侧逐句时间轴、底部连续响度波形。视频播放时根据 `currentTime` 高亮并自动滚动当前字幕行；点击音频波形或字幕行会跳转原视频时间。音频波形只从真实 `audio.wav` 解码生成，用连续灰色包络显示响度和停顿；解码前显示加载状态，失败时明确提示，不再用假波形兜底。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续如果要做爆点标记，应基于当前连续响度波形和字幕时间轴继续加 marker，而不是恢复底部音频条。

### 2026-05-17 · 收紧音频解析第一步版面

UI Workflow

问题：音频解析第一步顶部“音频文案依据”和主区域“原文案提取”同时展示全文，和逐句时间轴重复；逐句表格、讲话人/节奏/背景音分析也默认占用太多工作台版面。

改动：`web/components/ad-recreation-board.tsx` 将顶部“音频文案依据”改为默认折叠的 `details`；移除主面板里的“原文案提取”大卡片，不再把逐句时间轴和声音/背景音拆成两个并列区域；改为一个统一音频解析结果面板，顶部放声音/节奏/背景音 3 个短摘要，下面放紧凑可滚动逐句时间轴。

影响：`web/components/ad-recreation-board.tsx`、`docs/source-analysis.html`。后续如果需要全文原文案，只展开“音频文案依据”；如果需要查看完整分析文本，用悬停或后续扩展详情入口，不要恢复独立大卡片。

### 2026-05-17 · 修复逐句时间轴假字幕

Bugfix ASR

问题：当前 SKG 网关模型列表没有真实 `/audio/transcriptions` ASR 模型，`whisper-1` 原始调用返回 404；后续 `gemini-2.5-flash` 多模态 fallback 实际不能听到音频，却返回了 1 秒一段的重复假字幕，导致“逐句时间轴”乱掉。

改动：`api/main.py` 新增本机 `mlx_whisper` ASR fallback，并让它复用可用静态 `ffmpeg`，避免 Homebrew `ffmpeg` 动态库损坏。新增 ASR 质量校验：重复文本、逐秒合成时间轴、音频覆盖率过低的结果会被拒绝；转写失败时不再复用旧 transcript 或写入假时间轴。当前任务 `ec90faadad27` 已重新解析为 25 段真实时间轴。

影响：`api/main.py`、`api/.env.example`、`RULES.md`、`docs/source-analysis.html`。后续部署机器需要安装或配置可用 `LOCAL_ASR_BIN`；否则远端 ASR 不可用时会明确失败，而不是展示假逐句。

### 2026-05-17 · 修复素材输入元数据解析并移除底部音频条

UI Bugfix

问题：粘贴 TK 链接后视频已经下载到 `source.mp4`，但本机 Homebrew `ffprobe`/`ffmpeg` 因缺少 `libx265.215.dylib` 直接崩溃，后端误显示为“下载失败”。同时用户不再需要底部音频展示。

改动：`api/main.py` 新增媒体二进制选择逻辑，先验证 PATH 里的 `ffmpeg/ffprobe` 是否可执行，失败时回退到本机静态 `ffmpeg`；没有可用 `ffprobe` 时用 `ffmpeg -i` 解析时长和分辨率。下载阶段把“元数据解析失败”和“下载失败”区分开。ASR 请求增加 `ASR_TIMEOUT_SECONDS`，后续补充本机 `mlx_whisper` fallback 后不再直接信任不可听的多模态假字幕。`web/app/page.tsx` 不再导入和渲染 `AudioStrip`，`AdRecreationBoard` 移除“打开音轨”按钮。

影响：`api/main.py`、`web/app/page.tsx`、`web/components/ad-recreation-board.tsx`、`RULES.md`、`docs/source-analysis.html`。后续音频预览如果需要恢复，应先明确是否仍放在右侧工作表，而不是默认恢复底部浮层。

### 2026-05-17 · 收窄为第一步音频解析

UI Workflow

问题：用户明确否定前一版“开始后自动抽帧、分镜、元素、合成”的推进方式，当前只需要把信息流广告快速复刻的第一步跑通：粘贴 TK 链接或上传视频，下载源视频，提取原音频文案，并分析讲话人、节奏和背景音。

改动：`web/app/page.tsx` 的开始流程改为下载完成后只自动触发 `triggerTranscribe`；上传视频也加入同一音频解析队列。`AdRecreationBoard` 主渲染改成左侧素材输入 + 右侧音频解析工作表，不再显示“追加分镜”“开始抽帧”“生成全部视频”。`AudioStrip` 右侧改为原文案/翻译/声音背景音分析。`AudioScript` 新增 `background_audio_profile`，后端 `pipeline_transcribe` 先保存原文案、中文翻译、讲话人、节奏和背景音分析，当前第一步不默认生成 SKG 新口播或 TTS 配音。

影响：`web/app/page.tsx`、`web/components/ad-recreation-board.tsx`、`web/components/audio-strip.tsx`、`web/lib/api.ts`、`api/main.py`、`RULES.md`、`.project.json`、`docs/source-analysis.html`。后续需求应先描述“音频解析完成后是否进入下一步”，不要默认把抽帧/分镜/合成塞进开始动作。

### 2026-05-17 · 开始生产自动编排

UI Workflow

状态：已被上一条“收窄为第一步音频解析”覆盖；保留此记录用于解释旧代码和历史提交为什么存在。

问题：用户希望粘贴视频链接后点击一次“开始”，系统就自动完成素材准备：抽帧、音频分析、关键元素扫描和分镜初稿；人工只负责判断规划是否合理、选择关键元素、再单条或全量生成视频。

改动：`web/app/page.tsx` 新增开始生产编排状态：创建/激活 job 后，下载完成自动触发 `analyzeJob` 与 `triggerTranscribe`，关键帧出来后逐帧调用 `describeFrame` 并用 `updateStoryboard` 保存分镜初稿。视频生成时若分镜未显式选择产品图，会自动复制四张 `desktop-skg-product-angle-01..04` 作为 SKG 产品真源，并把已生成的关键元素 6 视图作为主体参考。`AdRecreationBoard` 把导入按钮改为“开始”，分镜卡里的候选元素可点击生成提取图 + 6 视图，顶部新增“生成全部视频”。`AudioScript` 新增 `speaker_profile` 和 `rhythm_profile`，用于展示讲话人 / 节奏参考。

影响：`web/app/page.tsx`、`web/components/ad-recreation-board.tsx`、`web/components/nodes/index.tsx`、`web/lib/api.ts`、`api/main.py`、`RULES.md`、`.project.json`、`docs/source-analysis.html`。后续需求应区分“开始生产自动编排”和“人工审核/选择/生成”的边界。

### 2026-05-17 · 合并为单一分镜生产板块

UI Workflow

问题：四列横向生产流仍把音频文案、关键元素和视频生成拆开，用户真正需要的是每个分镜内部上下游一一对应，快速复刻信息流广告。

改动：`AdRecreationBoard` 改为左侧素材输入列 + 右侧单一分镜生产板块。右侧顶部保留音频解析、打开音轨、追加分镜和抽帧控制；下方每张 `StoryboardSegmentCard` 从上到下依次包含音频分镜文案、每个分镜需要的关键元素、视频生成候选。新增 `DraftSegmentCard` 支持先无限追加草稿分镜，再绑定关键帧后保存和生成候选视频。完整视频合成入口保留在底部，后端合成接口仍待接入。本地开发态隐藏 `nextjs-portal`，避免 Next Issue 浮层遮挡看板截图。

影响：`web/components/ad-recreation-board.tsx`、`web/app/globals.css`、`RULES.md`、`.project.json`、`docs/source-analysis.html`。后续需求应按“素材输入列 + 分镜生产板块 + 分镜卡片三层结构”描述。

### 2026-05-17 · 看板改为四列横向生产流

UI Workflow

问题：左侧抽屉式看板仍像单点操作面板，不符合用户要的“从左往右推进”的广告生产逻辑。

改动：`AdRecreationBoard` 改为全屏横向四列：素材输入列按文件任务管理素材；音频解析 / 新分镜文案列把分镜从上到下排列；视频关键元素 / 抽帧生成列把关键帧横向排列，并在每张帧卡上直接生成元素和候选片段；视频合成列汇总音频、候选片段和待接入合成接口。`page.tsx` 不再渲染右侧空白 ReactFlow 画布。

影响：`web/components/ad-recreation-board.tsx`、`web/app/page.tsx`、`RULES.md`、`.project.json`、`docs/source-analysis.html`。该方向已被上方“单一分镜生产板块”取代，保留为历史记录。

### 2026-05-17 · 主界面改为左侧信息流广告复刻看板

UI Workflow

问题：此前主界面把输入、画面、音频、合成组织成 ReactFlow 可视化节点，但当前目标已确认是“快速产出信息流广告复刻片段”，节点式展示增加理解成本。

改动：新增 `web/components/ad-recreation-board.tsx`，把素材输入、视频抽帧、音频文案、关键帧选择、剧情规划/产品融入和候选片段选择合并到左侧工作表。`web/app/page.tsx` 主渲染改为左侧看板 + 右侧空白 ReactFlow 无限画布，画布节点和边暂不展示；`web/next.config.mjs` 清理 Next 16 已不支持的 `eslint` 配置，避免本地 dev 左下角 Issue 提示遮挡界面。

影响：`web/app/page.tsx`、`web/components/ad-recreation-board.tsx`、`web/next.config.mjs`、`RULES.md`、`.project.json`、`docs/source-analysis.html`。后续需求应优先描述“左侧看板里的哪一段工作表”和“右侧空白画布未来要承载什么”。

### 2026-05-16 · 登录页 Logo 静态资源公开访问

UI Deploy

问题：生产登录页引用 `/skg-logo-black.svg`，但 Nginx 只公开了 `/login/`、`/_next/`、`/assets/` 和 `/oasis-source/`，未登录访问该 SVG 会被重定向到 `/login/`，导致 logo 不显示。

改动：`deploy/nginx.conf` 新增 `location = /skg-logo-black.svg`，把官网 SKG 字标作为登录页必需静态资源公开；`RULES.md` 和本文档同步更新部署事实。

影响：`deploy/nginx.conf`、`RULES.md`、`docs/source-analysis.html`。

### 2026-05-16 · 登录页品牌文字和 Logo 水平对齐

UI Login

问题：SKG logo 放大后，右侧“营销内容工作台”的视觉水平线和 logo 内“未来健康”中文部分略有错位。

改动：`web/app/globals.css` 将系统标识连同分隔线整体下移，桌面端和移动端分别使用不同偏移，保持 logo 尺寸不变。

影响：`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-16 · 登录页系统标识改中文并放大 Logo

UI Login

问题：登录页用户主要是华人，左上角系统标识继续使用英文 `Marketing Studio` 不够直接；SKG logo 在当前画面中略小，分隔线和文字需要更稳地水平对齐。

改动：`web/app/login/page.tsx` 将系统标识改为“营销内容工作台”；`web/app/globals.css` 放大桌面和移动端 logo，调整品牌组间距、分隔线高度、中文字号和字距。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录右侧表单下移并收紧按钮间距

UI Login

问题：错误感叹号去掉后，保持登录和提交按钮之间仍保留了旧状态区空位；右侧表单整体也显得偏高。

改动：`web/app/login/page.tsx` 只在成功态渲染状态图标，不再为空闲/错误态保留固定高度；`web/app/globals.css` 将桌面端右侧表单继续下移到更贴近截图反馈的位置，移动端保持原排列。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录错误状态去掉感叹号

UI Login

问题：密码输入错误时，保持登录和按钮之间会出现一个感叹号图标，视觉上干扰登录表单。

改动：`web/app/login/page.tsx` 删除错误态 `AlertCircle` 图标渲染；错误反馈仍由动态角色的 error 状态承担，成功态勾选图标保留。

影响：`web/app/login/page.tsx`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页补系统标识和保持登录

UI Login

问题：只放 SKG 字标还缺少具体系统识别；保持会话复选框没有文字说明；表单上方单独的小锁图标占位多余。

改动：`web/app/login/page.tsx` 在 SKG 字标旁加入 `Marketing Studio` 系统标识，复选框旁恢复“保持登录”，并删除表单上方独立锁图标；`web/app/globals.css` 增加品牌标识组合布局与移动端尺寸。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页加入 SKG 字标并增强角色立体感

UI Login

问题：登录页缺少 SKG 品牌识别；动态角色仍偏扁平，和玻璃草场背景的空间感不够一致。

改动：新增 `web/public/skg-logo-black.svg`，来源为官网 `cn.skg.com/logo-black.svg`；`web/app/login/page.tsx` 在组合登录框内加入 SKG 标识；`web/app/globals.css` 为标识做反相白色玻璃处理，并给四个动态角色加高光、暗边、内阴影、接触投影和透视层次。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`web/public/skg-logo-black.svg`、`docs/source-analysis.html`。

### 2026-05-15 · 登录框固定在视口中心

UI Login

问题：组合登录框仍放在普通文档流的居中容器里，背景滚动或视口变化时视觉上会偏离画面中心。

改动：`web/app/globals.css` 将 `login-source-overlay` 改为固定覆盖全屏层；组合登录框自身用 `position:fixed; left/top:50%; transform:translate(-50%,-50%)` 直接锚定视口中心，避免网格或背景滚动状态造成偏移。

影响：`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录小人完整显示并恢复背景响应

UI Login

问题：左右排列后动态小人左侧区域偏窄，角色边缘被裁；上轮为处理底部黑边把 Oasis 背景硬锁成单屏，削弱了背景随鼠标和滚动变化的感觉。

改动：`web/app/globals.css` 扩大组合登录框和左侧角色列，提升角色区域高度与缩放比例；`web/components/login/oasis-canvas.tsx` 改为原生鼠标事件和 `postMessage` 双通道转发，输入框上移动鼠标也驱动草地；`web/public/oasis-source/index.html` 恢复完整滚动进度，保留末端阶段，只禁用原 footer 可见时的 canvas 上移逻辑来去除底部黑边。

影响：`web/app/globals.css`、`web/components/login/oasis-canvas.tsx`、`web/public/oasis-source/index.html`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页背景锁定单屏避免底部黑边

UI Login

问题：Oasis 原源码仍保留多段滚动页面高度，浏览器滚到最后一段或恢复 iframe 滚动位置时，相机会进入 footer 视角并在登录页底部露出黑边。

改动：`web/public/oasis-source/index.html` 的登录嵌入模式禁用 `html/body` 滚动，将隐藏的 `#scroll-container` 固定为单屏，并把隐藏 footer 固定到视口下方且高度归零，避免原脚本触发 canvas 上移。

影响：`web/public/oasis-source/index.html`、`docs/source-analysis.html`。

### 2026-05-15 · 登录框改为动画和表单左右排列

UI Login

问题：登录框内动画角色和账号/密码表单仍是上下堆叠，不符合“左右排列”的要求。

改动：`web/app/login/page.tsx` 给表单加独立布局类；`web/app/globals.css` 将桌面端组合登录框改为两列网格，左侧放大动画角色，右侧放账号、密码、复选框和提交图标；移动端继续上下排列避免挤压。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页路由文字彻底清空

UI Login

问题：登录框主体已经没有可见文字，但 `/login` 仍会继承全站 `title`/`description`，背景 iframe 也保留了描述性 `title`，导致检查页面源码时还能看到文字。

改动：新增 `web/app/login/layout.tsx` 将登录路由 metadata 覆盖为空；`web/components/login/oasis-canvas.tsx` 删除 iframe 的 `title` 属性；`web/next.config.mjs` 禁用开发环境左下角 Next Dev Indicator。登录界面只保留动态图形、输入框、复选框和图标按钮。

影响：`web/app/login/layout.tsx`、`web/components/login/oasis-canvas.tsx`、`web/next.config.mjs`、`docs/source-analysis.html`。

### 2026-05-15 · 登录框改为无可见文字

UI Login

问题：组合登录框内仍显示输入占位、保持会话、按钮文字和状态提示文字，不符合“登录框文字都删掉”的要求。

改动：`web/app/login/page.tsx` 删除账号/密钥输入框占位文字、保持会话文本、提交按钮文本、错误/成功状态文本以及表单控件上的可读 `aria-label`；表单视觉只保留图标、输入区域、复选框和箭头按钮。

影响：`web/app/login/page.tsx`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页合并小人和表单并清空旧文字

UI Login

问题：登录页不应再出现旧版入口文案、流程状态和指标文字；小人独立玻璃框会扩大遮挡面积，网格背景也不需要。

改动：`web/app/login/page.tsx` 将动态角色和登录表单合并进同一个 `login-source-auth-panel`，删除独立角色框。`web/app/globals.css` 让浮层容器默认不接收指针事件，只让登录框接收交互；角色区域去掉网格、边框、底部阴影和单独背景。`web/components/login/oasis-canvas.tsx` 改用 `document` 捕获阶段监听鼠标移动，并向 Oasis iframe 派发原生 `mousemove`，让它复用原源码玻璃板覆盖时仍驱动草地的逻辑。

影响：`web/app/login/page.tsx`、`web/components/login/oasis-canvas.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页只保留源码背景、登录和动画

UI Login

问题：登录页仍像内容页，保留了旧版入口营销文案、状态胶囊和底部指标，和“直接把源码背景写过来，上面只放登录和动画”的目标不一致。

改动：`web/app/login/page.tsx` 删除左侧营销文案、状态胶囊、标题、说明、Pipeline 和指标栏，只保留 `OasisCanvas`、动态角色透明框和登录表单。`web/app/globals.css` 新增 `login-page--source`、`login-source-overlay`、`login-source-character-panel` 等样式，让两个功能浮层直接叠在原版 Digital Oasis 背景上。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页草地鼠标转发、面板压缩和角色放大

UI Login

问题：原版 Digital Oasis 鼠标划过草地会产生响应，但登录页的表单和透明面板盖在 iframe 上方时，iframe 收不到鼠标坐标；同时右侧登录面板过大，左侧动态角色被压成小装饰。

改动：`web/components/login/oasis-canvas.tsx` 在捕获阶段监听父页面指针移动，并通过 `postMessage` 发送到 `web/public/oasis-source/index.html`，后者复用原 raycaster 逻辑驱动草地。`web/app/login/page.tsx` 将身份验证面板改成 290-320px 窄列、去掉强制大高度、压缩标题/输入/按钮间距；`web/app/globals.css` 将动态角色面板放大成左侧透明框架里的主视觉。

影响：`web/app/login/page.tsx`、`web/components/login/oasis-canvas.tsx`、`web/public/oasis-source/index.html`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页两块主面板复刻 Pillars 透明卡片质感

UI Login

问题：登录页左右两块面板仍偏旧黑色实体面板，没有用上源码 `Pillars` 区域的透明玻璃质感。

改动：`web/app/globals.css` 将左侧内容面板和右侧登录面板统一改为源码 `.pillar-card` 的核心效果：`rgba(10,18,10,.55)` 半透明底、`rgba(140,180,120,.12)` 细边、`16px` 圆角、`blur(16px)`、`0 8px 40px rgba(0,0,0,.4)` 阴影和 hover 边框/背景变亮；输入框、动态图角色面板、Pipeline 胶囊和底部状态条也同步成同一透明体系。

影响：`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页改为 Digital Oasis 动态背景

UI Canvas

问题：用户希望采用下载的 `remix-3d-website-the-digital-o` 视觉方向；登录页需要更有沉浸感，但不能回到具体产品展示。

改动：新增 `web/public/oasis-source/index.html`，直接复制下载包原始 WebGPU / Three.js 草场源码；`web/components/login/oasis-canvas.tsx` 改为 iframe 承载这份源码，登录页只做上层文案和表单覆盖。源码页仅用 CSS 隐藏 demo 站自己的导航、文字和设置面板，保留原草场、景深、风动和鼠标交互。

影响：`web/app/login/page.tsx`、`web/components/login/oasis-canvas.tsx`、`web/public/oasis-source/index.html`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页移除产品元素并保留动态模块

UI

问题：登录页不应该放具体产品图，入口职责是进入内容生产系统，不是展示某个产品。

改动：移除登录页产品图、G7/Neck Massager 等产品文案和产品摄影卡，改为抽象流程视觉与旧版入口文案。四个动态几何角色作为独立小组件保留，继续响应鼠标眼神跟随、输入、显示密码、错误和成功状态。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页吸收 skg.com 官网视觉元素

UI

改动：参考 skg.com 官网的浅灰产品橱窗、黑白强对比、胶囊按钮、SKG 标识、米白/香槟金健康产品光感，重构生产登录页左侧展示区；角色舞台从纯暗色网格改为官网感浅灰产品展示台，底部模块文案改为 Shop by Need / Recovery / Self-Care 语义。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页角色视觉样式升级

UI

改动：在保留四个几何角色结构的基础上，增加底座阴影、发光边、玻璃高光、内部面板和状态点，让角色更像 SKG 内容工作台里的小模块，而不是纯色几何块。

影响：`web/components/login/animated-login-characters.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页角色取消默认上下浮动

UI

问题：角色舞台默认挂了 `login-stage-breathe` 无限循环，导致四个角色在登录页一直上下移动。

改动：移除默认呼吸动画，角色平时固定贴底；错误态只保留短暂横向抖动，成功态保留一次性反馈动画。

影响：`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页角色组件重构

UI Refactor

改动：新增 `web/components/login/animated-login-characters.tsx`，把登录页四个角色从 `web/app/login/page.tsx` 抽成独立组件；角色用配置数组渲染，眼睛、嘴型和黄色 SVG 嘴不再散落在页面主体。动效状态从全页 `data-mood` 改为挂在角色舞台 `login-character-stage` 上，样式作用域更清晰。

影响：`web/app/login/page.tsx`、`web/components/login/animated-login-characters.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页角色眼神幅度增强

UI

改动：放大登录页动画角色的鼠标跟随瞳孔位移，并加大显示密码时眼睛整体看向目标的偏移；同时略微放大白眼球，避免瞳孔大幅移动时显得被裁切。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 登录页动画角色改回风格库原版几何结构

UI

问题：首版登录页把风格库的动画角色理解成圆润小球，视觉上偏幼稚，和 `14 动画角色登录` 的原始气质不一致。

改动：对照风格库 `AnimatedCharacters.vue` 和 demo，把角色重写为紫色高矩形、黑色矩形、橙色半圆、黄色圆角柱的贴底几何组合；保留鼠标视线跟随，并让输入、显示密码、错误、成功状态驱动 skew、眼睛和嘴型变化。

影响：`web/app/login/page.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。

### 2026-05-15 · 生产站点增加应用内登录页

Runtime Security UI

问题：公司域名部署后任何人知道地址都能打开工作台并调用生成能力。

改动：把浏览器 Basic Auth 改为应用内登录页：前端新增 `web/app/login/page.tsx`，参考风格库 `14 动画角色登录` 做四个几何角色、鼠标视线跟随、输入 / 显示密码 / 错误 / 成功状态反馈；后端新增 `/auth/login`、`/auth/check`、`/auth/logout`，使用 HttpOnly Cookie + HMAC 会话签名；生产 Nginx 通过 `auth_request` 保护工作台和 `/api/`。

影响：`api/main.py`、`web/app/login/page.tsx`、`web/app/globals.css`、`web/lib/api.ts`、`docker-compose.prod.yml`、`deploy/nginx.conf`、`deploy/.env.production.example`、`api/.env.example`、`.project.json`、`RULES.md`、`docs/deploy-vps.md`、`docs/source-analysis.html`。

### 2026-05-15 · 公司域名生产部署配置

Runtime Deploy

改动：把生产入口确定为 `https://marketing.skg.com`，DNS 已解析到 VPS `76.13.31.179`。新增 Docker Compose 生产配置：前端用 Next 静态导出 + Nginx，`/api/` 反代到唯一容器名 `skg-marketing-api:4291`，避免与 Coolify 网络里其他项目的泛名 `api` 冲突；后端任务目录持久化到服务器 `./data/jobs`；Traefik 通过既有 `coolify` 外部网络接管 80/443。已完成上线验证：HTTPS 首页 200，`/api/health` 返回 `ok:true`。

影响：`Dockerfile.web`、`Dockerfile.api`、`docker-compose.prod.yml`、`deploy/nginx.conf`、`deploy/.env.production.example`、`docs/deploy-vps.md`、`.project.json`、`RULES.md`、`docs/source-analysis.html`。

### 2026-05-15 · 本地启动改为后台不弹 Terminal

Runtime

问题：通过 macOS Terminal 启动后端会每次弹出一个终端窗口，打开页面时干扰使用。

改动：新增 `scripts/start-dev-background.sh` 和 `scripts/stop-dev-background.sh`。启动脚本自动检查前端 4290 和后端 4291，缺哪个后台启动哪个，日志写入 `.logs/`，PID 写入 `.pids/`，以后无需通过 `osascript` 打开 Terminal。

影响：`scripts/start-dev-background.sh`、`scripts/stop-dev-background.sh`、`.gitignore`、`RULES.md`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合按真实产品外置合成

产品融合 Video Gen

问题：Seedance 生成时可能把颈部按摩仪当成可变形装饰物，导致产品样式变化、穿进透明身体或与骨架融合。

改动：产品融合 prompt 改为英文硬约束：四张 SKG 产品图是真实产品照片和唯一实物真源，生成时按外置刚性设备做 product placement / visual compositing；产品必须停留在透明皮肤外侧，后颈外侧承托、两端沿左右颈侧向前，保留遮挡、接触阴影、透视和真实比例，禁止 x-ray blending、穿模、融进骨架或重绘成其他颈带。

界面：产品融合顶部常驻显示桌面四张真实产品角度图，并支持鼠标停留放大查看。每行视频结果不再只显示最新一个，而是按历史持续追加横向结果条，鼠标停留任一结果会放大预览。

后端：生视频参考图顺序调整为主参考图之后优先传四张产品图，再传其余人物角色图，提高真实产品外观权重。

影响：`web/app/page.tsx`、`web/components/lightbox.tsx`、`api/main.py`、`docs/source-analysis.html`。

### 2026-05-14 · 修正 SKG 豆包视频网关路径

Video Gen Seedance

问题：产品融合视频能进入队列，但后台任务 5% 后失败，错误为 `/contents/generations/tasks` 返回 404。

根因：`https://ai.skg.com/doubao` 这个 SKG 豆包网关的真实视频入口是 `/api/v3/contents/generations/tasks`，不是火山方舟直连 base 下使用的 `/contents/generations/tasks`。

改动：后端默认路径识别 `ai.skg.com/doubao` 并自动使用 `/api/v3/contents/generations/tasks`、`/api/v3/contents/generations/tasks/{id}`、`/api/v3/contents/generations/tasks/{id}/content`；本机 `api/.env` 和 `api/.env.example` 同步更新。

影响：`api/main.py`、`api/.env`、`api/.env.example`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合改为内置角色 + 产品 + 描述生成

FrameLightbox 产品融合 角色库

问题：当前产品融合不再需要手动首帧/尾帧，用户要的是从内置透明骨架人角色、场景描述、产品使用方式和享受状态直接生成视频。

改动：桌面 `skg_anatomy_characters_20260514_120852` 的 5 个角色、35 张图内置为 `api/character_library/skg-characters`。产品融合页新增角色下拉和角色预览，每行只保留场景/产品使用/享受描述、秒数、生成按钮和结果视频；选择不同角色时，6 行描述会自动改成对应角色的场景气质、产品使用动作和享受状态，并自主写入“本镜头主要参考哪几张角色图、生成什么场景”。生成前自动复制所选角色 7 张参考图和固定 4 张 SKG 产品图到当前 job。

后端：新增 `GET /character-library/skg`、`GET /character-library/skg/images/{filename}`、`POST /jobs/{job_id}/assets/character-library`。视频提交新增 `subject_images`，无首帧时主人物图以 `reference_image` role 传入 Ark/Seedance，而不是强制作为 `first_frame`。

影响：`api/main.py`、`api/character_library/skg-characters`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/lightbox.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合内置多组镜头语言

FrameLightbox 产品融合

问题：产品融合不能只写“人物使用产品”，还要稳定控制出场方式、景别、运镜、产品入画、佩戴贴合、使用感受和收尾；同时 SKG 产品是颈部/肩颈按摩仪，比例和佩戴位置不能跑偏。

改动：前端内置 36 条产品融合镜头语言模板，6 条为一组，对应建立出场、产品入画、佩戴贴合、使用感受、生活延展和收尾记忆；产品融合页新增“换一组”按钮，只刷新 6 行描述词，不改变已选角色和视频结果。视频 prompt 额外写入颈部/后颈/颈肩使用部位和真实尺寸比例约束。

影响：`web/components/lightbox.tsx`、`web/app/page.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 音频提取直接生成英文产品口播

Audio TTS

问题：“提取音频”不能只做原音频转文字再改写，用户需要点击后直接得到介绍 SKG 产品的英文文案和配音，长度尽量贴近原音频，并且声音不能生硬。

改动：`pipeline_transcribe` 提取 `audio.wav` 后读取原音频时长，用该时长估算英文口播词数；`_rewrite_audio_script_sync` 改为生成自然、有趣、可直接 TTS 的 SKG 英文产品介绍。ASR/翻译保留为对照和节奏参考，ASR 不可用时仍继续生成产品口播。TTS voice_id 改为从 `语音音色池` 随机选择男声、女声或成熟声。

影响：`api/main.py`、`api/.env.example`、`api/README.md`、`RULES.md`、`web/components/nodes/index.tsx`、`web/components/audio-strip.tsx`、`web/components/dashboard.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合描述词扩成 20 条精准模板

产品融合 Prompt

问题：产品融合视频的动作描述不能泛泛写“人物使用产品”，需要稳定表达透明骨架人在具体场景中佩戴 SKG 产品，并呈现舒适享受状态。

改动：前端内置 20 条产品使用描述模板，覆盖卧室、客厅、办公、浴室、阳台、影棚、阅读角等场景；当前产品融合页默认把前 6 条预填到 6 行镜头，用户只在需要时直接改每行描述。

后端：`generateProductFusionDescriptions` 的兜底模板同步扩为 20 条，LLM 提示也改为生成 20 条 35-70 字描述，要求包含场景、佩戴/展示动作和舒适表情，同时排除医疗治疗承诺。

影响：`api/main.py`、`web/components/lightbox.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合改为首尾帧加四产品角度垫图

FrameLightbox 产品融合

问题：原产品融合依赖白底人物、手动画区域、场景图和融合引导图，但当前透明骨架人二创流程更需要文字生成首尾帧，再把产品真源作为垫图传给视频模型。

改动：“场景图”页签改名为“首尾帧”，右侧用地点、风格、参考要素和 prompt 生成首帧/尾帧，生成后自动填入当前产品融合镜头。产品融合 6 行工作表改为首帧、尾帧、四张同一产品不同角度图、描述词、秒数和生成按钮，并提供桌面四角度填当前镜头/填满 6 镜头。

后端：`generateSceneAsset` 新增 `asset_role`，`first_frame/last_frame` 走文字生图并标记资产角色；`ProductFusionShot` 新增 `first_image`、`last_image`、`product_images`，视频提交直接把首尾帧和四张产品图交给 Seedance；产品库新增桌面 `skg产品1-4.jpg` 四角度条目。

影响：`api/main.py`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/lightbox.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 本地抽帧改为展示友好算力档

抽帧 Audio

问题：透明骨架人目标逐帧调用 Vision 验收会拖慢抽帧；切回本机算力后，如果自动档直接跑最高极准，也可能在展示时占满机器资源。

改动：`transparent_human` 目标保留，但抽帧阶段只走本地扫描、评分、去重和时间覆盖，不再逐帧调用 Vision。`quality=auto` 最高只自动选择精细；极准仍保留为手动选项。抽帧开始拆出 `audio.wav` 后会启动独立音频线程，视觉抽帧和音频处理并行，互不标失败。

影响：`api/main.py`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 修复 ReactFlow Hydration 和后端 reload 卡住

Canvas Dev Server

问题：刷新页面时 Next 报 Hydration mismatch，ReactFlow 节点服务端默认宽度和客户端 localStorage 里的用户调整宽度不一致；同时提交抖音链接时若后端正在 `--reload` 等后台任务结束，会出现 4291 端口占用但请求卡住。

改动：`web/app/page.tsx` 增加 `clientReady`，ReactFlow 和底部音频条只在浏览器挂载后渲染，避免服务端 HTML 和客户端本地布局缓存不一致。后端启动说明改为不带 `--reload` 的稳定命令，并更新 `RULES.md`、`api/README.md` 和本页运行入口。

影响：`web/app/page.tsx`、`RULES.md`、`api/README.md`、`docs/source-analysis.html`。本地 4291 后端已按无 reload 模式重启。

### 2026-05-14 · 音频处理改为音频卡片手动触发

Audio Workflow

问题：等待抽帧完成后自动启动音频，不符合“先把声音文案拿出来审核”的工作流；用户需要在音频卡片上直接触发。

改动：移除前端抽帧完成后的自动转写逻辑；`AudioNode` 保留并固定显示“提取音频 / 重新提取音频”按钮，点击音频卡片也会立即打开底部音频条。后端 `/transcribe` 不再要求 `frames_extracted`，视频就绪后可直接从 `source.mp4` 拆出 `audio.wav`，并按原音频时长生成 SKG 英文产品介绍和 TTS 随机英文配音；抽帧中触发时不抢主状态，而是用 `audio_script.status` 表示音频处理中。当当前网关的 `whisper-1` audio endpoint 返回 404 时，会 fallback 到 Gemini 多模态音频识别；ASR 不可用时也会继续按原音频时长生成产品口播，不把可用文案标成前端错误。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`、`api/main.py`、`docs/source-analysis.html`。

### 2026-05-14 · 新增底部可伸缩音频条

Audio Timeline

问题：音频和文案只在节点或侧栏里展示，审核时缺少“文字和声音时间轴对应”的空间；英文口播和中文翻译也没有上下对齐。

改动：新增 `web/components/audio-strip.tsx`，在主工作台底部吸附显示，可拖拽调整高度、可收起。每个音频段按时间横向排列，上方显示英文，中间显示中文翻译，下方显示对应波形条；底部原音频播放器驱动时间轴，播放时绿色指针会沿全局波形移动，并在当前字幕节点内同步走过该段。右侧显示按原音频时长生成的 SKG 英文产品口播、TTS 随机英文配音和产品依据。后端新增 `source_audio_url` 和 `GET /jobs/{id}/audio.wav` 只读接口，前端用 Web Audio API 解码生成波形峰值。

影响：`web/app/page.tsx`、`web/components/audio-strip.tsx`、`web/lib/api.ts`、`api/main.py`、`docs/source-analysis.html`。

### 2026-05-14 · 音频结果改为改前/改后对照展示

Audio UI

问题：音频识别成功后只显示改写文案，用户看不到它和原音频之间的变化关系，难以判断“是不是把参考视频转成我们自己的话”。

改动：`AudioNode` 增加轻量对照摘要：改前显示原音频识别/翻译预览，改后显示 SKG 英文产品口播；侧栏 `Rewrite` 面板改为完整审核视图，先列原音频逐段 ASR/翻译，再列英文产品介绍稿、产品卖点依据和 TTS 英文配音播放器。

影响：`web/components/nodes/index.tsx`、`web/components/dashboard.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 多视频工作流状态按 job 隔离

Canvas Job State

问题：同时上传多个视频后，前端把已选关键帧和关键帧详情面板作为全局状态保存；切换 active 视频会清空选中帧，或者让详情面板指向另一个视频的同序号帧，容易误以为生图/自动化被终止或串任务。

改动：`web/app/page.tsx` 将 `selectedFrames` 和 `expandedFrame` 改为按 `jobId` 存储。切换视频只改变当前视图，不清空其他视频的选择；重新抽帧、删帧、手动加帧只清理或更新对应 job。异步生图、生视频、产品融合返回后按返回的 `job.id` 写回 `jobs[]`，不会落到切换后的 active job。轮询条件也把 `audio_script.status=rewriting` 纳入运行态，保证音频改写/配音阶段切换视频后仍继续刷新。

影响：`web/app/page.tsx`、`docs/source-analysis.html`。后端轮询本来已经覆盖所有运行中的 job，这轮主要修正前端 UI 工作上下文。

### 2026-05-14 · 抽帧后台任务不再卡住 API

API 抽帧

问题：点击视频抽帧时，后端 4291 端口能连接但 `/health` 和后续请求长时间不返回，前端看起来像按钮没有反应。

原因：`pipeline_download` 和 `pipeline_analyze` 声明为 async background task，但内部实际是同步 `yt-dlp`、`ffmpeg` 和 Vision 验收；Starlette 会在事件循环里执行 async background task，导致长抽帧把 API 主循环堵住。

改动：下载和抽帧 pipeline 改为普通同步函数，让 FastAPI/Starlette 按线程池后台任务执行；`analyze_queue_worker` 也改为同步 worker。服务启动恢复时，如果磁盘里有重启前遗留的 `downloading`、`splitting` 或 `transcribing` 运行态，会恢复成可重试状态，避免按钮一直 disabled。开发运行时改用不带 `--reload` 的后端命令，避免重载等待后台任务。

影响：`api/main.py`、`docs/source-analysis.html`。已重启本地 4291 后端并验证 `/health` 立即返回；遗留的 `8b37e65521a6` job 已恢复为 `downloaded`，可重新点击抽帧。

### 2026-05-14 · 生视频接入 SKG 豆包网关

Video Gen Seedance

问题：用户提供 `https://ai.skg.com/doubao` 作为视频模型网关；该网关应按 Seedance / 方舟内容生成任务格式提交，而不能误走普通 multipart 上传。

改动：`video_uses_ark()` 现在同时识别火山方舟域名和 `ai.skg.com/doubao`，统一使用 `content` JSON：文本 prompt、首帧、尾帧和产品参考图作为不同 role 传入。火山方舟直连按 `/contents/generations/tasks/{id}` 轮询；SKG 豆包网关按 `/api/v3/contents/generations/tasks/{id}` 轮询。`api/.env.example` 增加 SKG 豆包视频网关配置示例；生视频轮询上限改为 `VIDEO_POLL_TIMEOUT_SECONDS`，默认 900 秒，避免慢任务过早失败。

影响：`api/main.py`、`api/.env.example`、`docs/source-analysis.html`。本机 `api/.env` 已配置 `VIDEO_API_BASE_URL=https://ai.skg.com/doubao` 和视频专用 key。

### 2026-05-14 · 音频处理接入 SKG 英文产品口播与 TTS 配音

Audio TTS

问题：音频处理节点之前只说明“音轨 → ASR → 翻译 → 改写”，没有按原音频时长生成的产品介绍产物，也没有配音输出；用户无法直接拿到符合 SKG 产品语境的英文口播。

改动：`Job` 新增 `audio_script`，`pipeline_transcribe` 提取 `audio.wav` 后按原音频秒数生成 SKG 英文产品介绍文案，并在配置 `语音 API Key` 时调用 TTS T2A 输出 `/jobs/{id}/audio-script.mp3`。TTS voice_id 从英文男声、女声、成熟声池随机选择；前端 `AudioNode` 和侧栏 Rewrite 区显示模型链路、英文产品文案和配音播放器。

边界：TTS 官方 Speech API 当前接入的是 TTS 配音，不替代 ASR；原始音频文案提取仍走现有 OpenAI-compatible audio transcription 入口。

影响：`api/main.py`、`api/.env.example`、`api/README.md`、`web/lib/api.ts`、`web/components/nodes/index.tsx`、`web/components/dashboard.tsx`、`web/app/page.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 默认抽帧张数改为 12 帧

InputNode 抽帧

问题：透明骨架人主题需要更稳定的素材覆盖，默认 5 帧太少，容易缺少可用于主体、场景和产品融合的角度。

改动：后端 `KEYFRAME_COUNT` 默认值、前端抽帧 fallback、API client 默认参数都改为 12；抽帧设置里的张数选项把 12 放到第一位。透明骨架人目标仍会对每个候选做 Vision 验收，不合格候选自动换下一帧。

影响：`api/main.py`、`api/.env.example`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 抽帧新增透明骨架人 AI 验收目标

InputNode Vision

问题：透明人二创不能只靠清晰度抽帧，也不能只要出现“骨头”就算合格；需要确认同一人形角色同时具备透明/半透明外壳、干净白色骨架、足够大且清晰、非恐怖广告感。

改动：`FrameExtractTarget` 新增 `transparent_human` 并设为当前 UI 默认目标。后端抽帧先按本地清晰度、中心主体、对比度和去重扩大候选池，再逐张从原视频抽高清帧交给 Vision 评分；评分维度包括透明身体、可见骨架、人物占比、清晰度、商业风格和产品可用性。不合格帧会被删除并自动换下一候选，直到凑够目标张数或候选耗尽。

影响：`api/main.py`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/nodes/index.tsx`、`web/components/lightbox.tsx`、`web/lib/workflow-target.ts`、`docs/source-analysis.html`。

### 2026-05-14 · 清洗页增加一键替换待应用清洗版

FrameLightbox 清洗

问题：一键清洗后会生成多张待应用清洗版，但用户仍需要逐张点“替换原图”，素材准备阶段操作成本偏高。

改动：“原图/清洗”页新增“待替换清洗版”状态和“一键替换待应用 N 张”按钮，并显示批量替换进度和失败数。该按钮只应用已经存在的清洗结果，不重新清洗；不满意的帧仍可先单张重洗或丢弃。

影响：`web/components/lightbox.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合收敛为首尾帧 + 固定四产品图

FrameLightbox 产品融合

问题：产品融合页继续显示产品角度槽、辅助栏和产品图库会把操作变复杂；当前工作流只需要用户手动补人物首尾帧，产品图固定来自桌面 4 张 SKG 图。

改动：“产品融合”页每行只保留首帧、尾帧、已预填描述词、秒数、生成按钮和行末视频结果。生成单条或批量视频前，前端自动把内置的 4 张桌面 SKG 产品图复制为当前 job asset 并写入 `product_images[4]`；视频 prompt 增加 `产品融合镜头ID` 标记，用来把生成结果显示回对应行。

影响：`web/components/lightbox.tsx`、`web/app/page.tsx`、`web/components/nodes/index.tsx`、`web/components/dashboard.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合镜头组改为纵向 6 行工作表

FrameLightbox 产品融合

问题：产品融合要生成 6 条视频，但旧排版只在列表里显示摘要，真正编辑区只展开当前镜头，用户无法从上到下同时检查 6 条镜头的产品、人物、场景和描述是否一一对应。

改动：“产品融合”页左侧改为纵向 6 行镜头工作表。每行包含产品图槽、白底人物图槽、人物图内产品区域画框、场景图槽、动作描述、秒数选择和单条生成按钮；右侧只保留模型状态、当前镜头状态、AI 草拟 6 条、批量排队和当前镜头产品图库。

影响：`web/components/lightbox.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合改为 6 行区域约束镜头组

FrameLightbox Seedance

问题：只把产品图作为参考图无法解决尺寸和位置融合，模型不知道产品应该放在人物或场景里的哪个区域。

改动：`FrameLightbox` 的“产品融合”页改为 6 行镜头组。每行绑定产品图、白底人物图、手动画出的产品区域、场景图、描述词和视频秒数；图片槽支持上传和粘贴，产品图也可从内置 SKG 白底图库选用。右侧固定显示图片模型 `GPT Image 2` 和视频模型 `Seedance`，支持 AI 草拟 6 条动作描述和批量排队；单条生成入口放在每一行镜头内。

后端：新增 `POST /jobs/{job_id}/product-fusion/guide` 和 `POST /jobs/{job_id}/product-fusion/descriptions`。前者把产品图按 `product_region` 合成到白底人物图上，生成普通 `asset` 引导图；后者用 LLM 或本地模板生成 6 条动作描述草稿。前端再把引导图作为 Seedance 首帧，并把产品图、人物图、场景图作为参考图提交。

影响：`api/main.py`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/lightbox.tsx`、`web/components/nodes/index.tsx`、`web/components/dashboard.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 产品融合槽位接入应用内剪贴板

FrameLightbox Clipboard

问题：卡片上的“复制”写入的是应用内 `ImageRef` 剪贴板，而产品融合槽位只监听系统剪贴板文件，导致复制后的素材无法在产品融合里粘贴。

改动：`NodeData` 和 `FrameLightbox` 新增 `clipboard` 传递链路；产品融合三类槽位的“粘贴”按钮优先使用应用内剪贴板，应用剪贴板为空时再提示可选中槽位后 Cmd+V 粘贴系统图片。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`、`web/components/dashboard.tsx`、`web/components/lightbox.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 增加产品融合和 SKG 内置白底图库

FrameLightbox 产品融合

问题：生成视频需要稳定的 SKG 产品真源，不能每次都依赖临时上传或从参考视频里找产品图；桌面已有整理过的 SKG 产品图，应作为内置数据库使用。

改动：从桌面 `skg_product_downloads/all_products` 的 gallery 中筛出 41 张白底产品图，生成 `api/product_library/skg-products/manifest.json` 和压缩预览图。`FrameLightbox` 新增“产品融合”页签，`StoryboardWorkbench` 的 SKG 产品参考区也接入同一个 `ProductLibraryPicker`，支持搜索、品类筛选、尺寸预览和一键加入。

后端：新增 `GET /product-library/skg`、`GET /product-library/skg/images/{filename}` 和 `POST /jobs/{job_id}/assets/product-library`。选中库内产品图时，后端会复制成当前 job 的 `asset`，后续仍通过既有 `product_images` 进入生视频接口。

影响：`api/main.py`、`api/product_library/skg-products`、`web/lib/api.ts`、`web/components/product-library-picker.tsx`、`web/components/lightbox.tsx`、`web/components/storyboard-workbench.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 场景图改为全图参考和关键词 Prompt

FrameLightbox Prompt

问题：场景图页不能只围绕当前单张图；它需要看到全部关键帧，并通过地点、风格、参考要素等关键词组合出可控 prompt，再生成场景。

改动：`FrameLightbox` 的“场景图”页左侧改为全部关键帧网格：点击图片设为生成目标，点击“选”加入场景参考。右侧新增地点、生成方式、风格、额外关键词和参考要素 chips，并自动拼出可编辑场景 prompt。

后端：`generateSceneAsset` 请求新增 `prompt` 和 `source_frame_indices`；多张参考帧会拼成 contact sheet 给图像模型，同时把用户 prompt 注入场景生成提示词。

影响：`web/components/lightbox.tsx`、`web/lib/api.ts`、`api/main.py`、`docs/source-analysis.html`。

### 2026-05-14 · 主体资产改为参考重绘六张标准图

FrameLightbox Assets

问题：主体资产不是抠图，也不是只看当前单帧生成多角度；主体页需要看到全部参考帧，并用这些参考重新绘制一个完整主体。

改动：`FrameLightbox` 在“主体资产”页左侧显示参考帧网格，优先纳入所有已清洗帧，额外已选帧也会并入；小图排列，可点击切换当前帧。右侧仍负责统一主体确认和生成。人物/生物默认视图改为六张身份标准图：正面、背面、左侧、右侧、左前 45°、右前 45°；并把表情补充和动作补充折成独立分组，需要时再勾选。

后端：`generateSubjectAssets` prompt 改为“参考重绘”，明确禁止裁剪/抠图/粘贴源像素，要求主体完整居中、纯白/黑背景、无其他元素，并占画面约 85-95% 高度；落盘时会裁掉纯背景空白并放大主体。

影响：`web/components/lightbox.tsx`、`web/components/nodes/index.tsx`、`api/main.py`、`docs/source-analysis.html`。

### 2026-05-14 · 主体资产改为统一主体参考帧生成

FrameLightbox Workflow

问题：当前流程里抽多张关键帧的目的不是让每张图各自生成一个主体，也不是从单张图硬造多角度，而是用多张关键帧共同还原同一个主体的多角度、动作和表情。

改动：`FrameLightbox` 的主体页改成“统一主体”逻辑：全局只保留一个主体候选；生成主体资产包时默认传全部关键帧作为 `source_frame_indices`，用户手动选择关键帧时只传已选帧。场景图仍然按当前关键帧逐张生成，因此是一个主体包 + 多个场景图。

后端：`generateSceneAsset` 查找主体名称时改为从整个 job 的已生成主体资产中读取，而不是只看当前帧，确保任意关键帧生成场景图时都能移除统一主体。

影响：`web/components/lightbox.tsx`、`web/components/nodes/index.tsx`、`api/main.py`、`docs/source-analysis.html`。

### 2026-05-14 · 场景图改为主体资产之后生成

FrameLightbox API

问题：场景图如果先于主体资产生成，只能做普通背景清理，无法准确知道要移除哪个主体，也不利于后续生成相似但不同或同构换风格的场景。

改动：`FrameLightbox` 页签顺序改为“原图/清洗 → 主体资产 → 场景图 → 审核”；画面工作台缩略图和进度文案也同步为主体资产先于场景图。场景图页新增“去主体原场景 / 相似新场景 / 同构换风格”和风格选择，且在没有主体资产时提示先生成主体资产。

后端：`generateSceneAsset` 请求新增 `scene_mode` 和 `scene_style`；后端提示词会优先读取已生成主体资产对应的主体名称，生成去主体并补背景的场景图，再按模式决定是否做相似变化或风格变化。

影响：`web/components/lightbox.tsx`、`web/components/nodes/index.tsx`、`web/lib/api.ts`、`api/main.py`、`docs/source-analysis.html`。

### 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 · 清洗页支持一键批量清洗

FrameLightbox UX

问题：画面工作台里的关键帧已经在抽帧阶段筛过，逐张点“清洗水印”会拖慢素材准备；但自动清洗又不能直接覆盖原图，否则模型误改时不好回退。

改动：`FrameLightbox` 的“原图/清洗”页新增“批量清洗”卡片，一键顺序清洗所有未处理素材帧，并显示进度和失败数。批量清洗只生成 `cleaned` 待审核版本，不自动应用；没清干净的帧再用单帧框选区域做手工补洗。

影响：`web/components/lightbox.tsx`、`docs/source-analysis.html`。后端暂未新增 batch API，前端复用 `POST /jobs/{id}/frames/{idx}/cleanup` 顺序执行。

### 2026-05-14 · 关键帧详情改为素材准备面板

FrameLightbox UX

问题：面板标题仍叫“关键帧详情 · 元素提取”，里面还露出普通 cutout 抠图、AI 提取、元素清单等旧流程入口；“选用此帧 / 加入目标帧”也无法说明实际价值，因为抽帧阶段已经筛过图，进入画面工作台的关键帧默认就应该参与素材准备。

改动：`KeyframePanelNode` 标题改为“关键帧素材准备”；`FrameLightbox` 的主体页改成“主体识别 / 主体清单 / 主体资产包”，移除普通抠图列表、AI 提取按钮、详情内的目标帧开关以及手动/框选加主体入口，改为只显示“已在素材准备流程”的状态说明；`VisualLabNode` 上方缩略图也不再展示普通抠图分组，只展示关键帧、主体包、场景图和视频任务。

影响：`web/components/lightbox.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。底层旧 cutout 数据和接口暂保留兼容历史任务，但不再作为新素材准备流程的可见入口。

### 2026-05-14 · 画面工作台改为素材准备看板

Visual Lab UX

问题：画面工作台从展示缩略图扩展为素材生产中枢后，关键帧、主体资产包、场景图和视频任务继续混在一个列表里会让流程不清晰；关键帧详情面板也把清洗、识别、主体生成和场景生成都堆在一屏。

改动：`VisualLabNode` 改成素材准备进度看板，显示关键帧素材、主体资产、场景图和分镜/视频四个入口。`FrameLightbox` 新增“原图/清洗、主体资产、场景图、审核”四个页签，素材审核信息从普通列表中拆出来。

影响：`web/components/nodes/index.tsx`、`web/components/lightbox.tsx`、`docs/source-analysis.html`。这轮只重排工作台信息架构，批量自动准备队列仍留到下一阶段。

### 2026-05-14 · 画面工作台增加主体资产包和场景图

Visual Lab Assets

问题：抽帧阶段已经筛过图，画面工作台第一步应把已选关键帧转成可用于生视频的干净素材：同一主体一套多视角/动作/表情图，再基于主体生成每帧去主体场景图，而不是继续手动逐张抠普通 cutout。

改动：`KeyFrame` 新增 `scene_assets` 和 `quality_report`；`KeyElement` 新增 `subject_kind` 与 `subject_assets`。后端新增 `generateSubjectAssets` 和 `generateSceneAsset`，主体资产支持白/黑背景、原尺寸/固定尺寸、物体视角、人物/生物动作与喜怒哀乐等表情；当已选关键帧共同指向一个主体时，前端会把这些帧作为 `source_frame_indices` 传入，后端拼接参考板。

影响：`api/main.py`、`web/lib/api.ts`、`web/components/lightbox.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。生成出的素材保存在 `jobs/<jobId>/assets`，可作为 `asset` 类型复制到后续分镜槽位。

### 2026-05-14 · 抽帧精度自动选择并支持后端排队

Input Queue

问题：抽帧精度不应该每次都让用户判断；点击一个视频抽帧后，其他视频不应被全局禁用，而应该可以先后排队。另外打开视频抽帧侧边面板后，也应能自动抽帧。

改动：`quality` 新增 `auto` 默认值，后端按 CPU 核数、内存和视频时长解析为快速或精细；为了展示稳定，auto 不再自动进入极准，极准仅在用户手动选择时启用。后端新增内存队列 `ANALYZE_QUEUE`，多个 `analyze` 请求按顺序执行；前端轮询所有运行中的 job，不只轮询当前 active job。`VideoFramePanelNode` 内也加入同一套自动抽帧工具条。

影响：`api/main.py`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。队列目前是进程内队列，重启后不会恢复未执行的排队任务。

### 2026-05-14 · 抽帧工具条降噪并修复追加失败

Input Bugfix

问题：每个缩略图上方同时放目标、张数、精度和按钮太拥挤；另外追加抽帧时可能没有新增图片。

根因：追加模式下 `frames` 目录已经存在，但后端仍使用非 `exist_ok` 的 `mkdir`，触发 `File exists` 后任务进入解析失败。

改动：工具条默认只显示目标、抽帧/追加和设置按钮；张数、精度折叠到设置里。后端改为允许已存在的 `frames` 目录，追加模式不再因目录存在失败。缩略图高度增大到 192px，横屏/竖屏都按真实比例显示；抽帧评分也按视频原比例缩放，不固定 16:9。

影响：`api/main.py`、`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。已用临时 job 验证 append：已有 1 张关键帧时追加 3 张后变为 4 张。

### 2026-05-14 · 自动抽帧增加本地精度模式

Input Performance

问题：当前抽帧默认偏轻量，用户机器是 Apple M2 Max、12 核 CPU、38 核 GPU、64GB 内存，足以承受更密集的本地候选扫描；但需要在 UI 里提示算力档位，避免长视频误用重模式。

改动：后端 `/jobs/{id}/analyze` 新增 `quality` 参数：快速为 2fps/360px，精细为 8fps/720px，极准为 12fps/960px；高精度模式还会提高本地评分图分辨率，保留竖屏比例，不再把竖屏压扁到 16:9。每个缩略图工具条新增精度选择。

影响：`api/main.py`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。实测本机 64.5s、1080×1920、60fps 视频，12fps/960px 扫描 774 张候选约 2.61s；重型 ffmpeg 场景/模糊滤镜约 21.63s，因此继续使用本地 PIL/NumPy 评分更划算。

### 2026-05-14 · 每个输入视频缩略图绑定自己的抽帧工具条

Input UX

问题：统一放在缩略图浮条上方的抽帧工具条仍然不够明确，用户无法一眼判断当前会抽哪一个视频。

改动：抽帧目标、张数、精度和抽帧按钮改为渲染在每个视频缩略图正上方，并且每个 job 独立保存目标、张数和精度设置。点击某个缩略图上方的抽帧按钮时，前端直接把该 `jobId` 传给 `analyzeJob`，同时切换 active job 并进入该 job 的进度轮询。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。后续与输入视频相关的快捷操作都应优先贴近对应缩略图，不再依赖全局当前选择的心智。

### 2026-05-14 · 自动抽帧快捷工具条移到缩略图上方

Input Frame Target

问题：自动抽帧入口放在 Input 卡片正文里，离视频缩略图和预览工作区较远；用户需要在看缩略图时快速切目标、切张数并反复抽取。

改动：输入视频缩略图浮条上方新增自动抽帧快捷工具条，包含抽帧目标、张数快捷项和抽帧按钮。前端新增 `frameCount` 状态并把目标 / 张数传给 `analyzeJob`；已有关键帧时默认用 `mode=append` 追加抽取。

影响：`api/main.py`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。后端追加模式会保留已有关键帧，避开非常接近的时间点，并用新的 frame index 落盘。

### 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 · 视频抽帧面板默认静音播放

Input Video

问题：输入视频缩略图改为单击打开抽帧面板后，面板播放器如果自动播放带声音，会打断工作流。

改动：`VideoFramePanelNode` 的主播放器增加 `muted`，默认静音自动播放；用户仍可通过浏览器视频 controls 自行取消静音。

影响：`web/components/nodes/index.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · Canvas Panel 颜色跟随来源卡片且视频单击打开

Canvas Panel UX

问题：视频抽帧面板和画面工作台详情面板框架一致后，标题栏颜色也需要分别跟各自来源卡片一致；输入视频缩略图仍需要双击才能打开抽帧面板，操作偏重。

改动：视频抽帧面板标题栏使用 `--grad-input`，画面工作台详情面板标题栏使用 `--grad-ai`；输入视频缩略图改为单击打开抽帧面板，hover 仍负责尺寸预览。

影响：`web/components/nodes/index.tsx`、`docs/source-analysis.html`。后续面板颜色应从来源卡片类型继承。

### 2026-05-14 · 画面工作台详情面板统一为 Canvas Panel 框架

Visual Lab Canvas Panel

问题：关键帧详情 / 元素提取面板虽然默认左侧吸附，但外层仍是旧橙色“钉住”框架，和视频抽帧面板的紫色标题栏、画布/左/右/底吸附按钮不一致。

改动：`KeyframePanelNode` 改为和 `VideoFramePanelNode` 同一套 Canvas Panel 外壳：紫色标题栏、画布模式、吸附左侧、吸附右侧、吸附底部、缩放、关闭和右下角拖拽缩放。面板定位状态从单一 `pinned` 语义升级为 `framePanelDock`。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。后续工作面板应复用这套 Canvas Panel 框架。

### 2026-05-14 · 关键帧详情嵌入态去掉双标题栏

Visual Lab FrameLightbox

问题：画面工作台详情面板外层已有“关键帧详情 · 元素提取”工具栏，内层 `FrameLightbox` 嵌入态又显示一条橙红分镜导航栏，视觉上像两个窗口叠在一起。

改动：`FrameLightbox` 在 `embedded` 模式下不再渲染自己的顶部工具栏和外边框；上一帧 / 下一帧导航移动到 `KeyframePanelNode` 外层标题栏。

影响：`web/components/lightbox.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。非嵌入式 lightbox 保留原标题栏。

### 2026-05-14 · 画面工作台详情面板默认左侧吸附

Visual Lab Dock

问题：画面工作台点击关键帧后，关键帧详情 / 元素提取面板仍默认作为画布节点出现，还会触发 `fitView` 拉动画布；和视频抽帧面板默认左侧吸附的规则不一致。

改动：`framePanelDock` 初始值改为 `left`；从关闭状态打开关键帧详情时默认吸附左侧。若面板已打开，用户切回画布模式后继续切换关键帧，不会被强制吸回左侧；默认吸附状态下也不再触发画布 `fitView`。

影响：`web/app/page.tsx`、`docs/source-analysis.html`。画面工作台处理面板现在与视频抽帧面板保持同一默认策略：先贴左侧，需要时再切回画布。

### 2026-05-14 · 视频抽帧面板默认左侧吸附

Canvas Panel Dock

问题：视频抽帧面板默认以画布节点方式打开时，用户还要再点一次吸附左侧，和“处理面板先贴边、需要时再拖回画布”的工作习惯不一致。

改动：`videoPanelDock` 初始值改为 `left`；从关闭状态双击输入视频缩略图时默认吸附左侧。面板已打开后，用户手动切换到画布 / 右侧 / 底部不会被找回动作覆盖。

影响：`web/app/page.tsx`、`docs/source-analysis.html`。后续同类处理面板应优先考虑“默认贴边，必要时切回画布”的交互。

### 2026-05-14 · 视频抽帧面板支持删除已抽关键帧

Canvas Panel Frames

问题：视频抽帧面板只能新增关键帧，用户看到“已抽关键帧”后不能在同一工作上下文里清理误抽的帧。

改动：已抽关键帧缩略图右上角增加删除按钮，点击后按 `jobId + frameIdx` 删除对应关键帧；删除期间显示小号 loading。图片类素材仍沿用快速删除策略，不弹确认。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。视频抽帧面板不再依赖当前 active job 来决定删除目标。

### 2026-05-14 · 吸附工作面板贴近视口边缘

Canvas Panel Dock

问题：视频抽帧面板吸附左侧 / 右侧时顶部仍留出明显空白；这不是实际板块遮挡，而是面板吸附样式里硬编码了 `top: 72` 和对应的高度预留。关键帧面板也保留了旧 storyboard 顶栏避让逻辑。

改动：新增统一吸附边距常量，视频抽帧面板和关键帧详情面板吸附时都贴近视口边缘，仅保留 8px 安全边距；移除关键帧面板对旧 `data-storyboard-dock` / `data-storyboard-bar` 的避让查询。

影响：`web/components/nodes/index.tsx`、`docs/source-analysis.html`。后续画布工作面板的吸附语义统一为“贴边”，不是为顶部旧板块预留空间。

### 2026-05-14 · 输入视频双击改为画布抽帧面板

Canvas Panel Input

问题：输入视频缩略图双击原来只在 Input 节点上方展开一个临时播放器，不能作为无限画布工作台移动、找回或吸附，后续其他板块也无法复用这种交互。

改动：新增 `videoFramePanel` ReactFlow 节点和 `VideoFramePanelNode`。双击输入视频缩略图会打开/找回画布内抽帧面板，面板可拖动、右下角缩放，也可一键吸附到左侧、右侧或底部边缘；面板内支持播放、时间轴定位、当前时间抽帧和查看已抽关键帧。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。原固定全屏 `VideoLightbox` 不再从 Input 双击路径进入；后续处理板块应复用同类画布工作面板语义。

### 2026-05-14 · Hover 大预览尺寸信息增强

Canvas HoverPreview

问题：原始尺寸和 Fit 比例之前是左上角小号单行文字，用户在快速扫缩略图时不够醒目，无法马上感知素材分辨率差异。

改动：`HoverPreview` 左上角改为两层信息徽章：标题固定为“原始尺寸”，主数字用大号等宽字体显示 `宽 × 高`，旁边保留 `Fit` 百分比或 `1:1 原寸` 状态。

影响：`web/components/nodes/hover-preview.tsx`、`docs/source-analysis.html`。定位和 Fit / 1:1 行为不变，只提升尺寸信息可读性。

### 2026-05-14 · 删除确认改为页面内分层交互

Canvas UX

问题：浏览器原生删除确认会突然出现在页面顶部，和无限画布的操作上下文割裂；图片类素材如果每次删除都确认，也会拖慢快速整理素材的节奏。

改动：输入视频和生成视频任务删除改为画布内确认层，背景轻遮罩并支持点击背景 / Esc 取消；关键帧和元素提取图属于可快速整理的图片素材，点击删除后直接执行。

影响：`web/components/nodes/index.tsx`、`docs/source-analysis.html`。视频删除仍走既有删除接口；图片删除仍走原有回调，只调整确认策略。

### 2026-05-14 · 输入视频缩略图支持删除整个 job

Input API

问题：画布顶部输入视频缩略图只有切换和预览，没有删除入口；用户清理视频队列时只能删关键帧或生成视频任务，不能删除整个输入视频。

改动：新增 `DELETE /jobs/{id}`，前端新增 `deleteJob` 和 `onDeleteJob`；Input 缩略图右上角常驻删除按钮，确认后移除该 job、清理 URL 参数，并删除本地 `jobs/<id>` 目录。

影响：`api/main.py`、`web/lib/api.ts`、`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 大图预览改为尺寸感知 Fit / 1:1

Canvas HoverPreview

问题：有些源视频和图片分辨率很大，完全按原尺寸展示会撑爆画布；但统一固定预览大小又会丢失素材真实尺寸感知。

改动：`HoverPreview` 默认按原比例适应可视区域，角标显示原始分辨率和当前 Fit 百分比；点击钉住后可切换到 `1:1`，超大素材在预览框内滚动查看局部。

影响：`web/components/nodes/hover-preview.tsx`。视觉缩略图高度同步放大，图片缩略图的复制 / 删除按钮改为常驻大号 icon。

### 2026-05-14 · 缩略图滑动条改为大号可拖轨道

Canvas Thumbnail

问题：节点上方缩略图横排内容多时，原生横向滚动条太细且在画布缩放下不容易点中，用户很难拖动。

改动：新增 `FloatingThumbnailStrip` / `ThumbnailScrollRail`，在缩略图下方显示明显的大号紫色拖动轨道；轨道支持点击跳转、按住拖动和键盘左右移动，并用 `nodrag nopan` 避免误触发画布拖拽。

影响：`web/components/nodes/index.tsx`、`web/app/globals.css`、`docs/source-analysis.html`。Input、VisualLab 以及保留的旧视觉节点缩略图条共用同一交互。

### 2026-05-14 · 三个视觉节点合并为画面工作台

VisualLab Canvas

问题：镜头拆解、元素改造、生成视频三个卡片在主画布上占同等权重，但它们只是视觉素材状态展示和入口；真正处理都在点击后的工作台/面板中完成。

改动：新增 `VisualLabNode`，把关键帧、元素 cutout、视频任务缩略图合并到一个“画面工作台 · Visual Lab”卡片里；DAG 从 `Input → Keyframe → Storyboard → VideoGen → Compose` 简化为 `Input → VisualLab → Compose`，音频线仍独立。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。底层数据、接口和旧节点组件暂不删除。

### 2026-05-14 · 修复节点右下角缩放点击偏移

Canvas Resize

问题：点击或轻微拖动卡片右下角缩放把手时，节点会突然偏移/跳变，影响在无限画布上精调卡片大小。

原因：`getComputedStyle(nodeEl).width/height` 读到的已经是 ReactFlow 节点坐标下的布局尺寸，旧逻辑又除了一次 `zoom`，导致拖动起始宽高被放大或缩小；点击时 1px 级 pointermove 也会立刻写入错误宽高。

改动：起始宽高直接使用 computed style，只有鼠标移动量按 zoom 换算；增加 2px 点击死区，单纯点击缩放角不再改写节点尺寸。

影响：`web/components/nodes/resize-handle.tsx`、`docs/source-analysis.html`。

### 2026-05-14 · 缩略图 hover 原尺寸预览贴缩略图上边缘

Canvas HoverPreview

问题：用户要的是“鼠标停在卡片缩略图上时，原尺寸图片/视频在该缩略图上方边缘展示，并且仍属于无限画布”；不能贴节点卡片上边缘，也不能放到页面 fixed 层。

改动：`HoverPreview` 增加缩略图锚点坐标，预览层仍渲染在 ReactFlow 节点 DOM 内，但用缩略图的中心 x 和 top y 定位，预览底边贴缩略图上边缘；Input 视频、镜头拆解关键帧、元素改造 cutout、生成视频缩略图统一走该逻辑。

影响：`web/components/nodes/hover-preview.tsx`、`web/components/nodes/index.tsx`、`docs/source-analysis.html`。

### 2026-05-13 · 打开应用自动恢复历史 job

API Page

问题：前端只从 URL `?job=` 读 job 列表，没有任何本地或后端列表回填，打开 `/` 不带参数就是空白，之前跑过的 job 看不见。

改动：后端新增 `GET /jobs` 列表接口（返回 `JobSummary`：id/url/status/progress/duration/width/height/video_url/frame_count/video_count/thumbnail/error/mtime，按 state.json mtime 倒序，可带 `limit`）。前端 `page.tsx` 启动逻辑：URL 有 `?job=` 时尊重 URL；没有时自动调 `listJobs()` 拿全部历史，反转后让最新 job 落在末尾（active）。持久化基于 `api/jobs/<id>/state.json` 磁盘文件，不依赖浏览器存储，换浏览器/清缓存都不会傻。

影响：`api/main.py`（`JobSummary` 类型 + `list_jobs` endpoint）、`web/lib/api.ts`（`JobSummary` + `listJobs`）、`web/app/page.tsx`（启动 useEffect）。

### 2026-05-13 · 允许骨骼人使用按摩仪后状态变好

Prompt

问题：本轮参考素材的主体可能是人形骷髅/透明骨骼人，不应被提示词强行替换成普通真人；核心是“用了 SKG 颈部按摩仪后状态变好”。

改动：prompt 允许保留人形骷髅作为视觉隐喻，要求正确佩戴 U 形颈部按摩仪，并通过从僵硬/揉脖子/疲惫到抬头/肩颈舒展/放松来表现状态改善；同时禁止恐怖化、血腥化或夸大医疗治愈。

影响：`web/app/page.tsx`。

### 2026-05-13 · 生视频提示词改为产品图优先

Prompt StoryboardWorkbench

问题：已经有真实 SKG 产品图后，提示词还偏“借鉴原视频”，容易让模型保留竞品或改变产品形态。

改动：生成视频 prompt 明确“上传的 SKG 产品图是唯一产品真源”，首尾帧只控制起止构图、场景和动作，原视频链接只参考节奏和镜头调度；增加产品一致性、产品呈现、禁止非 SKG 产品/竞品包装/随机新增结构等约束。

影响：`web/app/page.tsx`。

### 2026-05-13 · 产品参考支持本地上传和拖拽

StoryboardWorkbench API

问题：SKG 产品参考不能只依赖从关键帧/元素里复制，用户需要手动上传同一产品的多角度图。

改动：`SKG 产品参考` 区支持点击上传和拖拽上传图片，一次可传多张，最多保留 6 张。后端新增 `POST /jobs/{job_id}/assets` 保存产品图资产，并返回 `kind: "asset"` 的 `ImageRef`；生成视频时这些资产会作为产品参考传入 Ark。

影响：`web/components/storyboard-workbench.tsx`、`web/lib/api.ts`、`api/main.py`。

### 2026-05-13 · 首尾帧编排增加 SKG 产品槽

StoryboardWorkbench API

问题：首尾帧可以控制视频起止，但还需要单独指定 SKG 产品图，避免模型只模仿原视频动作而没有稳定产品外观。

改动：分镜编排区新增 `SKG 产品` 槽，和首帧、尾帧并列；生成视频时把该槽作为 `product_image` 提交。Ark 请求会附加一张 `reference_image` 产品参考图；如果接口不接受额外参考图，后端自动回退到首尾帧生成。

影响：`web/components/storyboard-workbench.tsx`、`web/app/page.tsx`、`api/main.py`。

### 2026-05-13 · 分镜编排改为首尾帧生成

StoryboardWorkbench API

问题：赶交付时，顶部横向分镜缩略条占空间，4 图槽也不如“首帧到尾帧”直接；用户希望直接做首尾帧视频生成。

改动：移除 `StoryboardBar` 的横向分镜缩略图区域，只保留标题栏和展开按钮；`StoryboardWorkbench` 改成首帧 / 尾帧两个槽，首帧默认当前分镜，尾帧默认下一张已选分镜，也可从剪贴板粘贴指定结束画面。后端 `/storyboard/video` 支持 `first_image`/`last_image`，Ark 请求同时传 `first_frame`/`last_frame`，如果接口不接受尾帧字段则自动回退到单首帧。

影响：`web/components/storyboard-bar.tsx`、`web/components/storyboard-workbench.tsx`、`web/app/page.tsx`、`web/lib/api.ts`、`api/main.py`。

### 2026-05-13 · 生视频携带原视频链接做节奏参考

StoryboardWorkbench API

问题：用户赶交付，希望直接把上传的原视频链接给视频模型参考，而不是只靠单张关键帧。

改动：前端提交生视频时增加 `source_ref: { kind: "source_video", url: job.url }`；Ark 请求体在文本 prompt 和首帧之外追加 `video_url` 参考视频，用于模仿节奏、镜头运动和动作顺序。如果 Ark 返回 400/422 不接受参考视频字段，后端自动回退到“当前关键帧首帧生成”，保证这次不会直接阻断出片。

影响：`web/app/page.tsx`、`web/lib/api.ts`、`api/main.py`、`docs/source-analysis.html`。

### 2026-05-13 · 快速出片改为关键帧直生视频

StoryboardWorkbench Prompt

问题：赶交付时不适合再让 4 图槽决定首帧；如果某个槽里是抠图元素，模型会拿碎元素当第一帧，视频容易不连贯。

改动：“生成视频”按钮改成直接用当前分镜关键帧作为首帧提交，4 图槽和改造目标只作为提示词参考；提示词强调一镜到底、首帧稳定、时间线连续、禁止跳切/换场景/主体变形。后端取关键帧时优先使用未应用的清洗版，否则使用当前 frame 文件。

影响：`web/app/page.tsx`、`web/components/storyboard-workbench.tsx`、`api/main.py`。

### 2026-05-13 · 生视频支持火山方舟 Ark 异步任务

VideoGenNode API

问题：用户提供火山方舟 `https://ark.cn-beijing.volces.com/api/v3` 作为生视频通道；这个通道不是 Poe 的 `/videos` 形态，而是内容生成异步任务。

改动：后端识别 Ark base 后，提交改为内容生成任务接口，火山方舟直连使用 `POST /contents/generations/tasks`，SKG 豆包网关使用 `POST /api/v3/contents/generations/tasks`。请求体使用 `content` 数组：文本 prompt + 首帧 `image_url` data URL；轮询对应的 `{id}` 任务地址，成功后读取 `content.video_url` 下载 MP4。本机默认 Seedance 模型改为 Ark 可见的 `doubao-seedance-2-0-fast-260128`。

影响：`api/main.py`、`api/.env.example`、`docs/source-analysis.html`。本机 `api/.env` 需要把 `VIDEO_API_BASE_URL`/`VIDEO_API_KEY`/`VIDEO_CREATE_PATHS`/`VIDEO_STATUS_PATH` 指向 Ark。

### 2026-05-13 · 生视频改接 Poe 视频模型

VideoGenNode API

问题：SKG ezlink 的 OpenAI 兼容 base 可列出部分模型，但常规 `/videos` 入口返回 404/unsupported；用户确认可用的视频模型在 Poe 通道里。

改动：后端新增 `POE_API_BASE_URL`/`POE_API_KEY` 配置，未显式配置 `VIDEO_API_BASE_URL` 时优先走 Poe；Seedance / Kling / Veo/Voe 业务别名默认映射到 Poe 真实模型 `seedance-2-fast`、`kling-omni`、`veo-3.1-fast`。Poe 提交使用 `input_image` base64，继续轮询 `/videos/{id}` 并下载 `/videos/{id}/content`。

影响：`api/main.py`、`api/.env.example`、`docs/source-analysis.html`。密钥只放本地 `api/.env`，不进入源码解析页。

### 2026-05-13 · 生视频提交不再被前端锁死

StoryboardWorkbench API

问题：虽然当前探测到常见视频入口返回 404/unsupported，但模型层确实有视频模型，不能在前端简单判定“未开通”并禁用。

改动：撤掉分镜编排里的前置禁用；后端允许提交 seedance / kling / veo / voe，并支持通过 `VIDEO_CREATE_PATHS` 逗号分隔配置多个候选生成入口，逐个尝试。

影响：`api/main.py`、`api/.env.example`、`web/app/page.tsx`、`web/components/storyboard-workbench.tsx`。

### 2026-05-13 · 生视频错误提示改为可读原因

VideoGenNode API

问题：提交生视频失败时，前端把 `generateStoryboardVideo 503 {"detail": ...}` 原样展示，用户无法快速判断是配置、端点还是 UI 问题。

改动：`generateStoryboardVideo` 解析后端 JSON 的 `detail` 后再抛错；后端错误文案区分“模型存在”和“入口不可用”；Video Gen 失败卡把 `/videos 404` 长错误压缩成一句可读原因。

影响：`web/lib/api.ts`、`web/components/nodes/index.tsx`、`api/main.py`。

### 2026-05-13 · Video Gen 卡片增加复制和删除

VideoGenNode API

问题：Video Gen 节点上方失败/完成任务卡只有整卡点击复制，不够明确；失败任务也无法从界面清掉。

改动：每个视频任务卡左上角增加复制 prompt 按钮，右上角增加删除任务按钮；后端新增 `DELETE /jobs/{job_id}/storyboard-videos/{video_id}`，删除 `generated_videos` 记录并清理本地任务目录。

影响：`web/components/nodes/index.tsx`、`web/app/page.tsx`、`web/lib/api.ts`、`api/main.py`。

### 2026-05-13 · 分镜编排接入真实生视频任务

StoryboardWorkbench VideoGenNode

问题：4 图槽已经粘贴参考图后，用户要直接调用生视频 API，而不是只生成 prompt 或图片任务。

改动：分镜编排明细区增加 Seedance / Kling / Veo 3 模型选择和“调用模型生成视频”按钮；后端新增 `/jobs/{job_id}/frames/{idx}/storyboard/video`。提交后按 `VIDEO_CREATE_PATHS` 逐个尝试生成入口，成功后轮询并保存 MP4；失败时保留任务卡和具体入口错误，方便继续排查网关实际路径。`VideoGenNode` 读取 `job.generated_videos` 展示排队、生成中、失败和完成视频。

影响：`api/main.py`、`api/.env.example`、`web/components/storyboard-workbench.tsx`、`web/components/nodes/index.tsx`、`web/app/page.tsx`、`web/lib/api.ts`。Sora 不再作为默认模型；真实模型 ID 通过 `VIDEO_MODEL_SEEDANCE`、`VIDEO_MODEL_KLING`、`VIDEO_MODEL_VEO3` 配置，真实视频 API 地址通过 `VIDEO_API_BASE_URL`/`VIDEO_API_KEY` 配置。

### 2026-05-13 · 分镜编排下拉区支持上推缩小

StoryboardWorkbench

问题：分镜编排明细区默认占用太多顶部面积，展开后下方画布空间不足。

改动：明细区默认高度降为 320px，并增加底部拖拽手柄，可上推缩到 180px，也可下拉放大查看完整内容。

影响：`web/components/storyboard-workbench.tsx`。

### 2026-05-13 · 分镜缩略图条与编排明细合并为一个下拉区

StoryboardBar StoryboardWorkbench

问题：顶部分镜缩略图条和下方内嵌工作台都带分镜导航，看起来像两个不同板块。

改动：`StoryboardBar` 成为唯一分镜导航；`StoryboardWorkbench` 移除自己的标题栏、左侧分镜列表和底部快捷栏，只保留当前分镜的 4 图槽与改造目标明细。

影响：`web/components/storyboard-bar.tsx`、`web/components/storyboard-workbench.tsx`、`web/app/page.tsx`。

### 2026-05-13 · 分镜头编排工作台改为内嵌下拉

StoryboardWorkbench StoryboardBar

问题：元素改造节点等入口仍会打开 `fixed inset-0` 的全屏 `StoryboardWorkbench`，用户感觉像跳转页面。

改动：移除 `StoryboardWorkbench` 的 portal 全屏承载方式，改为渲染在顶部分镜栏下方；所有“打开编排”入口只展开这个内嵌区域。

影响：`web/components/storyboard-workbench.tsx`、`web/components/storyboard-bar.tsx`、`web/app/page.tsx`、`web/components/nodes/index.tsx`。

### 2026-05-13 · 钉住面板停靠到分镜头编排边缘

KeyframePanelNode StoryboardBar

问题：关键帧详情钉住在浏览器左侧固定位置时，会遮挡顶部分镜头编排栏展开后的缩略图区域。

改动：给 `StoryboardBar` 增加稳定 DOM 标记；钉住面板实时读取该区域下边缘，并吸附到其下方。展开 / 折叠分镜头编排时，钉住面板自动让位。

影响：`web/components/storyboard-bar.tsx`、`web/components/nodes/index.tsx`。

### 2026-05-13 · 顶部分镜头编排不再跳转全屏工作台

StoryboardBar

问题：顶部 `StoryboardBar` 的“进入编排”和分镜缩略图点击会打开全屏 `StoryboardWorkbench`，打断当前画布流程。

改动：顶部按钮改为“展开编排”，只下拉展示当前分镜列表；缩略图点击只聚焦该分镜，不再触发全屏跳转。后续已把工作台整体改成内嵌下拉，见上方最新记录。

影响：`web/components/storyboard-bar.tsx`、`web/app/page.tsx`。

### 2026-05-13 · 钉住关键帧详情改为左侧停靠

KeyframePanelNode

问题：钉住后仍像自由浮层一样停在画布附近，用户继续缩放画布或调整面板尺寸时容易把它和画布节点混在一起。

改动：钉住后统一吸附到浏览器左侧边缘，脱离 ReactFlow 画布缩放；钉住瞬间把当前可见大小转换成面板真实尺寸，之后只由右下角拖拽或标题栏按钮调整。

影响：`web/components/nodes/index.tsx`；钉住语义从“原地浮在上层”改为“左侧停靠工作面板”。

### 2026-05-13 · 关键帧详情支持右下角拖拽缩放和上层钉住

KeyframePanelNode

问题：只有按钮缩放不够直观；钉住后仍作为画布节点，会继续随 ReactFlow 画布缩放。

改动：增加右下角拖拽缩放手柄；钉住时通过 portal 固定到浏览器上层，脱离 ReactFlow 画布缩放和平移。

影响：`web/components/nodes/index.tsx`、`web/app/page.tsx`；未钉住时仍是画布节点，钉住后保持屏幕固定位置。

### 2026-05-13 · 关键帧详情面板增加钉住按钮

KeyframePanelNode

问题：面板可以拖动后，用户仍可能误拖；切换图片时希望保持固定工作位置。

改动：在标题栏增加钉子按钮。钉住后面板节点禁止拖动，切换关键帧只切换内容不移动位置；取消钉住后可继续拖动。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`。

### 2026-05-13 · 切换关键帧不再重置详情面板位置

KeyframePanelNode

问题：用户把关键帧详情面板拖到合适位置后，再点击下一张关键帧会把面板拉回默认位置，造成视觉疲劳。

改动：已打开的面板只切换内容，不移动位置；只有面板不存在、首次打开时才放到默认位置并自动聚焦。

影响：`web/app/page.tsx`；关闭后重新打开仍会出现在默认位置。

### 2026-05-13 · 关键帧详情面板增加缩放控制

KeyframePanelNode

问题：关键帧详情面板作为画布节点后可以随画布缩放，但面板自身没有尺寸控制，用户无法单独放大或缩小它。

改动：在面板标题栏增加 `-`、百分比重置、`+` 控制，支持 75% 到 135% 的面板级缩放。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`；点击新关键帧仍会找回到默认位置，缩放比例保留。

### 2026-05-13 · 关键帧详情从固定左侧抽屉迁到无限画布

KeyframeNode

问题：关键帧详情 / 元素提取面板固定在左侧 drawer，和 ReactFlow 无限画布割裂，也不会跟随画布缩放。

改动：移除主页面隐藏渲染的 `Dashboard` drawer 承载方式，新增独立 `keyframePanel` ReactFlow 节点来挂载 `FrameLightbox`。

影响：`web/app/page.tsx`、`web/components/nodes/index.tsx`；点关键帧后面板默认出现在流程左侧空白画布里，不遮挡 Input / Keyframe 主节点；标题栏可拖动，跟随 ReactFlow 平移和缩放。再次点击关键帧缩略图会把面板找回到默认位置，并自动把视野拉到“关键帧 + 面板”。

### 2026-05-13 · 元素改造 hover 预览简化为原帧预览

StoryboardNode

问题：元素改造节点的 hover 预览虽然已改为节点内显示，但仍比关键帧节点复杂，多了“来源原帧 / 提取元素”两栏和元素名称，信息过载。

改动：改成和镜头拆解关键帧一致的简单预览：只显示来源原帧，底部显示分镜编号和时间。

影响：`web/components/nodes/index.tsx`；元素改造板块 hover 现在更轻，不干扰当前判断。

### 2026-05-13 · 元素改造 hover 预览改为节点内效果

StoryboardNode

问题：上一版把元素预览用 `createPortal` 挂到 `body`，DevTools 里会出现额外 fixed 层，交互形态和关键帧节点不一致。

改动：改成节点内 `group-hover` 预览，不再向 `body` 插入预览层。后续又简化为只展示来源原帧，见上方最新记录。

影响：`web/components/nodes/index.tsx`；元素改造板块的 DOM 和交互效果更接近关键帧缩略图。

### 2026-05-13 · 新增独立源码解析与协作地图

docs

目的：把产品功能区、源码位置、接口、数据模型、需求描述方式固定下来，减少“描述不准导致改偏”。

影响：新增 `docs/source-analysis.html`，不接入 Next 应用，不影响工作台运行。

以后描述：可以直接引用本页的功能区名称、节点职责和源码文件名。

### 2026-05-13 · Storyboard 元素缩略图 hover 预览修复

StoryboardNode

问题：元素改造节点上方小图 hover 没有像镜头拆解节点一样显示原图预览，并且首次修复时出现运行时错误。

原因：节点内部 overflow 裁剪了预览；随后 portal 预览里把变量写成了不存在的 `aspectRatio`。

影响：`web/components/nodes/index.tsx`。该记录之后又改为节点内预览，见上方最新记录。

### 2026-05-13 · 元素识别结果不再锁死

元素提取

问题：Vision 识别可能错，但元素列表像最终结果；点击提取图会跳页面，打断用户思路。

改动：支持元素改名、改英文提示、改位置、删除元素、重复提取、删除单张提取图；提取图不再用链接跳新页。

影响：`FrameLightbox`、`web/lib/api.ts`、`PATCH /jobs/{job_id}/frames/{idx}/elements/{element_id}`。

### 2026-05-13 · 分镜编排入口聚焦到具体分镜

StoryboardWorkbench

问题：从 Storyboard 或顶部分镜条进入编排时，没有明确定位到用户正在看的那一帧。

改动：工作台接受 `focusedFrame`，点击缩略图会打开工作台并聚焦对应分镜。

影响：`page.tsx`、`StoryboardBar`、`StoryboardWorkbench`、`StoryboardNode`。

### 2026-05-13 · 视觉管线不再被 ASR 阻断

Pipeline

问题：SKG 网关 audio 不通时，视觉解析也容易被标记失败。

改动：`analyze` 主流程强调拆轨和关键帧，声音文案轨独立处理。

影响：`api/main.py`、`page.tsx`、节点语义说明。

## 更新规则

以后任何改动只要影响产品理解、节点职责、界面行为、数据模型、API、运行方式或用户操作路径，都要同步更新本页的对应章节和“变更记录”。

改动类型 | 必须更新本页哪里 | 原因
--- | --- | ---
看板文案 / 工作区功能 | 业务管线、节点职责边界、界面区域到源码、变更记录 | 避免用户按旧节点理解描述需求。
新增 / 修改接口 | 接口地图、数据模型、变更记录 | 避免前后端契约不清。
新增数据字段 | 数据模型、源码结构地图、变更记录 | 刷新恢复和 state.json 依赖字段一致。
改交互路径 | 界面区域到源码、需求描述模板、变更记录 | 用户描述“点击哪里”时必须和真实路径一致。
修 bug | 变更记录；如果暴露新坑，也更新当前已通与阻塞 | 让后续同类问题能快速定位。