Переглянути джерело

feat(duration): 视频时长不再固定 30 秒,改为由 Shot 台词时间分配表求和得出 T(≤30)

- elements.md 元素2:去掉『默认30秒/可选项15/30秒』,改为时长由 Shot 台词时间分配表逐 Shot 求和得 T、硬上限≤30、T 须写入 prompt 三处
- SKILL Step5『30秒硬卡』改『时长软卡≤30s』(按3-3.7字/秒估算,不硬卡110字);Step8 新增『时长由 Shot 表算出』子项,规划动线表时间列→求和=T→同步总体描述/时间戳0→T/--duration T/JSON
- script-template/wan3-workflow 硬性约束段与范式:『撑满约[30s]』→『[T秒]』,时间戳0→T连续,--duration 30→<T>,JSON duration:30→<T>;动线规划表加『Shot 台词时间分配表』时长预算说明
- README/docs/暨北内部:同步『30秒硬卡→时长软卡≤30s』『单段≤30秒不固定30秒』等表述;generate_video.py --duration help 注明传 Shot 表之和 T
zhengqi 1 тиждень тому
батько
коміт
0a1dc12af5

+ 4 - 4
README.md

@@ -14,7 +14,7 @@
 3. **门店场景**必须采用门店空间索引实景图(按动线规划从资源包选取对应 zone 照片),怡呵美 LOGO 随实景自然呈现。
 4. **音色**必须用指定文件作 `reference_audio`。
 5. 口播文案由用户内容**转口语化**适合口播。
-6. 整段视频**一个片段、≤30 秒**(超了反馈精简,循环直到满足;绝不拆片段)。
+6. 整段视频**一个片段、≤30 秒**(时长不固定 30 秒,由 Shot 台词时间分配表求和得出 T 作为实际 duration;T 超限则反馈精简,循环直到满足;绝不拆片段)。
 7. 确认后调用**百炼 wan3** 生成、轮询、下载本地、交付确认。
 8. **不支持二次创作**:任何元素修改都重新组装完整脚本、整段重发 wan3(不用编辑/延长模式)。
 
@@ -30,7 +30,7 @@
 
 对 WorkBuddy 说:「用美业口播科普视频脚本技能,做一条关于 *[选题]* 的口播视频」。技能按 `SKILL.md` 的 11 步流程执行:
 
-> 收集输入 → 文字风格问卷 → 锁定固定素材 → 生成并确认物料(人物形象照 / 门店空间实景图 / 插画)→ 处理口播文案(口语化 + 30 秒硬卡)→ **确认口播 + 敏感词/合规检测(必跑,用户按建议改或自改后复检)** → 确定插画插入点 → 组装编导分镜 Prompt → 逐步确认 → 调 wan3 生成 → 成片交付 → 修改即整段重发。
+> 收集输入 → 文字风格问卷 → 锁定固定素材 → 生成并确认物料(人物形象照 / 门店空间实景图 / 插画)→ 处理口播文案(口语化 + 时长软卡 ≤30s)→ **确认口播 + 敏感词/合规检测(必跑,用户按建议改或自改后复检)** → 确定插画插入点 → 组装编导分镜 Prompt(规划 Shot 时间分配表、求和得 T)→ 逐步确认 → 调 wan3 生成(duration=T)→ 成片交付 → 修改即整段重发。
 
 也可手动驱动生成脚本:`python scripts/generate_video.py --help`。
 
@@ -43,7 +43,7 @@ graph TD
     A[用户触发<br/>选题 / 选题+素材] --> B[收集基础输入<br/>+ 文字风格问卷]
     B --> C[锁定固定素材<br/>3项OSS URL 已写死]
     C --> D[生成并确认物料<br/>人物形象照 / 门店空间实景图 / 插画]
-    D --> E[处理口播文案<br/>转口语化 + 30秒硬卡 ≤110字]
+    D --> E[处理口播文案<br/>转口语化 + 时长软卡 ≤30s]
     E --> E2[确认口播 + 敏感词/合规检测<br/>必跑 · 机器初筛+人工复核]
     E2 --> F[确定插画插入点<br/>指定从哪句开始融入]
     F --> G[组装编导分镜 Prompt<br/>动线+运镜+插画+门店元素+背景锚定]
@@ -61,7 +61,7 @@ graph TD
 
 ### 1. 编导分镜要点(确保真实感 · 五块)
 
