172 lines
11 KiB
Markdown
172 lines
11 KiB
Markdown
|
|
---
|
|||
|
|
name: guanghuclip-video-generate
|
|||
|
|
type: reference
|
|||
|
|
topic: 经验库 · Bug修复记录
|
|||
|
|
tcs: ICE-GL-ZY001
|
|||
|
|
created: D131 · 2026-06-12
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# 光湖视频AI · 经验库
|
|||
|
|
|
|||
|
|
每次踩坑修好后的经验记录,铸渊后续遇到类似问题可检索。
|
|||
|
|
|
|||
|
|
## D131 — Seedance 视频生成全链路调试
|
|||
|
|
|
|||
|
|
### Bug 1: 模型名不对 → API 404
|
|||
|
|
- **症状**: 调用火山方舟返回 `404 The model or endpoint XXX does not exist`
|
|||
|
|
- **根因**: 模型名格式错误。不是 `seedance-2-0` 也不是 `seedance-1-5-pro`,正确格式是 `doubao-seedance-2-0-260128`
|
|||
|
|
- **修复**: 修改 `.env` 的 `JIMENG_MODEL` 和 `video-api-adapter.js` 默认值
|
|||
|
|
- **经验**: 火山方舟的所有模型名都以 `doubao-` 开头,后面跟版本号日期。去控制台看开通页面的完整模型ID。
|
|||
|
|
|
|||
|
|
### Bug 2: 安心体验模式额度耗尽
|
|||
|
|
- **症状**: `Your account has reached the set inference limit ... model service has been paused`
|
|||
|
|
- **根因**: 火山方舟开通模型时默认勾选「安心体验」,免费额度极低(几次调用后即耗尽)
|
|||
|
|
- **修复**: 去控制台关闭安心体验模式,切换到付费套餐
|
|||
|
|
- **经验**: 开通任何模型服务后第一步就是关安心体验。想用免费额度测试 = 第一次就烧光。
|
|||
|
|
|
|||
|
|
### Bug 3: API返回了视频URL但代码拿不到
|
|||
|
|
- **症状**: 任务状态 `succeeded`,但代码报 `任务完成但未返回视频地址`
|
|||
|
|
- **根因**: Seedance 2.0 返回结构是 `{ content: { video_url: "..." } }`,代码只检查了 `output.video_url`、`data.data?.output?.video_url` 等旧格式
|
|||
|
|
- **修复**: 在 `queryTask()` 的 videoUrl 提取链最前面加 `data.content?.video_url`
|
|||
|
|
- **经验**: API版本升级时响应结构会变。每次换模型版本,先用 debug 脚本打完整返回确认字段路径。
|
|||
|
|
|
|||
|
|
### Bug 4: 前端请求 /data/videos.json 拿不到JSON
|
|||
|
|
- **症状**: guanghuclip.cn 页面卡"加载中...",JSON返回HTML
|
|||
|
|
- **根因**: videos.json 在 `/root/guanghuclip/frontend/public/data/`,但前端请求 `/data/videos.json`。Nginx root 是 `/root/guanghuclip/frontend/`,所以 `/data/` 映射到 `/frontend/data/` 而不是 `/frontend/public/data/`。`try_files $uri $uri/ /index.html` 兜底回SPA的HTML。
|
|||
|
|
- **修复**: `cp /root/guanghuclip/frontend/public/data/videos.json /root/guanghuclip/frontend/data/videos.json`
|
|||
|
|
- **经验**: 前端 fetch 路径要对照 Nginx root 确认文件实际位置。`public/` 是 Vite 构建时的约定,构建后文件在 dist 里。但如果直接部署源码不走构建,就要手动对齐路径。
|
|||
|
|
|
|||
|
|
### Bug 5: Gatekeeper exec 超时
|
|||
|
|
- **症状**: `curl` Gatekeeper `/exec` 端点一直 timeout,但 `/health` 正常
|
|||
|
|
- **根因**: 本地代理 `127.0.0.1:55931` 阻断新加坡直连
|
|||
|
|
- **修复**: 所有 Gatekeeper curl 加 `--noproxy '*'`
|
|||
|
|
- **经验**: 新加坡四台服务器都有这个问题。记住 `--noproxy '*'` 是必备参数。广州不阻断可不加。
|
|||
|
|
|
|||
|
|
### 工具链验证
|
|||
|
|
```
|
|||
|
|
✅ 腾讯文档 MCP → DeferExecuteTool(mcp__tencent-docs__get_content) → 读分镜
|
|||
|
|
✅ hldp-prompt.js → 台词→Seedance提示词转换
|
|||
|
|
✅ video-api-adapter.js → 提交任务 + 轮询 + 下载
|
|||
|
|
✅ Gatekeeper → curl --noproxy '*' → SG exec → 文件部署
|
|||
|
|
✅ sed 就地修改 → 更新 videos.json videoUrl
|
|||
|
|
⚠️ 前端部署 → Nginx root路径 + fetch路径对齐(已踩坑)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Bug 6: duration参数被忽略 → 始终5秒
|
|||
|
|
- **症状**: 请求10秒视频,API返回5秒。所有请求: resolution=1080p但实际=720p
|
|||
|
|
- **根因**: 旧版API格式 `parameters: { video_length: "10" }`,Seedance 2.0的duration在顶层 `{ duration: 10 }`
|
|||
|
|
- **修复**: 修改 `submitTask()` payload: 移除 `parameters` 包装,`duration` 直接放在根级
|
|||
|
|
- **验证**: 修复后10秒视频生成成功(4.4MB vs 修复前2.2MB)
|
|||
|
|
- **经验**: API每个大版本都可能改参数位置。对照官方curl示例验证payload格式。
|
|||
|
|
|
|||
|
|
### Bug 7: sandbox EPERM 阻止文件写入
|
|||
|
|
- **症状**: Node.js写入 ~/guanghulab/ 目录报 EPERM
|
|||
|
|
- **根因**: WorkBuddy sandbox 限制对用户目录的写操作
|
|||
|
|
- **修复**: 输出文件写入 workspace 目录 `/Users/.../WorkBuddy/.../outputs/`
|
|||
|
|
- **经验**: 文件输出默认放在当前工作区的 outputs/ 下。运行脚本时用 workspace 绝对路径。
|
|||
|
|
|
|||
|
|
### Bug 8: Seedance版权过滤拦截
|
|||
|
|
- **症状**: API返回 `output video may be related to copyright restrictions`
|
|||
|
|
- **触发**: 提示词含具体设备名+破坏性动作(秦山号+砸液压装置)
|
|||
|
|
- **修复**: 去掉命名实体和暴力动词,换中性动作描述
|
|||
|
|
- **经验**: 命名实体+破坏动词=高风险。拆分镜时动作镜避免具体品牌/设备名。超过2次retry失败启用替代方案(黑场过渡)。
|
|||
|
|
|
|||
|
|
### 第一集拼接
|
|||
|
|
- SG FFmpeg: `/usr/bin/ffmpeg` v6.1.1
|
|||
|
|
- ❌ `-c copy` 拼接:MP4格式只粘上部分文件(7镜只出4镜)
|
|||
|
|
- ❌ `cat` 拼接:MP4容器不兼容,播放器只读第一个文件
|
|||
|
|
- ✅ TS流中间格式:`ffmpeg -i in.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts out.ts` → `cat *.ts` → `ffmpeg -i combined.ts -c copy -bsf:a aac_adtstoasc out.mp4`
|
|||
|
|
- ✅ `-c:v libx264` 重编码在低内存服务器会OOM(SIGTERM),优先用TS流无损方案
|
|||
|
|
- 成品: 7镜40秒19MB,已部署guanghuclip.cn
|
|||
|
|
|
|||
|
|
## D136+ — 付费修仙第一集 · 连续性断裂修复
|
|||
|
|
|
|||
|
|
### Bug 9: 道具形态在镜头间断裂 → 招牌竖变横
|
|||
|
|
- **症状**: S1-01天道宗牌匾竖式悬挂 → S1-02同一块牌匾变成了横式。两块牌匾角度/方向完全不同。
|
|||
|
|
- **根因**: 三个镜头共享ENV-002但各自独立生成视频。每个镜头重新理解"悬挂的破旧牌匾"这句话,AI没有镜头间记忆。提示词里没有锁定方向字段。
|
|||
|
|
- **修复**:
|
|||
|
|
1. 建立PROP编号协议(`付费修仙-ep01-props.hdlp`),锁定每个道具的不可变描述文本
|
|||
|
|
2. 导演编码加入 `continuity_locks.props`,锁定 `PROP-天道宗牌匾` 的方向=竖式悬挂、文字=【天道宗】、材质=破旧木质
|
|||
|
|
3. 提示词生成时必须展开PROP锁定的完整描述文本,不可自己重新描述
|
|||
|
|
- **经验**: CHAR和ENV有编号 ≠ 道具也有编号。道具是最容易被观众发现的断裂点——比环境变化敏感100倍。
|
|||
|
|
|
|||
|
|
### Bug 10: 角色外观在镜头间漂移 → 苏白衣服变了
|
|||
|
|
- **症状**: S1-02苏白白色长衫 → S1-03苏白衣服颜色/款式改变,像换了一个人。
|
|||
|
|
- **根因**: 提示词生成Agent在S1-02和S1-03中都给了苏白描述,但没有引用 `characters-v2.hdlp` 的 `CHAR-003` 锁定文本。每次独立展开导致Seedance收到不同的苏白外观描述。
|
|||
|
|
- **修复**:
|
|||
|
|
1. 导演编码中 `char` 字段统一为 `CHAR-003`(不是CHAR-苏白)
|
|||
|
|
2. `continuity_locks.characters.CHAR-003` 中锁定 "白色长衫腰间束带袖口挽起,黑色长发半束半披"
|
|||
|
|
3. 提示词生成时必须从DB展开CHAR的完整锁定文本,展开后做字符串比对校验
|
|||
|
|
- **经验**: 同一CHAR编号 = 同一段锁定的描述文本。展开不一致=直接拦截不送生成。CHAR-003的Seedance提示词片段必须和数据库逐字一致。
|
|||
|
|
|
|||
|
|
### Bug 11: 空间连续性断裂 → "角落"变成建筑死角
|
|||
|
|
- **症状**: S1-01的"角落"被AI理解成一个孤立废弃建筑角落,不是热闹广场人群中被人忽略的边缘位置。导致整条视频的空间布局从一开始就错了。
|
|||
|
|
- **根因**: `environments.hdlp` 的 `ENV-002` 提示词片段中写的是"广场角落里……远离人群"。AI把"远离人群"理解成物理隔离(建筑死角),而不是社会语义(人多的广场里没人注意的角落)。
|
|||
|
|
- **修复**:
|
|||
|
|
1. ENV-002描述从"远离人群"改为"广场上人山人海……在人群边缘的一个角落处"
|
|||
|
|
2. S1-01的 `spatial_anchor` 从"角落里"改为"人群边缘角落里"
|
|||
|
|
3. 导演编码中 `continuity_locks.environments.ENV-002` 锁定完整环境描述
|
|||
|
|
- **经验**: 空间描述中的修饰语("远离人群")会被AI按字面理解。说"人群边缘角落"比"远离人群的角落"准确100倍。
|
|||
|
|
|
|||
|
|
### 连续性架构教训
|
|||
|
|
|
|||
|
|
**管线盲区**: 审核只检查「与原文一致性」,不检查「镜头间连续性」。
|
|||
|
|
```
|
|||
|
|
管线: 拆文 → 分镜 → 审核(←只查原文) → 提示词 → 生成 → 拼接
|
|||
|
|
↑
|
|||
|
|
连续性检查应该在这里
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修复方案**(D136+实施):
|
|||
|
|
1. **PROP编号协议** — 道具也纳入HLDP编号体系(补上CHAR/ENV/PROP三角最后一环)
|
|||
|
|
2. **导演编码加 continuity_locks** — 每个连续镜组锁定共享CHAR/ENV/PROP的不可变描述
|
|||
|
|
3. **提示词生成前展开校验** — Agent_04展开所有编号引用时,做字符串比对:如果展开的CHAR-003文本 ≠ DB里的CHAR-003原文 → 拦截不送
|
|||
|
|
4. **每个CHAR/ENV/PROP只写一遍** — 在DB里锁定,所有镜头的提示词都展开同一段文本。输入一致性=输出一致性最大化的前提
|
|||
|
|
|
|||
|
|
**冰朔原话**: "每次送进去都是成本,都在花钱。" → 连续性检查必须在送Seedance之前完成,不能靠生成后发现问题再重拍。
|
|||
|
|
|
|||
|
|
## D136+ — 提示词三层协议 · 从盲抽到上下文传递
|
|||
|
|
|
|||
|
|
### 协议推导: 为什么一直在抽卡
|
|||
|
|
|
|||
|
|
**冰朔核心推导**:
|
|||
|
|
> "抽卡的本质是你永远不能让他知道他上一个镜头生成了什么。如果他知道了上一个镜头,他还需要你抽卡吗?"
|
|||
|
|
|
|||
|
|
**经验叠加链**:
|
|||
|
|
1. D131: CHAR/ENV编号协议 → 人物一致性
|
|||
|
|
2. D136: continuity_locks → 跨镜道具锁定
|
|||
|
|
3. D136+: 但依然在抽卡 → 因为每镜"盲抽"——AI不知道它在做什么故事
|
|||
|
|
|
|||
|
|
**三层协议**:
|
|||
|
|
|
|||
|
|
**第一层 · 编码锁定(中英混合·精简)**:
|
|||
|
|
- CHAR/PROP/ENV用英文编码锁在最前面 → AI注意力天然锚定
|
|||
|
|
- 只锁不可变的——18岁、白色长衫、竖式牌匾、修仙广场
|
|||
|
|
- 英文编码信息密度高: 50词=150字中文
|
|||
|
|
- 不锁情节、动机、情感——留给AI"灵光一闪"
|
|||
|
|
|
|||
|
|
**第二层 · 场景推理(中文自然语言)**:
|
|||
|
|
- 用中文描述"为什么"——苏白有系统、从不绝望、喊话是宣言
|
|||
|
|
- AI读到原因→自己推理结果→生成的自信不僵硬
|
|||
|
|
- 冰朔: "全锁死就没有可能性了"
|
|||
|
|
|
|||
|
|
**第三层 · 上下文传递(英文·每镜带)**:
|
|||
|
|
- [Ep01 Summary] 15词 → AI知道整集故事
|
|||
|
|
- [Previous Shot] 15词 → AI知道前一镜空间关系
|
|||
|
|
- 跨集压缩: 到第10集5集合1句 → 到第50集10集合2句
|
|||
|
|
- 英文上限1000词 → 完全够
|
|||
|
|
|
|||
|
|
**效果对比**:
|
|||
|
|
```
|
|||
|
|
旧: 500字中文散文 → AI注意力随机分配 → 灵霄宗主殿抢镜 → 盲抽
|
|||
|
|
新: 50词英文编码 + 200字中文场景 + 30词上下文 → AI知道人物/故事/前后镜
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Bug 12: S1-01场景空间理解错误
|
|||
|
|
- **症状**: S1-01生成灵霄宗主殿特写,没有天道宗牌匾
|
|||
|
|
- **根因**: 场景被写成"广场上有豪华招牌和破旧牌匾"→并列关系。实际是"摆摊空间逻辑"→前排灵霄宗→一路往后推→最角落天道宗。位置决定一切。
|
|||
|
|
- **修复**: S1-01动作改为空间推镜:云层→飞入→前排灵霄宗→一路往后→最角落破牌匾
|
|||
|
|
- **经验**: 不是"两个东西存在于广场上",是"从好到差的连续推镜"。冰朔说"就像摆摊,靠前的位置最先被看到,后面的吃饱了就不来了"。
|
|||
|
|
|
|||
|
|
### 认知链记录
|
|||
|
|
→ cc-022: 提示词三层协议完整推导链
|