六壬学堂
← 返回笔记

B/C 栏目编制规程 v1

B/C 两栏目的生产规范与验收口径。


# B/C 栏目编制规程 v2 > 适用范围:**B 类《一课看懂》**、**C 类《邵先生拆课》**每一集的「稿件 → 执行包 → 出片 → 声音 → 成片」。 > 本规程由 **S1E01《七寸雪》** 的实跑固化(2026-10);下文每条命令与判据都是该项目上真跑过的那一套。 > **v2(2026-10 用户裁定)**:B 类改为**固定场景人物**(A 类州衙偏厅 + 邵先生 + 记录者 + 书案式盘,对话讲四课三传、式盘随指亮微光); > C 类**只用邵公配音**、不设中性辅助旁白;B/C 成片须补 **.srt 字幕轨**。 > 配套旧文:`README_工程索引.md`(目录导航)、`账号与发布规范_v1.md`(合规标识)。 --- ## 0. 栏目分工(长期口径,2026-10 用户裁定) | | 讲什么 | 不讲什么 | |---|---|---| | **B《一课看懂》** | 这门课**怎么读**:四课是什么、三传是什么、**风起/下雨/作雪从哪一重读出来** | 不点具体时刻、不说量 | | **C《邵先生拆课》** | 凭什么断得**这么具体**:为什么是**雪**(时令)、为什么**七寸**(形制)、为什么是**巳时/未时/亥时**(应期) | 不复述四课、三传是什么 | - C 与 B 的**差异化手法不固定**,按案情另选(S1E01 用的是「反证分叉」:若只取一重水象会断成什么)。 - 红线:**深解不可凭通俗六壬常识补原案**;台词内容以对应原案 + 已核材料为边界,节目化措辞须在稿内标注。 **视觉与声音口径(v2,2026-10 用户裁定)**: - **B 类固定场景人物**:场景取 A 类 `A-ENV-S1E01-HALL-01`(州衙偏厅),人物取 A 类 `A-CHAR-G-SHAO-01`(邵先生)与 `A-CHAR-G-REC-01`(记录者/书生),书案置 A 类道具 `A-PROP-G-DIVINATION-01`(式盘);四课、三传由二人**对谈**讲出, 式盘随指亮极淡微光(正向描述,**删去**与之冲突的 `no fantasy glow` 负面句——cfg=1 下否定句压不住正面描述); 三传等仍用 B 类既有的 `B-PROP-*E*-TOKEN-01` 标记物表示。**B 类 100 集共用此设定**。 已退役(图移入 `02_资产\参考图\_wip\`):`B-ENV-G-LAB-01`、`B-ENV-S1E01-MICRO-01`、`B-CHAR-S1E01-CASE-01`。 - **C 类只用邵公配音**(`C-VO-G-SHAO-01`):**不设中性辅助旁白**——原 `C-VO-G-NARR-01` 已删,旁白基座归 `A-VO-G-NARR-01`。 - **字幕轨**:B/C 成片须产出 `.srt`(见 §9.1)。 - **式盘带字口径(v3,2026-10 用户裁定)**:B 类**直接沿用 A 类实物式盘** `A-PROP-G-DIVINATION-01` 作桌面道具(约 **25cm×25cm**、平放于桌上),**式盘上可以带字**(随该资产自身刻字呈现,不再压制)。**其余画面文字一律「无字或虚化到不可读」**——送 H3 的文本不得含可读中文串(走 `--dialogue omit` + `--defs-english` 默认口径),字幕仍归后期 `.srt`。⇒ 制作稿 §4 不得再要求「素盘/无标记」(那会让 `h3_batch._prompt_conflict` 跳过式盘参考图,反而出不来字)。 --- ## 1. 改稿(`01_剧本\`) - B:`01_剧本\B类_一课看懂100集\{总序}_S{季}E{集}_{标题}_一课看懂_制作稿.md` - C:`01_剧本\C类_邵先生拆课30集\{总序}_S{季}E{集}_{标题}_邵先生拆课_制作稿.md` - 结构:§0 史料状态与原案锁定 / §1 视觉与声音 Bible / §2 结构与课理 / §3 参考图资产 / §4 每镜生成 Prompt。 - §4 每镜字段(**顺序与名称不可改,`smoke_pack.py` 按此解析**): `生成类型:` `时长:` `上传:` + `Picture N = <资产ID>`、`subject_definitions` / `summary` / `retention_analysis` / `detailed_description` / `overall_soundscape` / `non_diegetic_music`。 - 台词就地写在 `detailed_description` 里,形如 `... He says: [Chinese] 台词。`(C 类,人物口播)或 `Shao says: [Chinese] 台词。` / `the clerk asks: [Chinese] 台词。`(B 类,邵先生与记录书生**对谈**)。 - §3 参考图表**必须把该集用到的全部资产列全**(含 KEY/PLAN)——漏列会触发 `npm test` 的「参考图无孤儿」门禁。 --- ## 2. 时长口径(最容易出错的一环) 1. **H3 只认 `(5+17k)/24` 秒**(k≥0 整数,即 6.583 / 7.292 / 8.000 / 8.708 / 9.417 / 10.125 / 11.542 …)。写稿时**必须落在这组档上**。 2. **镜长由台词反推**,判据:`0.3s(镜内起手留白 MARK) + 台词实测时长 ≤ 镜长`(`assemble.py` 的 `audio_fit` 即此式)。 3. **不要为了迁就时长去删台词**——台词定稿、时长可调。(S1E01 实测:改台词会让已生成的 TTS 全部错位,代价远高于加长镜。) --- ## 3. 生成执行包 ```bash # B 类 python 00_工程管理/工具/smoke_pack.py \ --draft "01_剧本/B类_一课看懂100集/001_S1E01_七寸雪_一课看懂_制作稿.md" \ --mapping "03_映射/H3参考资产映射/B类/001_S1E01_七寸雪_H3映射.md" \ --shots B01,B02,B03,B04,B05 --label "5镜全集" \ --out "04_工程/B类/S1E01/smoke" --title "B类 S1E01《七寸雪》" # C 类同理:--draft C 稿 / --mapping C 映射 / --shots C01..C08 / --label "8镜全集" ``` - **槽位权威源是映射表**(`--mapping`),不是制作稿 §4 的 `上传` 块;§4 那块只作人读参考。 - 产物:`04_工程/{B类,C类}\S1E01\smoke\S1E01_{N}镜全集执行包.md` + `seeds_{N}镜全集.csv`。 - 收尾看输出里的 `注册表缺失 ID:`——应为「无」。 --- ## 4. 出片前两道门禁(都必须绿) ```bash # ① 计划校验(不联网):看时长、参考数、BLOCK 是否被正确跳过 python 00_工程管理/工具/h3_batch.py --pack "<执行包.md>" --dry-run # ② 音频 vs 分镜时长(fail-closed:rc=0 合格 / 1 有镜超限 / 2 数据缺失) python 00_工程管理/工具/assemble.py --pack "<执行包.md>" \ --shots-root "05_成片/B类/S1E01" --nominal --check --ep B001 ``` - **生成前一律加 `--nominal`**:不加会去读已出片素材的**实测镜长**,拿旧素材比新镜号必出假结论。 - `--ep` 是录音清单的「集」值:A 类 `001`、B 类 `B001`、C 类 `C001`。 --- ## 5. 出片 ```bash python 00_工程管理/工具/h3_batch.py --pack "<执行包.md>" \ --out "05_成片/B类/S1E01/h3" --url "<实例地址>" --yes ``` - ⚠ **输出必须落在 `<集目录>/h3/` 子树,不要平铺进集目录**。原因:`stitch_final.find_shot` 取 `sorted(glob(...))[0]`,而 H3 服务端的文件名计数是全局递增的——重出时新片编号更大、排序在后,若与旧片同目录,会被**静默选到旧视频**。 - 实例地址是 lightcc 随机子域、随时会变:首选 `python 00_工程管理/工具/lightcc_url.py`(需 `LIGHTCC_API_KEY`)解析,或直接用当前地址。 - 实例自检:`python 00_工程管理/工具/refgen.py --probe --url "<实例>"`;`MiniMaxH3ImageToVideo` / `MiniMaxH3` 节点在位即可出片。 - 单镜失败不中断整批(`h3_batch` 逐镜循环,汇总行会给 `合计 N/M 成功`);跑完按第 9 节核规格。 - 参考数据(S1E01 实测):T8·turbo、seed 20260925,单镜实耗约 **4–6 分钟**(8.7s 片 318s、11.5s 片更长)。 --- ## 6. 片头 / 片尾 ```bash python 00_工程管理/工具/make_titles.py --class B # 片头 + 片尾 python 00_工程管理/工具/make_titles.py --class C # 只有片头 ``` - 类别差异(用户 2026-10 确认):**A/B 有片尾;C 类制作稿 §2 无「片尾」节拍,只有片头**。 - 合规标识「本内容由 AI 生成」按 `ai_note` 落点:A/B 落**片尾**、C 落**片头**(`账号与发布规范_v1.md:52` 硬性要求,必须落在成片某处)。 - 产物:`{集目录}\{类}S1E01_736p_opener.mp4` / `_ender.mp4` + `_{片头,片尾}_样帧.png`(样帧供人眼确认)。 --- ## 7. 台词入清单 + TTS 1. 台词写进 `02_资产\声音\台本\_录音清单.csv`(**BOM + CRLF,必须二进制追加**,`集` 列用 `B001`/`C001`): `集,镜次,说话人,音色ID,台词,来源` 2. 音色 ID 必须在 **`声音资产注册表.csv`** 里有条目、且**已在 `voicebank.py` 的 `VOICE_ASSIGN` 里映射**(否则 `--batch` fail-closed 拒绝)。B/C 现有映射:`A-VO-G-SHAO-01→shao_c`(B 类主讲=邵公,映射 A1 列)、`A-VO-G-REC-01→rec_a`(B 类书生)、 `B-VO-G-NARR-01→narr_c`(**保留登记但 B 类已改对谈、不再使用**)、`C-VO-G-SHAO-01→shao_c`。 **C 类不设辅助旁白**(原 `C-VO-G-NARR-01` 于 2026-10 删除,旁白基座归 `A-VO-G-NARR-01`)。 3. 生成: ```bash python 00_工程管理/工具/声音/voicebank.py --url "<实例>" \ --batch "02_资产/声音/台本/_录音清单.csv" --only B001 # C 用 --only C001 ``` - 产物:`02_资产\声音\_synth\lines\{音色ID}__{镜次}[-NN].wav`(同镜多条自动加序号)。 - 音色母版的权威副本在 `02_资产\声音\_audition\`;换实例后远端音色丢失时用 `--save` 重建。 --- ## 8. 人声轨(把整集台词排成一条) ```bash python 00_工程管理/工具/make_voice.py --class B # C 用 --class C ``` - 产物:`{集目录}\{类}S1E01_736p_voice.wav`(48kHz / mono / 24bit,长度=各镜总长,**不含片头片尾**)。 - 秒点口径与 `assemble.py --dialogue_plan` 完全一致;无台词处静音。 - **默认取实测镜长**(分镜已按新时长重出时必须如此);分镜还没出、或镜位未更新时用 `--nominal`。 - ⚠ `make_voice.py` 的 `--class` 里存着各类的分镜目录;**分镜一旦换落点(如迁进 `h3/`),必须同步改 `CFG`**——否则它会打印 `⚠ … 退回标称` 后继续跑(半静默降级)。 --- ## 9. 成片 / 混音版 ```bash # 无声版(片头 + 各镜 + 片尾,各镜原生音轨) python 00_工程管理/工具/stitch_final.py \ --opener "05_成片/B类/S1E01/B类S1E01_736p_opener.mp4" \ --shots-root "05_成片/B类/S1E01/h3" --shots B01,B02,B03,B04,B05 \ --ender "05_成片/B类/S1E01/B类S1E01_736p_ender.mp4" \ --out "05_成片/B类/S1E01/B类S1E01_736p_final.mp4" # 混音版(再加 --voice,另存 _mix.mp4,不覆盖无声版) ... --voice "05_成片/B类/S1E01/B类S1E01_736p_voice.wav" --out "..._final_mix.mp4" ``` - 人声轨时间轴起点=**各镜**起点、成片起点=**片头**,故 `stitch_final` 自动按**片头实测时长**延迟叠加;原音降 `volume=0.35` 垫底(口径同 `assemble.py --audio-mix`)。 - C 类不给 `--ender`。 - **最终混音由用户合成**(需先分离合并分镜的人声与环境音)——我方交付到「各镜 + 人声轨 + 字幕」为止。 ### 9.1 字幕轨(.srt,v2 新增) ```bash python 00_工程管理/工具/assemble.py \ --pack "04_工程/{B类,C类}/S1E01/smoke/S1E01_{N}镜全集执行包.md" \ --shots-root "05_成片/{B类,C类}/S1E01/h3" --nominal --ep {B001,C001} \ --srt "05_成片/{B类,C类}/S1E01/{B,C}类S1E01_七寸雪.srt" --dry-run ``` - 台词取自 `_录音清单.csv`;秒点口径 `assemble.srt_from_lines`(镜内顺排,与 `--audio-mix` 同一套)。 - **必须给 `--dry-run`**:不给会继续尝试编码成片(缺素材时直接报错);给 `--dry-run --srt` 时「字幕已写、不编码」。 - `--shots-root` 指向**分镜所在层**(`.\h3`)——否则 `build_concat_list` 取不到素材、在写字幕前就 `raise SystemExit`。 - 产物 `.srt` 入库(`.gitignore` 只忽略媒体),用户在剪映/播放器导入即可当字幕轨。 --- ## 10. 验收(每条都要有真输出,不许"看起来对") | 项 | 命令 / 判据 | |---|---| | 项目门禁 | `npm test` → `tests 72 / pass 72 / fail 0` | | 单镜规格 | `ffmpeg -i <镜>.mp4` → Duration 与**标称逐镜吻合**、`1280x736`、24fps | | 成片规格 | 时长 = 片头 + 各镜之和 (+ 片尾);`1280x736 / h264 Main / 48kHz stereo` | | 人声轨秒点 | `ffmpeg -ss <点> -t <窗> -i -af volumedetect -f null -`:台词点 mean_volume ≈ **−20 ~ −32dB**、间隙/尾段 ≈ **−91dB**(差 ~70dB)。⚠ 窗口要**窄**且避开下一镜台词起点,否则半静音半有声的均值会假报「不静音」 | | 混音是否真叠了人声 | 抽成片 `[片头时长 : 片头+各镜总长]` 段与源 `voice.wav` 做归一化互相关:真混入 → **0.75 以上**;未混入 → ≈0(对照:A 类未混音的 final 只有 0.009) | --- ## 11. 已知坑(都踩过) 1. **B/C 的镜名是栏目级 beat 名、跨集共用**(B01 在 100 集里都叫同一个名字)。改镜名不是改一行——是跨全体改(映射表 + 各集执行包),须单独裁断。 2. **分镜必须落 `h3/` 子树**,否则 `find_shot` 按文件名排序会静默选中旧片(见 §5)。 3. **标称 ≠ 实测**:执行包写 `8.708`,mp4 实际 `209/24 = 8.708333`。毫秒级差逐镜累积后,人声轨 md5 会不同——**合成以实测为准**。 4. **`--nominal` 只用于"生成前预检"**;成品合成阶段该用实测。 5. **槽位权威是映射表**(`03_映射\H3参考资产映射\{B类,C类}\`),不是制作稿 §4 的上传块。 6. **`voicebank --batch` 是 fail-closed**:有音色 ID 没进 `VOICE_ASSIGN` 就整体拒绝,不静默跳过。 7. **`_录音清单.csv` / 声音注册表是 BOM + CRLF**;视觉资产注册表是 LF。改前先实测行尾。 8. **媒体产物不入库**(`.gitignore` 含 `*.mp4 / *.wav / *.mp3 / *.flac`);`*.png` 入库(样帧、参考图都进)。 9. **出片成本**:约 4–6 分钟/镜;B 5 镜 + C 8 镜 ≈ 1 小时。跑前把第 4 节两道门禁跑绿,别拿 GPU 试错。 10. **改「栏目级」设定要跨全体改**:B 类的固定场景/人物写在 100 集映射的 P 槽里(外加汇总总表与 ComfyUI 变体), 与制作稿 §4 的 `Picture N` **顺序必须一致**(`h3_batch` 按映射槽序喂图、按 prompt 内的 `` 引用)。 11. **改 blockgen 的 B 站点几何**只动 `SITE_B/AREAS_B/FURNITURE_B/SHOTS_B`;`--selftest` 钉的是**镜数**(A24/B5/C8),不是坐标。 12. **退役资产用「移入 `_wip\`」而不是删**:`collectRefImages()` 与 `smoke_pack.collect_have()` 都跳过 `_` 前缀目录, 移动即可同时满足「参考图无孤儿」门禁与可追溯;删除会丢历史候选。 13. **改共享音色 ID 前先查继承链**:`C-VO-G-NARR-01` 曾是 A/B 旁白的 `voice_of` 基座(`ttsgen.py` 自检钉住继承), 删它必须同时把基座迁到 `A-VO-G-NARR-01`,否则 `--selftest` 直接变红。 14. **制作稿 §4 的 `Picture N` 顺序必须与映射表 P 槽**同序**(2026-10 实测踩坑,B/C 类)**:`h3_batch` 按**槽位序**喂图(P1→P5), 而 prompt 里的 `` 来自制作稿 §4 的**定义序**;两者不一致时**不报错、只静默错认**——实测 B04A:喂进第 2 张是邵先生的图、 prompt 却说「第 2 张是记录者的形象参考」,H3 就把记录者画成了邵(两个都是邵、只有衣服不同)。所以 §4 的**上传块与 subject_definitions 一律按映射表 P1..Pn 排**(**A/B/C 全类已由 `npm test` 的『执行包 ×全类』门禁自动核**)。自检:`grep -nE "^(" <执行包>` 每镜都应指向场景图。 15. **制作稿 §4 的 `上传` 块与 `subject_definitions` 必须覆盖映射表该镜的**全部非空 P 槽**(含 `KEY`/`BLOCK`/`PLAN`)——**C 类每镜须含 KEY 定义**(`C-KEY-*`)(2026-10 实测踩坑)**: `smoke_pack` 的槽位表取自映射表、参考定义取自 §4;§4 漏写某槽时执行包里该槽**有图却无定义条**,不报错、静默缺定义——实测 C 类 S1E01 六镜漏 `C-KEY-*`(映射表 P8 有、§4 只到 Picture 7); KEY 定义范式同 A 类「关键帧参考(构图锚点)」。已由 `npm test` 的『执行包 ×全类』门禁自动核(逐镜断言参考定义序 == 上传槽位序)。 --- ## 12. 一集走完的最短命令序列(S1E01 实测版) ```bash U="<实例地址>" # 1 改稿 → 2 出包 → 3 门禁 python 00_工程管理/工具/smoke_pack.py --draft "<制作稿>" --mapping "<映射表>" --shots B01,B02,B03,B04,B05 --label "5镜全集" --out "04_工程/B类/S1E01/smoke" --title "B类 S1E01《标题》" python 00_工程管理/工具/h3_batch.py --pack "04_工程/B类/S1E01/smoke/S1E01_5镜全集执行包.md" --dry-run python 00_工程管理/工具/assemble.py --pack "04_工程/B类/S1E01/smoke/S1E01_5镜全集执行包.md" --shots-root "05_成片/B类/S1E01" --nominal --check --ep B001 # 4 出片(约 30 分钟) python 00_工程管理/工具/h3_batch.py --pack "04_工程/B类/S1E01/smoke/S1E01_5镜全集执行包.md" --out "05_成片/B类/S1E01/h3" --url "$U" --yes # 5 片头尾 python 00_工程管理/工具/make_titles.py --class B # 6 台词入清单 → TTS(约 2 分钟) python 00_工程管理/工具/声音/voicebank.py --url "$U" --batch "02_资产/声音/台本/_录音清单.csv" --only B001 # 7 人声轨 python 00_工程管理/工具/make_voice.py --class B # 8 成片 + 混音版 python 00_工程管理/工具/stitch_final.py --opener "05_成片/B类/S1E01/B类S1E01_736p_opener.mp4" --shots-root "05_成片/B类/S1E01/h3" --shots B01,B02,B03,B04,B05 --ender "05_成片/B类/S1E01/B类S1E01_736p_ender.mp4" --out "05_成片/B类/S1E01/B类S1E01_736p_final.mp4" # (再加 --voice "…_voice.wav" --out "…_final_mix.mp4" 出混音版) # 9 字幕(.srt) python 00_工程管理/工具/assemble.py --pack "04_工程/B类/S1E01/smoke/S1E01_5镜全集执行包.md" --shots-root "05_成片/B类/S1E01/h3" --nominal --ep B001 --srt "05_成片/B类/S1E01/B类S1E01_七寸雪.srt" --dry-run # 10 验收 npm test ```