-- **人物行为动线**:30 秒单段 ≤2 个动作、方向不反向(「走动→落座」则落座后不再起身;「坐姿→起身走动」则走动后不再落座);口播时不设计整理产品等手部摆弄动作,手部只用自然手势 / 点头。
+- **人物行为动线**:单段(≤30 秒)≤2 个动作、方向不反向(「走动→落座」则落座后不再起身;「坐姿→起身走动」则走动后不再落座);口播时不设计整理产品等手部摆弄动作,手部只用自然手势 / 点头。
 - **运镜组合**:2–3 种随机穿插(跟随 / 推近 / 拉远 / 横移 / 手持微晃)。
 - **插画展示方式**:仅限局部画中画——形状随机选用**正方形或圆形**,单个插图**宽度 ≤ 画面 1/2、高度等比**,可置于**画面任意位置但不遮挡人物面部**;**禁止全屏铺盖与人物画中画式全屏**(用户 2026-09-17 规则 + 2026-09-22 尺寸约束补充)。
 - **门店丰富元素**:前台 / 美容床 / 沙发 / 桌椅 / 其他店员虚化走过,随机点缀 2–3 个增加景深。

+ 8 - 7
SKILL.md

@@ -108,11 +108,11 @@ agent_created: true
 
 展示后请用户**逐类挑选/确认**;若用户**未做任何选择** → 系统**自动随机指定**一组(记录"已自动随机指定")继续。确认后的物料(人物形象照/插画)与选取的门店实景图登记进脚本「物料清单」。
 
-### Step 5 — 处理口播文案(转口语化 + 30 秒硬卡)
+### Step 5 — 处理口播文案(转口语化 + 时长软卡 ≤30s)
 
 - **用户自带内容/口播** → 转换为口语化、适合口播的文案(自然亲和、带 `/` `//` 停顿符号、科普准确)。
 - **用户只给选题/知识点** → 技能生成口语化口播文案。
-- **30 秒硬卡循环**:按"30 秒 ≈ 90–110 字"估算字数;若 >110 字 → **反馈用户精简,等用户回精简版后重新估算**,循环直到 ≤110 字(对应 ≤30 秒,预留停顿余量、避免语速赶)才继续。绝不为凑时长拆分片段。
+- **时长软卡循环(不固定 30 秒,但 ≤30 秒)**:按"每秒 ≈ 3–3.7 字(放慢语速 + 句间气口)"估算台词所需时长;若预计 >30 秒 → **反馈用户精简,等用户回精简版后重新估算**,循环直到预计 ≤30 秒才继续。绝不为凑时长拆分片段。最终的精确总时长 T 由 Step 8 的 Shot 台词时间分配表求和得出(见 Step 8 第 5 点)。
   - ⚠️ **口播红线**:组装 prompt 时须内联完整「口播定本」作唯一台词依据,并显式禁止 TTS 据画面/主题自行补词(句间/句末幻觉加词,如"做好防晒"后补"干皮");prompt 其他文字(标题/表头/规格标注)一律不出声。详见 `wan3-workflow.md` 坑5。
 
 ### Step 6 — 确认口播文案 + 敏感词/合规检测(定稿后必跑)
@@ -139,18 +139,19 @@ agent_created: true
 - 该插入点直接决定 Step 8 单段 Prompt 中"画面融入插画"的时机,必须显式写进 prompt。
   - ⚠️ **插画禁人物红线**:生成插画参考图时必须显式要求"画面中严禁出现任何完整人物、人形轮廓、手势或人影"——否则插画里的人物会与口播真人并置成"两个主角"(见 `wan3-workflow.md` 坑7)。插画只画机理示意 / 物品 / 皮肤特写 / 光线氛围。
 
-### Step 8 — 组装单段 30 秒脚本(编导分镜级)
+### Step 8 — 组装单段脚本(编导分镜级,时长由 Shot 表算出)
 
 用 `assets/script-template.md` 填充,产出**单份结构化 Markdown**:
-一、角色定义 → 二、固定品牌素材 → 三、自动生成素材 → 四、口播文案(口语化,字数校验)→ **四-补、插画插入点** → 五、单段视频 Prompt(整段 ≤30 秒,**官方公式版**:总体描述 + Shot序号 + 时间戳 + 分镜内容,时间戳英文 `Shot N [x-y s]`、台词 `{}` 圈出;**prompt 中禁止写 Image N/Audio N**)→ 六、保留分析 → 七、硬性禁令 → 八、AI 口令(wan3 请求:命令 + JSON)。
+一、角色定义 → 二、固定品牌素材 → 三、自动生成素材 → 四、口播文案(口语化,字数校验)→ **四-补、插画插入点** → 五、单段视频 Prompt(整段 [T] 秒、T 由 Shot 台词时间分配表求和得出且 ≤30,**官方公式版**:总体描述 + Shot序号 + 时间戳 + 分镜内容,时间戳英文 `Shot N [x-y s]`、台词 `{}` 圈出;**prompt 中禁止写 Image N/Audio N**)→ 六、保留分析 → 七、硬性禁令 → 八、AI 口令(wan3 请求:命令 + JSON)。
 - **落盘**:组装完成后,将脚本写入**本任务文件夹** `脚本_<主题>.md`;并把第五节整段 prompt 单独写出到本任务文件夹 `prompt.txt`(供 Step 10 直接 `--prompt "$(cat .../prompt.txt)"` 读取)。
 - 第五节单段 Prompt **必须按 `wan3-workflow.md` 第四节「编导分镜版」范式写**,像专业编导一样覆盖四块:
