# SKG TK 二创验证 — 当前状态（2026-05-18）

## 一句话
SKG 信息流广告快速复刻工作台：TK 链接/上传 → 下载源视频 → 并行音频解析与 12 张动作/节奏参考帧 → 相似主体 / 产品素材池 → 分镜口播改写 → 首尾帧审核 → 视频候选待开放。当前主流程不直接批量提交视频模型。

## 路径 / 端口
- 路径：`~/Projects/business/20260512-20260512-skg-tk-二创验证/`
- web dev：`cd web && pnpm dev`（端口 **4290**）
- api dev：`cd api && source .venv/bin/activate && uvicorn main:app --port 4291 --reload`
- 测试 job：`?job=c6767f3a166b`（chrisorb 71s 竖屏 TK）

## SKG 网关能力（实测 · 关键！）
`base_url: https://ai.skg.com/ezlink/v1`
key 写在 `api/.env` 的 `LLM_API_KEY`

| 端点 / 字段 | 状态 | 用途 |
|---|---|---|
| 远端 ASR | `ASR_MODEL=whisper-1` | 第一优先级音频转写；失败后进本机 ASR。 |
| 本机 ASR | `LOCAL_ASR_MODEL=mlx-community/whisper-tiny` | 二级兜底，优先产出真实逐句时间轴。 |
| ASR 兜底 / 音频分析 | `ASR_FALLBACK_MODEL=gemini-2.5-flash` | 远端和本机都失败后才做多模态 ASR；音频画像会读取 `audio.wav` + 转写时间轴，失败则本地估算。后端会拒绝假字幕、重复文本和覆盖率过低结果。 |
| 字幕翻译 | `TRANSLATE_MODEL=gemini-2.5-flash` | 按 ASR 段落补中文；失败时保留英文时间轴，中文可为空。 |
| 画面理解 / brief | `VISION_MODEL=gpt-4o` | 关键帧 Vision 和相似主体非身份化 brief 已切 GPT；旧环境若写 `gemini-*` 会自动归一化到 `GPT_TEXT_MODEL`。 |
| 通用改写 / 分镜描述 | `REWRITE_MODEL=gpt-4o` | 已切 GPT；旧 Gemini 覆盖值会自动归一化。 |
| 新口播改写 | `AUDIO_REWRITE_MODEL=gpt-4o` | 默认跟随 `REWRITE_MODEL`；失败后依次尝试 `ASR_FALLBACK_MODEL`、`TRANSLATE_MODEL`，再用本地模板兜底。 |
| 产品视角识别 | `PRODUCT_VIEW_MODEL=gpt-image-2` | 多图批量识别；失败后单图重试，再写本地默认视角和风险备注。 |
| 所有生图 / 修图 | `gpt-image-2` | 服务端硬锁，无其他图片模型 fallback；覆盖关键帧生图、水印清理、元素提取、主体资产包、产品补角度、首尾帧。 |
| 配音 | `VOICE_PROVIDER=azure_openai` + `AZURE_TTS_MODEL=gpt-4o-mini-tts` | 语音固定 Azure OpenAI TTS。后端会按 `AZURE_TTS_PATHS` 依次尝试路径，便于区分路径错误和整条语音服务不可用。 |
| 视频 | `VIDEO_MODEL=seedance`，别名支持 `kling-omni`、`veo-3.1-fast` | 当前主流程暂停直接提交；真实 ID 由 `VIDEO_MODEL_SEEDANCE` / `VIDEO_MODEL_KLING` / `VIDEO_MODEL_VEO3` 配置，入口按 `VIDEO_CREATE_PATHS`。 |

**网关后端 = one-hub 多渠道代理**。当前 key 分组叫「纯OpenAI+AWSClaude+Gemini官方」，缺 audio 渠道（`gpt-4o-audio-preview` 503 "无可用渠道"）和 video 渠道。