-  1. **人物行为动线**(元素 25):30 秒单段内 **≤2 个动作切换**,且方向不反向("走动→落座"则落座后不再起身;"坐姿→起身走动"则走动后不再落座);**口播时不设计"整理产品"等手部摆弄动作**,手部只用自然手势 / 点头;全程在门店场景里与场景互动,**绝不全程正对镜头站桩**。
+  1. **人物行为动线**(元素 25):单段(≤30 秒)内 **≤2 个动作切换**,且方向不反向("走动→落座"则落座后不再起身;"坐姿→起身走动"则走动后不再落座);**口播时不设计"整理产品"等手部摆弄动作**,手部只用自然手势 / 点头;全程在门店场景里与场景互动,**绝不全程正对镜头站桩**。
      - 动线须在脚本第五节以 **【动线设计规划】表**逐 Shot 拆解(姿态/走位、手势/肢体、场景互动点),与下方分镜脚本一一对应,落实"≤2 动作切换、不反向、不站桩"。
   2. **运镜组合**(元素 12):每条约 2–3 种手法按时间轴穿插(跟随 / 推近 / 拉远 / 横移 / 手持微晃),随机组合、不全程单一机位。
   3. **插画展示方式**(元素 26):在「插画插入点」处触发,插画以**画中画**形式呈现——**形状随机选用正方形或圆形**,单个插图**宽度 ≤ 画面宽度的 1/2、高度等比**,可置于**画面任意位置但不遮挡人物面部**,**禁止全屏铺盖 / 人物画中画式全屏**(用户 2026-09-17 硬性规则 + 2026-09-22 尺寸约束补充);同一视频多次出现可轮换形状 / 位置,不固化一种。
   4. **门店丰富元素**(元素 27):在门店场景里随机点缀 2–3 个道具 / 人物(前台 / 美容床 / 沙发 / 桌椅 / 其他店员虚化走过),增加景深与真实感。
-  5. **背景逐段锚定**(元素 22 / 门店空间索引):每个 Shot 必须绑定对应 zone 参考图的元素清单(如门厅:品牌墙 + 吊灯 + 白门 + 圆几绿植 + 白沙发;产品区:怡呵美发光字展柜 + 灯带层板 + 绿植),并在硬规则写"人物未走位时背景禁止漂移成其他房间";人物真实经过的过渡空间(如走廊)**必须传对应实景图**,仅靠俯瞰图 + 文字会脑补"幽灵硬件"(见 `wan3-workflow.md` 坑4 与 `references/store-spatial-index.md`,实景图在 `assets/store-spatial-index/`)。
+  5. **时长由 Shot 表算出(不写死 30 秒)**:先规划第五节【动线设计规划】表的「时间」列(每 Shot 绑定对应台词句数与时长,按台词内容分配),**求和得到预计总时长 T**;T 即本段 `duration`。把 T 同步写入三处:① 总体描述「让内容自然撑满约[T秒]」② 分镜脚本时间戳 0→T 连续铺满、末段结束于 T ③ `--duration T` 与 JSON `duration`。T 必须 ≤30,超限回 Step 5 精简口播。
+  6. **背景逐段锚定**(元素 22 / 门店空间索引):每个 Shot 必须绑定对应 zone 参考图的元素清单(如门厅:品牌墙 + 吊灯 + 白门 + 圆几绿植 + 白沙发;产品区:怡呵美发光字展柜 + 灯带层板 + 绿植),并在硬规则写"人物未走位时背景禁止漂移成其他房间";人物真实经过的过渡空间(如走廊)**必须传对应实景图**,仅靠俯瞰图 + 文字会脑补"幽灵硬件"(见 `wan3-workflow.md` 坑4 与 `references/store-spatial-index.md`,实景图在 `assets/store-spatial-index/`)。
 - 口播台词用 `{}` 圈出、逐句写进各 Shot 的「分镜内容」;在讲对口白前**加入语气/节奏指令**(见 `wan3-workflow.md` 第四节:疑问/转折处语调上扬、核心点重音与停顿、整体松弛有起伏、禁止机械平读),缓解 wan3 原生 TTS 语气偏平的问题;在「插画插入点」指定句处明确写"讲到[第 N 句:原文]时,画面以[某展示方式]融入插画风格的抽象可视化";音色用自然语言描述"随附音频作音色参考",**不写 Audio 1**。**⚠️ prompt 文本里绝不出现 `Image N`/`Audio N`**(会被 wan3 当对白念出,详见 `wan3-workflow.md` 第一节/第七节)。
 - 引用的是**确认后的生成物料**(仅内部对应 media 数组顺序,prompt 中不写 Image N/Audio N):人物完整形象照、门店空间实景图(按动线 zone 选取,LOGO 随实景自然呈现)、插画;门店场景直接取自资源包实景图,无需合成 LOGO。
 
@@ -177,7 +178,7 @@ agent_created: true
 - **固定 3 项永远锁定(作生成输入)**:人物五视角/制服细节/音色来自素材包(`assets/brand/`)或公网 URL(`config.brand_assets`),不可被自动生成覆盖;制服胸牌样式绝对不可变。
 - **提交的是确认后的生成物料**:wan3 实际接收 Image 1=人物完整形象照、Image 2=门店空间实景图(按动线 zone 选取)、Image 3/4=插画、Audio 1=音色;原始 3 项固定素材仅用于生成人物完整形象照,不直接提交;门店实景图直接取自资源包。
 - **风格先确认后出图**:发起任务先文字版问风格,再生成「人物完整形象照 + 插画」示例图供确认;门店场景直接采用门店空间索引实景图,无需生成示例。
-- **单片段 ≤30 秒**:口播超 110 字必须反馈精简、循环直到满足;不拆分片段。
+- **单片段 ≤30 秒**:口播预计超 30 秒必须反馈精简、循环直到满足;不拆分片段(最终 T 由 Step 8 Shot 表求和确认)。
 - **LOGO 随实景自然呈现**:门店 LOGO 不另行生成,随选取的门店空间实景图(品牌墙 Z01「YIHEMEI 你的水光肌肤管理师」/ 发光字展柜 Z02 等)自然出现在成片;动线主场景若途经含 LOGO 的 zone,LOGO 即在画面中。
 - **动线规划最先确定**:人物出场场景由动线规划决定,不固定前台;动线规划须于 Step 4 选取实景图前先行确定(见 Step 4 前置说明),并填入脚本第五节【动线设计规划】表(含场景 zone 列),门店实景图据此按对应 zone 选取。
 - **原生音视频**:口播写进 prompt 作对白,音色作 reference_audio,wan3 一次性生成画面+对白+口型+环境音。

+ 9 - 7
assets/script-template.md

@@ -39,13 +39,13 @@
 
 ---
 
-## 四、口播文案(口语化,≤110 字 / 30 秒,预留停顿余量)
+## 四、口播文案(口语化,按约 3–3.7 字/秒估算、总时长 ≤30 秒、不固定 30 秒)
 
 > 由用户内容转换而来,自然亲和、适合口播;`/` 短停、`//` 长停不读出。
 
 [口语化口播全文:……(示例)"很多姐妹分不清泛红和红血丝 / 其实它俩真不是一回事 // 泛红是一过性的、受刺激就红 / 红血丝是毛细血管扩张、常年挂在那 // 搞清楚了,护肤才不踩坑。"]
 
-字数校验:[N] 字 ≤150 → 满足 30 秒约束。
+字数校验:[N] 字 → 按 ~3–3.7 字/秒 估算约 [N/3.5≈T] 秒,须 ≤30 秒(T 最终由第五节 Shot 表求和确认)。
 
 ---
 
@@ -74,7 +74,7 @@
 
 ---
 
-## 五、单段视频 Prompt(整段 30 秒 · 编导分镜版,含参考引用)
+## 五、单段视频 Prompt(整段 [T] 秒 · 编导分镜版,含参考引用;T 由本节【动线设计规划】时间列求和得出且 ≤30)
 
 > 一段连续 prompt 描述整段画面(不拆分请求),wan3 原生生成画面 + 对白 + 环境音。下方范式按官方「总体描述 + 镜头序号 + 时间戳 + 分镜内容」组织,**时间戳用英文 `Shot N [x-y s]`、台词用 `{}` 圈出**。⚠️ **prompt 文本里绝不写 `Image N`/`Audio N`**(会被 wan3 当对白念出,见 `wan3-workflow.md` 第一节/第七节);第三节物料靠 media 数组顺序间接对应,用自然语言描述画面与音色即可。写这条 prompt 要像专业编导:**人物必须在门店场景里"活"起来,不站桩;运镜/插画展示/门店丰富元素按下面四块随机组合设计**(对应 `elements.md` 元素 25/26/27/12)。
 