## 模型选型（运行时默认 / 归一化后）
```
ASR_MODEL=whisper-1
LOCAL_ASR_MODEL=mlx-community/whisper-tiny
ASR_FALLBACK_MODEL=gemini-2.5-flash
TRANSLATE_MODEL=gemini-2.5-flash
GPT_TEXT_MODEL=gpt-4o
VISION_MODEL=gpt-4o
REWRITE_MODEL=gpt-4o
AUDIO_REWRITE_MODEL=gpt-4o
IMAGE_MODEL=gpt-image-2
PRODUCT_VIEW_MODEL=gpt-image-2
SUBJECT_ASSET_IMAGE_MODEL=gpt-image-2
VOICE_PROVIDER=azure_openai
AZURE_TTS_MODEL=gpt-4o-mini-tts
VIDEO_MODEL=seedance
VIDEO_MODEL_KLING=kling-omni
VIDEO_MODEL_VEO3=veo-3.1-fast
```

## Pipeline 状态（9 步工作台版）
当前主入口是信息流复刻工作表，不再是旧 ReactFlow 八节点主画布。

| 步 | 节点 | 状态 | 备注 |
|---|---|---|---|
| 1 | **素材输入** | ✅ | TK 链接 / 上传视频；失败素材可重新下载。 |
| 2 | **源视频下载** | ✅ | yt-dlp + cookies 配置；上传视频直接进入 downloaded。 |
| 3 | **音频文案** | ✅ | 拆 `audio.wav`，ASR、翻译、讲话人 / 节奏 / 背景音画像。 |
| 4 | **抽帧参考** | ✅ | 下载完成后自动抽 12 张动作/节奏参考帧；支持当前播放点手动补帧。 |
| 5 | **相似主体** | ✅ | GPT 视觉 brief + `gpt-image-2` 文字生图，生成类似但不复刻的人物/透明骨架主体。 |
| 6 | **产品素材池** | ✅ | 不限量上传；`gpt-image-2` 识别视角 / 用途 / 风险，缺角度可补图。 |
| 7 | **分镜文案** | ✅ | 按逐句时间轴生成行，可单段或整片 GPT 改写；保存后写入 storyboard action。 |
| 8 | **画面首尾帧** | ✅ | 用相似主体视图 + 产品素材池生成首帧/尾帧，审核后保存规划。 |
| 9 | **视频候选** | ⏸️ | 历史候选可看；主流程当前暂停直接提交视频模型。 |

## UI 架构（重要）
- 主入口：`web/components/ad-recreation-board.tsx`，左侧素材输入列 + 右侧信息流复刻工作表。
- 工作流条：01 素材输入 → 02 源视频下载 → 03 音频文案 → 04 抽帧参考 → 05 相似主体 → 06 产品素材池 → 07 分镜文案 → 08 画面首尾帧 → 09 视频候选。
- 源视频工作区：左侧 9:16 原视频播放器，内置当前点抽帧；右侧音频波形 + 逐句时间轴 + 参考帧池。
- 相似主体：模板库 / 内置形象 / 源视频相似方向；生成结果统一用媒体素材卡，支持 hover 放大、删除、单张重生。
- 分镜工作台：产品素材池、逐句口播、画面规划、首尾帧和历史视频候选在同一纵向工作表里处理。
- 旧 ReactFlow 节点、旧 lightbox、旧 storyboard workbench 底层保留，但当前不作为主入口。

## 数据模型（关键 typescript / pydantic）
```typescript
KeyFrame {
  index: number              // 稳定 ID（不连续！frames 数组按 timestamp 排序）
  timestamp: number
  url: string
  description?: {
    scene, objects: [{name, position, color, extract_prompt}],
    style, suggested_prompt
  }
  generated_images?: [{ id, prompt, model, mode, url, selected, created_at }]
}

Job { frames: KeyFrame[] ... }
```

**前端取帧必须用 `frames.find(x => x.index === activeIndex)` 不能用数组下标**（之前的 bug）。

## 关键文件
- `web/app/page.tsx` — 多 job state 管理（jobs[] + activeJobId），开始后并行触发音频解析和 12 张视觉抽帧
- `web/components/ad-recreation-board.tsx` — 当前主工作台：素材输入、音频结果、参考帧池、相似主体、产品素材池、分镜规划和首尾帧
- `web/components/media-asset-tile.tsx` — 图片 / 视频 / 抽帧 / 产品图 / 主体图 / 首尾帧 / 视频候选统一媒体卡
- `web/components/dashboard.tsx` — 旧 ReactFlow / Kanban 面板，底层保留但当前不作为主入口
- `web/components/lightbox.tsx` — 旧深度素材面板，底层保留
- `web/components/video-lightbox.tsx` — Input 节点点视频缩略图弹的播放器
- `web/components/nodes/index.tsx` — ReactFlow 8 节点定义
- `web/lib/api.ts` — API client
- `api/main.py` — FastAPI 所有端点，Job/KeyFrame/AudioScript/ProductRef/SubjectAsset/SceneAsset/GeneratedVideo 模型