@@ -93,7 +93,7 @@
 整体手持微晃保留真实手机拍摄质感。
 
 语气与节奏:她自然亲和地讲解,像真人面对面聊天一样有温度有起伏——问句好奇上扬、肯定句沉稳、
-列举句轻快有层次、收束句温和坚定;整体语速比自然对话放慢约一半、从容舒缓,让内容自然撑满约[30s],
+列举句轻快有层次、收束句温和坚定;整体语速比自然对话放慢约一半、从容舒缓,让内容自然撑满约[T秒](T=动线规划表各 Shot 时长之和,≤30s),
 句与句之间留约[0.5s]自然气口,不赶。
 
 声音:原生清晰女声普通话对白(音色参考随附音频)、轻微环境音、无背景音乐;
@@ -108,6 +108,8 @@
 
 【动线设计规划】(按 Shot 拆解;下表为示例,按本片实际主题替换对应行。⚠️ **人物出场场景由本规划决定,不固定前台**;硬约束:单段 ≤2 个动作切换且方向不反向、绝不全程正对镜头站桩、须与门店场景互动)
 
+> **📐 Shot 台词时间分配表(时长预算)**:本表「时间」列即逐 Shot 的台词时间分配,须**按本任务台词内容**规划(每 Shot 绑定对应口播句数与篇幅)。各 Shot 时长**求和 = 本段预计总时长 T**(上表示例 = 30s,仅作格式演示)。**T 即本段实际 `duration`,必须 ≤30 秒**;T 同步用于:总体描述「撑满约[T秒]」、下方分镜脚本时间戳 0→T 连续铺满、以及第八节 `--duration T` / JSON `duration`。若求和 >30,回第四节精简口播。
+
 | Shot | 时间 | 场景 zone(出场/经过) | 姿态 / 走位 | 手势 / 肢体 | 场景互动点 |
 |------|------|------------------------|-------------|-------------|------------|
 | 1 | 0-4s | Z02 产品陈列架前(开场) | 端坐于陈列架前 | 手持微晃、自然手势比划 | 怡呵美发光字展柜 / 灯带层板 |
@@ -120,7 +122,7 @@
 > 动作切换计数:端坐 → 起身走动(1 次);走动后落座/站立至结尾(不二次起身、不反向)。满足 ≤2 个动作切换。
 > 场景清单:本片出场/经过 zone = Z02 → Z05 → Z04(据此从 `assets/store-spatial-index/` 选取对应门店实景图,LOGO 随 Z02 发光字展柜等地区实景自然呈现;不限定前台)。
 
-【分镜脚本】
+【分镜脚本】(示例时间戳按 T=30s 演示;实际须用本任务算出的 T 重排,全程 0→T 连续、末段结束于 T,不空段)
 Shot 1 [0-4s]:[开场中近景,女美容师端坐面诊桌前,手持微晃手机质感,镜头极轻微横摇];
 她好奇上扬地提问{[第四节·口播句1]},句末留自然气口。
 
@@ -180,7 +182,7 @@ python scripts/generate_video.py \
     插画/插画_参考1.png:reference_image \
     插画/插画_参考2.png:reference_image \
     "https://cdn.x/voice_ref.mp3:reference_audio" \
-  --duration 30 --ratio 9:16 --resolution 720P \
+  --duration <T> --ratio 9:16 --resolution 720P \   # T = 第五节动线规划表各 Shot 时长之和(≤30)
   --output 成片_<主题>.mp4
 ```
 
@@ -200,7 +202,7 @@ python scripts/generate_video.py \
       {"type": "reference_audio", "url": "<voice_ref URL 或 上传URL>"}
     ]
   },
-  "parameters": {"resolution": "720P", "ratio": "9:16", "duration": 30, "audio": true, "prompt_extend": false, "watermark": false}
+  "parameters": {"resolution": "720P", "ratio": "9:16", "duration": <T>, "audio": true, "prompt_extend": false, "watermark": false}  # T = 第五节动线规划表各 Shot 时长之和(≤30)
 }
 ```
 

+ 4 - 4
docs/暨北内部-朵朵口播视频专用技能.md

@@ -31,8 +31,8 @@
 | 分辨率 resolution | `720P` |
 
 ### 3. 固定编导规则(确保真实感、不 AI 感)