## 已通的 API 端点
```
POST /jobs                                       创建 job（链接）
POST /jobs/{id}/download/retry                  TK 链接下载失败后重新下载
POST /jobs/upload                                上传视频
GET  /jobs/{id}                                  job 状态
POST /jobs/{id}/transcribe                       音频提取 + ASR + 翻译 + 讲话人/节奏/背景音分析
POST /jobs/{id}/analyze?frames=12                动作/节奏参考帧抽取
POST /jobs/{id}/frames?t=<sec>                   手动按时间戳加帧
POST /jobs/{id}/frames/{idx}/describe            ✅ Vision 识别（3 次重试 + reasoning_content 兜底）
POST /jobs/{id}/frames/{idx}/generate            ✅ 生图（i2i / text-only, 含 negative_prompt）
GET  /jobs/{id}/frames/{idx}/gen/{gen_id}.jpg    生成图二进制
POST /jobs/{id}/frames/{idx}/gen/{gen_id}/select 选用某 gen 给下游
POST /jobs/{id}/assets/product-views/analyze     产品视角 / 用途 / 风险识别
POST /jobs/{id}/assets/product-angle             缺产品角度补图
POST /jobs/{id}/script/rewrite                   单段 / 整片新口播改写
POST /jobs/{id}/frames/{idx}/scene-asset         首帧 / 尾帧 / 场景资产生成
GET  /jobs/{id}/video.mp4                        原视频
GET  /jobs/{id}/audio.wav                        原音频 wav
GET  /jobs/{id}/frames/{idx}.jpg                 关键帧 jpg
GET  /health
```

## 当前约束 / 不要踩
1. 图片 / 视频 / 抽帧 / 产品图 / 生成图 / 首尾帧 / 视频候选缩略图默认复用 `web/components/media-asset-tile.tsx`。
2. 所有生图入口服务端只允许 `gpt-image-2`，不要重新加 Gemini 图片模型或其他 fallback。
3. 画面理解和文案改写默认归 GPT：`VISION_MODEL`、`REWRITE_MODEL`、`AUDIO_REWRITE_MODEL` 会拦截旧 `gemini-*` 覆盖值。
4. Gemini 仍保留在 ASR fallback / 音频分析 / 翻译链路，不要误删。
5. 语音只走 Azure OpenAI TTS；不要新增或依赖其他配音通道配置。
6. TikTok 受限下载遇到 `Log in for access` 不是后端没接到任务；需要 `YTDLP_COOKIES_FILE` 或 `YTDLP_COOKIES_FROM_BROWSER`，配置后可点“重新下载”。
7. 当前主流程不直接批量提交视频；先走“分镜规划 → 首尾帧 → 人工审核”。
8. 后端长任务不要用 `--reload`。
9. 关键帧 `index` 是稳定 ID，不等于数组下标；前端取帧用 `frames.find(x => x.index === idx)`。

## 最近变更
- 2026-05-18：前端模型链路弹窗、`.project.json`、`api/README.md` 和本状态文档已按真实后端链路重写：音频三级 ASR、翻译失败行为、音频画像兜底、产品识别重试、相似主体 GPT brief + gpt-image-2 文字生图、脚本改写本地模板兜底、视频主入口暂停。
- 2026-05-18：清理个人语音通道残留，`/health`、前端类型、环境模板和文档不再暴露相关字段或配置。
- 2026-05-18：`VISION_MODEL`、`REWRITE_MODEL`、`AUDIO_REWRITE_MODEL` 切到 GPT 默认模型 `gpt-4o`，并加旧 Gemini 环境变量归一化保护。
- 2026-05-18：语音通道固定 Azure OpenAI TTS，并按 `AZURE_TTS_PATHS` 尝试语音路径。
- 2026-05-18：TikTok 受限链接支持 cookies 配置和失败素材“重新下载”。
- 2026-05-18：媒体素材交互统一收口到 `MediaAssetTile`。
- 2026-05-18：产品图视角识别和产品缺角度补图收敛到 `gpt-image-2`。