-- **单段时长**:整段一个片段、**≤30 秒**(超字数自动反馈精简,绝不拆片段)。
-- **人物动线**:30 秒内动作**≤2 个、方向不反向**——「走动→落座」则落座后不再起身;「坐姿→起身走动」则走动后不再落座;**口播中不设计整理产品等手部摆弄动作**,手部只用自然手势 / 点头。
+- **单段时长**:整段一个片段、**≤30 秒**(时长不固定 30 秒,由 Shot 台词时间分配表求和得 T 作实际 duration;超 30 秒自动反馈精简,绝不拆片段)。
+- **人物动线**:单段(≤30 秒)动作**≤2 个、方向不反向**——「走动→落座」则落座后不再起身;「坐姿→起身走动」则走动后不再落座;**口播中不设计整理产品等手部摆弄动作**,手部只用自然手势 / 点头。
 - **运镜组合**:2–3 种随机穿插(跟随 / 推近 / 拉远 / 横移 / 手持微晃)。
 - **插画展示方式**:仅限局部画中画——形状随机选用**正方形或圆形**,单个插图**宽度 ≤ 画面 1/2、高度等比**,可置于**画面任意位置但不遮挡人物面部**;**禁止全屏铺盖 / 人物画中画式全屏**(用户 2026-09-17 规则 + 2026-09-22 尺寸约束)。
 - **门店丰富元素**:前台 / 美容床 / 沙发 / 桌椅 / 其他店员虚化走过,随机点缀 2–3 个增加景深。
@@ -106,7 +106,7 @@ flowchart TD
     B --> C[Step2 锁定3项固定品牌素材<br/>朵朵人物 / 制服 / 音色]
     C --> D[Step3 生成确认物料<br/>人物形象照 / 门店空间实景图 / 插画]
     D --> E[Step4 用户确认物料选材]
-    E --> F[Step5 口播转口语化 + 30秒字数硬卡]
+    E --> F[Step5 口播转口语化 + 时长软卡 ≤30s]
     F --> G[Step6 用户确认口播文案]
     G --> H[Step7 确定插画插入点<br/>指定从哪句开始融入]
     H --> I[Step8 编导分镜级 Prompt 组装<br/>动线 + 运镜 + 插画展示 + 门店元素]
@@ -155,4 +155,4 @@ flowchart TD
 1. **密钥安全**:`.env` 含个人 Key,已加入 `.gitignore`,切勿手动提交;重新打包技能前请删除本地 `.env`。
 2. **整段重发**:本技能不支持二次创作,任何修改都整段重生成(对应品牌硬需求)。
 3. **逐步确认**:每个确认点请认真看,避免浪费百炼生成额度。
-4. **画质**:成片为 9:16 竖屏 720P、单段 ≤30 秒,适合短视频平台直接发布。
+4. **画质**:成片为 9:16 竖屏 720P、单段 ≤30 秒(时长 T 由 Shot 表求和得出),适合短视频平台直接发布。

+ 6 - 4
references/elements.md

@@ -17,9 +17,11 @@
 - 说明:wan3 `ratio` 参数支持 16:9 / 4:3 / 1:1 / 3:4 / 9:16 / adaptive。
 
 ## 2. 视频时长(Duration,单段)
-- 默认:30 秒
-- 硬约束:**整段 ≤30 秒**(wan3 上限)。技能在口播文案阶段按"30 秒 ≈ 90–110 字"估算(预留停顿余量、避免语速赶),超了**反馈用户精简、循环直到 ≤30 秒**才继续(见 SKILL.md 第 5 步)。
-- 可选项:15 秒 / 30 秒(不提供分片段;若内容过多请精简而非延长)
+- **不固定为 30 秒**:单段时长由「Shot 台词时间分配表」(即脚本第五节【动线设计规划】的「时间」列)的逐 Shot 时长之和决定,而非写死 30 秒。
+- **硬上限**:整段 **≤30 秒**(wan3 上限)。若 Shot 表求和超过 30 秒,回 Step 5 反馈用户精简口播、循环直到 ≤30 秒才继续。
+- **计算方式(必做,写进 prompt)**:先在 Step 8 规划「Shot 台词时间分配表」(每 Shot 绑定对应台词句数与时长,按台词内容分配),再**求和得到预计总时长 T**;T 即本段实际 `duration`。把 T 同时写入三处:① 总体描述「让内容自然撑满约[T秒]」② 分镜脚本时间戳 0→T 连续铺满、末段结束于 T ③ `--duration T` 与 JSON `duration: T`。
+- **字数估算参考(非硬卡)**:因 T 浮动,按"每秒 ≈ 3–3.7 字(放慢语速 + 句间气口)"估算总需求字数与 T,不必死守 110 字;只要 T ≤30 即可。
+- 不提供分片段;若内容过多请精简而非延长。
 
 ## 3. 发布平台(Platform)
 - 默认:视频号
@@ -43,7 +45,7 @@
   - 用户自带完整口播(含 / 短停、// 长停 符号)
   - 技能生成(把用户给的内容**转换为口语化、适合口播**的文案;自然亲和、带停顿符号、科普准确)
 - 停顿符号约定(不读出):`/` 短停(换口气) `//` 长停(段落 / 情绪切换)
-- 字数硬约束:≤150 字(对应 30 秒)。
+- 字数参考:按 ~3–3.7 字/秒 估算,使本段总时长 T ≤30 秒(T 不固定 30 秒,由 Step 8 的 Shot 台词时间分配表求和得出)。
 
 ## 8. 角色面部素材(Character Reference Image)【固定素材包】
 - 默认:素材包 `assets/brand/character_5view.*`(用户指定五视角图,**固定锁定**)

+ 8 - 8
references/wan3-workflow.md

@@ -38,9 +38,9 @@
 
 > 提交的是**确认的物料**,不是原始 3 项文件本身。
 
-## 四、单段 30 秒 prompt 范式(编导分镜版)
+## 四、单段 prompt 范式(编导分镜版;时长 T 由 Shot 表算出,≤30 秒)
 
-一个 prompt 描述**整段 30 秒**的连续画面(不要拆成多个 Shot 分开发请求)。要把它当作一条**专业编导分镜**来写——人物必须在门店场景里"活"起来,不能一直正对镜头站桩。必须覆盖四块:**人物行为动线 / 运镜组合 / 插画展示方式 / 门店丰富元素**(对应 `elements.md` 元素 25/26/27/12)。结构范式:
+一个 prompt 描述**整段 [T] 秒**(T 由 Shot 台词时间分配表求和得出、≤30)的连续画面(不要拆成多个 Shot 分开发请求)。要把它当作一条**专业编导分镜**来写——人物必须在门店场景里"活"起来,不能一直正对镜头站桩。必须覆盖四块:**人物行为动线 / 运镜组合 / 插画展示方式 / 门店丰富元素**(对应 `elements.md` 元素 25/26/27/12)。结构范式:
 
 > 范式按官方「总体描述 + 镜头序号 + 时间戳 + 分镜内容」公式组织;时间戳用英文 `Shot N [x-y s]`,台词用花括号 `{}` 圈出。⚠️ **绝不在 prompt 里写 `Image N`/`Audio N`**(会被当对白念出);用自然语言描述画面与音色。
 
@@ -58,7 +58,7 @@
 整体手持微晃保留真实手机拍摄质感。
 
 语气与节奏:她自然亲和地讲解,像真人面对面聊天一样有温度有起伏——问句好奇上扬、肯定句沉稳、
-列举句轻快有层次、收束句温和坚定;整体语速比自然对话放慢约一半、从容舒缓,让内容自然撑满约[30s],
+列举句轻快有层次、收束句温和坚定;整体语速比自然对话放慢约一半、从容舒缓,让内容自然撑满约[T秒](T=Shot 时间分配表之和,≤30s),
 句与句之间留约[0.5s]自然气口,不赶。
 
 声音:原生清晰女声普通话对白(音色参考随附音频)、轻微环境音、无背景音乐;
@@ -89,10 +89,10 @@ Shot 6 [26-30s]:[结尾缓慢拉远收束,她保持站立、抬手手势收
 ```
 
 - 口播台词用花括号 `{}` 圈出、逐句写进各 Shot 的「分镜内容」,wan3 原生生成语音并对口型;`{}` 之外的是画面/运镜描述,不会被当台词。
-- **人物行为动线**按口播时长设计:≤15 秒用 1–2 个动作切换,30 秒用 3–4 个动线(走动/坐/起/落座/整理)。
+- **人物行为动线**按口播时长设计:单段(不论 T 长短)动作切换 **≤2 个**、方向不反向(见 SKILL Step 8 元素 25);动作幅度随 T 伸缩,短于 30 秒更不宜多。
 - **运镜**每条约 2–3 种按时间轴穿插,不全程单一机位;**插画展示方式**一场内可混用多种,不恒定为一种;**门店丰富元素**随机点缀 2–3 个,增加景深与真实感。
-- **时间戳即控速锚点(关键)**:`Shot N [x-y s]` 连续铺满目标时长(如 0–30s),既是分镜结构也是节奏约束。wan3 实测在「强制时长 > 口播实际长度」的空白时段会**自动编造废话填充**(padding 幻觉),故内容必须真实撑满时间戳区间——靠放慢语速 + 句间留足气口,而非空撑时长。宁可 `duration` 用 `−1` 智能时长(按内容自动定长,上限 30s)也不要硬撑。
-- 时长参数 `duration` 默认 `30`,`ratio=9:16`,`resolution` 按 config;若口播偏短或要规避 padding,可显式缩短 `duration` 或设 `−1`。
+- **时间戳即控速锚点(关键)**:`Shot N [x-y s]` 连续铺满本段总时长 T(即 0→T,如 0–26s),既是分镜结构也是节奏约束,也等于 `duration` 的实际值。T 由各 Shot 时长求和得出,必须 ≤30。wan3 实测在「强制时长 > 口播实际长度」的空白时段会**自动编造废话填充**(padding 幻觉),故 Shot 时间分配须让台词真实撑满时间戳区间——靠放慢语速 + 句间留足气口,而非空撑时长。**推荐直接传算出的 T(不要硬撑到 30)**;若内容确实偏短,可改用 `−1` 智能时长(按内容自动定长,上限 30s)。
+- 时长参数 `duration` 须传**本段算出的 T**(各 Shot 时长之和,≤30),不要写死 30;`ratio=9:16`,`resolution` 按 config;若口播偏短或要规避 padding,也可设 `−1` 智能时长(按内容自动定长,上限 30s)。
 - 反向约束(硬性禁令)也写进 prompt 负向描述:无字幕/无文字/无卡通化/无塑料皮肤/无变脸/无服装漂移/无场景跳变。
 
 ## 五、LOGO 落位(保证成片一定出现 LOGO)
@@ -118,7 +118,7 @@ python scripts/generate_video.py \
     /abs/插画_参考1.jpg:reference_image \        # Image 3
     /abs/插画_参考2.jpg:reference_image \        # Image 4
     "https://cdn.x/voice_ref.mp3:reference_audio" \  # Audio 1(config URL 透传,或本地路径)
-  --duration 30 --ratio 9:16 --resolution 720P \
+  --duration <T> --ratio 9:16 --resolution 720P \   # T = 各 Shot 时长之和(≤30,由 Shot 时间分配表算出)
   --output /abs/成片.mp4
 ```
 
@@ -130,7 +130,7 @@ python scripts/generate_video.py \
 - `media[].url` 支持**公网 URL 直传**,也支持**图像 base64 直传**(`data:{mime};base64,{b64}`)。固定 3 项若填了公网 URL(config.brand_assets),脚本默认直接透传;若 wan3 不接受站外 URL,把 `config.reupload_external_urls` 设为 `true`,脚本会先下载再编码 base64 直传。本地生成的图(人物形象照/门店内景/插画)一律编码 base64 直传,无需文件上传端点。
 - 用户所给 `llm-….maas.aliyuncs.com/compatible-mode/v1` 是 LLM 网关,**视频端点主机不带 `llm-` 前缀**。若视频调用报 404,确认 `config.workspace_id`/`region` 是否拼出 `https://{ws}.{region}.maas.aliyuncs.com`;可显式填 `config.api_base` 覆盖。
 - `reference_audio` 单段 ≤15s、≤15MB;音色样本过长先裁剪。
-- `duration` 必须 ≤30,超了先在技能侧精简口播(见 SKILL.md 第 5 步硬卡循环)。
+- `duration` 必须 ≤30,且应等于本段 Shot 时间分配表之和 T(见 SKILL.md 第 5/8 步);超了先在技能侧精简口播。
 - 不传 `X-DashScope-Async: enable` 会报"current user api does not support synchronous calls"。
 
 ### 实测新增坑(2026-09-17 ~ 09-18,去角质频率项目验证)

+ 1 - 1
scripts/generate_video.py

@@ -202,7 +202,7 @@ def main():
              "如 /abs/char.jpg:reference_image 或 https://cdn.x/char.jpg:reference_image;"
              "公网 URL 默认直接透传;本地文件编码 base64 直传;详见 config.reupload_external_urls。",
     )
-    ap.add_argument("--duration", type=int, default=30, help="时长(秒),≤30;传 -1 启用智能时长模式(按实际口播内容自动定长,上限 30s)")
+    ap.add_argument("--duration", type=int, default=30, help="时长(秒),≤30;建议传技能算出的 Shot 时间分配表之和 T;传 -1 启用智能时长模式(按实际口播内容自动定长,上限 30s)")
     ap.add_argument("--ratio", default=None, help="画幅,如 9:16")
     ap.add_argument("--resolution", default=None, help="分辨率,如 720P")
     ap.add_argument("--model", default=None)