@dsh-gis/dsh-video-studio-skill 0.8.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +582 -0
  2. package/README.md +287 -304
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/package.json +11 -10
  5. package/schemas/design.schema.json +722 -0
  6. package/schemas/film.schema.json +171 -15
  7. package/schemas/proposal.schema.json +133 -0
  8. package/skills/video-studio/SKILL.md +1316 -1066
  9. package/skills/video-studio/assets/design_fixture.json +141 -0
  10. package/skills/video-studio/assets/film.json +1 -2
  11. package/skills/video-studio/assets/golden_frames.json +12 -9
  12. package/skills/video-studio/assets/scenes.py +2207 -1190
  13. package/skills/video-studio/assets/voice_loudness.json +16 -0
  14. package/skills/video-studio/references/audio-variation.md +15 -11
  15. package/skills/video-studio/references/audio.md +36 -34
  16. package/skills/video-studio/references/change-impact.md +3 -3
  17. package/skills/video-studio/references/frame-qa.md +2 -2
  18. package/skills/video-studio/references/proposal.md +177 -0
  19. package/skills/video-studio/references/quality-gates.md +2 -2
  20. package/skills/video-studio/references/scene-grammar.md +311 -0
  21. package/skills/video-studio/references/sfx-design.md +1 -1
  22. package/skills/video-studio/references/style-packs.md +107 -168
  23. package/skills/video-studio/references/v08-quality.md +8 -8
  24. package/skills/video-studio/references/web-engine.md +1 -1
  25. package/skills/video-studio/references/word-timeline.md +2 -2
  26. package/skills/video-studio/scripts/designkit.py +2120 -0
  27. package/skills/video-studio/scripts/filmcheck.py +104 -33
  28. package/skills/video-studio/scripts/filmkit.py +153 -78
  29. package/skills/video-studio/scripts/grammar.py +619 -0
  30. package/skills/video-studio/scripts/musicgen.py +2043 -0
  31. package/skills/video-studio/scripts/preflight.py +10 -3
  32. package/skills/video-studio/scripts/previewkit.py +849 -0
  33. package/skills/video-studio/scripts/propose.py +825 -0
  34. package/skills/video-studio/scripts/qa_frames.py +45 -10
  35. package/skills/video-studio/scripts/qavmaf.py +77 -11
  36. package/skills/video-studio/scripts/render.py +505 -142
  37. package/skills/video-studio/scripts/scorekit.py +50 -1748
  38. package/skills/video-studio/scripts/selfcheck.py +851 -115
  39. package/skills/video-studio/scripts/stagewatch.py +21 -5
  40. package/skills/video-studio/scripts/stylekit.py +293 -570
  41. package/skills/video-studio/scripts/voicekit.py +502 -380
  42. package/skills/video-studio/scripts/webengine.py +15 -14
  43. package/tools/audio_similarity.py +57 -30
  44. package/tools/ci_check.py +9 -1
  45. package/tools/estimate.py +14 -8
  46. package/tools/golden_frames.py +56 -11
  47. package/tools/silhouette_qa.py +1263 -0
  48. package/docs/demo-pil-sheet.png +0 -0
  49. package/docs/styles/demo-results.json +0 -76
  50. package/docs/styles/sheet-8-styles.png +0 -0
  51. package/docs/styles/sheet-ai.png +0 -0
  52. package/docs/styles/sheet-craft.png +0 -0
  53. package/docs/styles/sheet-night.png +0 -0
  54. package/skills/video-studio/assets/score_demo.json +0 -307
package/README.md CHANGED
@@ -1,304 +1,287 @@
1
- # @dsh-gis/dsh-video-studio-skill
2
-
3
- ![version](https://img.shields.io/badge/version-0.8.1-blue) ![license](https://img.shields.io/badge/license-MIT-green)
4
-
5
- **DeepSeek Harness 技能插件:用代码从零生成中文视频。**
6
-
7
- 写剧本 → edge-tts 旁白 → **实测时长**排时间轴 → **提示点**驱动配乐与音效 → PIL 或浏览器逐帧渲染 →
8
- ffmpeg 编码 → 采样级混音 → **四层质检**(容器 / 信号 / 时间 / 页面)+ **v0.8 的四个新闸**
9
- (渲前资源预检 `G0` / 词级时间戳 `G10` / 全片 VMAF `G11` / ASR 回读 `G12`)。
10
- 零素材、可复现、可断点续跑、可脚本化验收;装成插件后,整片生产流程随技能一起进入每个会话。
11
-
12
- > 源自 `dsh-v` 资产包的 `02-技能包-video-studio`(817 个 DSH 会话的考古分析 + 5 套现存工程逆向 + 本机实测)。
13
- > **v0.2.0**:用这套技能真的做出一部 11 分钟成片后,发现 10 处"文档承诺了、代码没做到"的地方
14
- > (门禁失效、缓存不校验、stage 假独立、mux 二次编码等),全部修掉并补了 14 条回归断言。
15
- > **v0.3.0**:与另一部 6 分半成片(`ai-history-film`)对照后,补上本项目最缺的四块——
16
- > 物理建模音效库、程序化配乐、浏览器逐帧渲染引擎、帧级质检,以及把三者串起来的**提示点系统**。
17
- > **v0.4.0**:修掉 4 处"门禁看着干净、其实没在查"的静默问题(`--resume` 复用旧分块、
18
- > `music.mode=off` 仍混入旧配乐、PIL 路线音画同步恒空、亮度静止判据误报 4 段),
19
- > 补上仓库级体检(`tools/ci_check.py`)、CI、`requirements.txt`,并修掉管道中文乱码。
20
- > **v0.5.0(风格包)**:解决"每部片都长一个样"。一个 `style` id 同时决定画风(8 套主题 ×
21
- > 3 种版式)、配乐(8 套风格:调池/BPM 梯度/进行/动机/配器/鼓型)、旁白(9 个声线 × 6 档语气)
22
- > 与节奏;`"style": "auto"` 按内容自动选,三级内容指纹保证"改错别字不换整首曲子"。
23
- > 不写 `style` 字段 = v0.4 行为(配乐 PCM 逐样本一致,selfcheck 有断言)。
24
- > **v0.6.0(交付可信化)**:解决"**质检结论只活在控制台里**"。新增门禁账本与机读交付报告
25
- > `out/QC-REPORT.md`(gate matrix 分 **pass / fail / skipped 三档**——"没执行"不再冒充"通过")、
26
- > 人工签核 `--stage accept`(绑内容指纹,改了剧本旧签核自动失效)、阶段新鲜度 `--stage explain`
27
- > (改上游后哪些产物还是旧的、最小重跑什么)、开渲前成本预演 `tools/estimate.py`、
28
- > `film.json` 契约校验 `filmcheck.py`(改成 `holds` 这种拼写错误不再静默失效)。
29
- > 顺手修掉一个**已发布版本里的真 bug**:`--jobs >1` 并行渲染因主题色元组被 JSON 变成 list 而直接崩溃
30
- > ——也就是 README 下面教的"长片分块并行"此前根本跑不通。
31
- > 详见 [CHANGELOG.md](CHANGELOG.md)、SKILL.md §7.0 与 references/change-impact.md。
32
- > **v0.7.0(声音也不再一片一样)**:内容指纹从 seed 推进到**结构层**——和弦替换、进行档位、动机偏移、
33
- > 鼓型 ghost 都随内容变化;音效 seed 改内容派生并跟随配乐调性(`in_key`);段落边界前 2.2 s 的
34
- > whoosh/riser 自动 -3 dB,避免与配乐过门撞车;duck 按风格加深到 3.0–5.5 dB。legacy 路径逐样本不变。
35
- > **v0.7.1(旁白优先)**:配乐基线从 -1.5 降到 **-12 dB**,有人声处再按包络压配乐 6 dB / 音效 3 dB,
36
- > 混音后按台词活跃区实测旁白/背景差,**不足 12 dB 自动补压背景**(`guard_snr_db`,最多 30 dB)。
37
- > 实测(真实素材):旧混音 -4.2 dB → 新混音 12.0 dB,`audio_similarity --strict` D 组 12.9 dB;
38
- > selfcheck 34 → 38 条,其中第 35–38 条专盯这条链路。
39
- > 详见 [CHANGELOG.md](CHANGELOG.md) 与 SKILL.md §5.6 / §5.7、references/audio-variation.md。
40
- > **v0.8.0(把"看得见"变成"抓得住")**:四个方向——① **词级时间轴**:edge-tts 的 WordBoundary 事件落
41
- > `work/words.json`(4 句 / 64 词 / 末词偏差 0.09 s),字幕改按词折行,cue 可写词锚点 `"l03:w2+0.1"`;
42
- > ② **四道新门禁**:渲前资源预检 `G0`(缺字形/坏音频在渲第一帧前 fail,< 1 s)、词级时间戳 `G10`、
43
- > 全片 VMAF/SSIM `G11`(参考帧由场景函数**实时重渲**,不是成片抽帧;29 s 片 VMAF 97.22 / 14.2 s)、ASR 回读 `G12`
44
- > (成片音轨转文字对账,0.72 以下才 fail,8.7 s/片);③ **画幅/帧率参数化**(只做 16:9 横屏,
45
- > 内部恒 1080p、编码时下采样,720p 已实测全门通过)、**批量** `--batch`(≤100 条、开跑前全量预检、
46
- > 单条失败不阻断)、**预览** `--preview N`(前 N 秒出 mp4+gif)、**运行版本化** `--run-id`(`work/runs/<runId>/`);
47
- > ④ web 引擎跟随风格包(`window.__STYLE__` 注入,`style=None` 时逐字节等于 v0.7)+ 金帧像素回归
48
- > `tools/golden_frames.py`。**代价要说清**:29 s 模板片全链从约 28 s 涨到 **47.3 s**,其中 `qa` **23.9 s**
49
- > 已经**超过渲染本身**(`frames` 12.5 s);`estimate` 预演也从 28.4 s 变成 **58.8–108.2 s**(vmaf 31–50 s 是瓶颈)。
50
- > v0.8 之后"出片时间"不再只是渲染时间。selfcheck 43 → **51 条**。
51
- > 详见 [CHANGELOG.md](CHANGELOG.md) 与 SKILL.md §6.1 / §7.5、references/word-timeline.md、references/v08-quality.md。
52
- > **v0.8.1(全项目深审,无新功能)**:把 14 个模块 / 5 个前端文件 / 12 篇 references / 仓库工具链
53
- > 全部过一遍,修掉 **60+ 处**「看着没问题、其实没在查」。举几个真会伤到交付的:
54
- > ① **VMAF 参考帧与成片的字幕折行口径不一致**(渲染传 `words`、参考帧没传)——近静态画面
55
- > 从 **99.95 掉到 8.55**,同源好片被判 fail;② `--stage style/stills/frames/mux` 的门禁 fail
56
- > **没进退出码**(stdout 打 [FAIL]、进程仍 exit 0);③ `webengine` 在 `style=None` + 720p 时
57
- > **静默输出 1080p 原画的左上角裁切**(逐像素相同、标题/HUD 全丢、exit 0);
58
- > ④ `visual.layout` 与 `qa.vmaf.sample_step` 写了**完全没人读**;⑤ `selfcheck` 第 51 条把金帧
59
- > 的 skipped 当 PASS(**这条门禁从没真的比过一帧**);⑥ `ci_check` 把"跳过(没装 node)"记成 PASS。
60
- > 详见 [CHANGELOG.md](CHANGELOG.md) 的 0.8.1 段(含行为变化表与升级须知)。
61
-
62
- ## 安装
63
-
64
- 桌面版:插件管理器 → 填 `@dsh-gis/dsh-video-studio-skill`(或本地目录 `D:\self\code\dsh-video-studio-skill`)
65
-
66
- 命令行:
67
-
68
- ```bash
69
- dsh plugin --profile desktop add "@dsh-gis/dsh-video-studio-skill"
70
- # 本地调试(不发布也能装):
71
- dsh plugin --profile desktop add "D:/self/code/dsh-video-studio-skill"
72
- ```
73
-
74
- 安装后在「插件」页启用 `video-studio` 这一行,新开会话即可在技能目录看到 **video-studio**。
75
-
76
- ### 与手工技能目录的关系
77
-
78
- 技能按 rank 解析:`~/.dsh/skills`(rank 400)**优先于**插件提供的 bundled 技能根(rank 600)。
79
- 如果你之前手工装过 `~/.dsh/skills/video-studio`,它会把插件版本遮住。装好插件后**把旧目录移出 `~/.dsh/skills` 根目录**(只改名不够——扫描认的是 `<root>/<name>/SKILL.md`,`.bak` 后缀的目录照样会被扫到):
80
-
81
- ```bash
82
- mkdir -p ~/.dsh/backup
83
- mv ~/.dsh/skills/video-studio ~/.dsh/backup/video-studio.bak-$(date +%Y%m%d)
84
- ```
85
-
86
- 需要回滚时把目录移回 `~/.dsh/skills/video-studio` 即可。
87
-
88
- ## 效果(不是渲染出来的"宣传图",是默认模板片的真实抽帧)
89
-
90
- <p align="center"><img src="docs/demo-pil-sheet.png" width="100%" alt="默认模板片联系表:开场 / 正文卡片 / 正文卡片 / 收尾"></p>
91
-
92
- 上面四帧是用仓库自带的 `assets/film.json` + `assets/scenes.py` 从零跑一遍 `python render.py` 的
93
- `work/qa/sheet.png`,未经任何修图。配套实测(**作者机器** Windows 11 / OSGeo4W Python 3.12,
94
- v0.6 时期口径;TTS 实测时长与 AAC 编码会让这些数字在小范围内浮动,换机请按 SKILL.md §14 重测):
95
- **时长 30.10 s / 1920×1080 / 30 fps / h264+aac 48 kHz / -16.0 LUFS / 真峰 -1.2 dBTP / 黑帧 0 /
96
- 帧级深检:闪烁 0、空窗 0、画面静止 0**(音画同步在 PIL 路线上需要写 `visual_at` 才会真的查,见 SKILL.md §7)。
97
-
98
- 怎么复现:按 [SKILL.md §1](skills/video-studio/SKILL.md) 的五步上手,把自带模板拷到**空目录**里跑一遍即可
99
- (`cp assets/film.json assets/scenes.py` + 拷 `scripts/*.py` → `python render.py`)。数字每次都会差一点:
100
- TTS 实测时长、AAC 编码都会让真峰/响度/锐度浮动,**别 chasing 小数点**。本机(另一台)复测同模板得到的是
101
- 29.00 s / -16.5 LUFS / -1.4 dBTP / 锐度比 1.01(2026-11-10 另一台 Windows 机器复测)——
102
- **不同机器、不同 TTS 结果,两组都对,别混着引用**。
103
-
104
- ## 效果:同一个模板,八种气质(v0.5)
105
-
106
- 同一份文字,只改 `"style"`(画风 / 配乐 / 旁白 / 节奏一起变):
107
-
108
- <p align="center"><img src="docs/styles/sheet-8-styles.png" width="100%" alt="8 套风格对比:科技深蓝 / 杂志暖白 / 手绘纸感 / 活力撞色 / 极简黑白 / 电影青橙 / 暖灰薄荷 / 深黑鎏金"></p>
109
-
110
- 三份**不同题材**的短片(全流程真跑:TTS → 排轴 → 配乐 → 音效 → 混音 → 逐帧 → 编码 → 质检;数据见
111
- `docs/styles/demo-results.json`,是 v0.5 时期的实测快照,片源脚本未随仓库分发,**不可直接复现**;
112
- **别把这张表当成"现在跑出来就是这样"**——BPM/调性由内容指纹从风格梯度里选(v0.7 起指纹还参与配乐结构),
113
- 同一题材换一版正文就可能落到别的 BPM/调性,当前风格解析结果请以 `--stage style` 的打印为准):
114
-
115
- | 题材 | 自动选中的风格 | 配乐 | 旁白声线 | 质检 |
116
- |---|---|---|---|---|
117
- | AI 大模型的三年 | tech-deep 科技深蓝 | 小调 116BPM / Em | 青年开场 → 男声正文 → 女声引用 | PASS(17.3s,-16.0 LUFS) |
118
- | 手工木作的一天 | paper 手绘纸感 | 大调 88BPM / G | 女声 + 软糯女声正文 | PASS(19.9s) |
119
- | 深夜学习指南 | lo-fi 暖灰薄荷 | 大调 84BPM / F | 温柔女声 + 女声开场 | PASS(20.1s) |
120
-
121
- <p align="center"><img src="docs/styles/sheet-ai.png" width="32%" alt="AI 题材"><img src="docs/styles/sheet-craft.png" width="32%" alt="手作题材"><img src="docs/styles/sheet-night.png" width="32%" alt="深夜题材"></p>
122
-
123
- 三片的联系表(左→右为时间顺序)肉眼可见不是同一套风格:深蓝科技 / 牛皮纸手作 / 冷灰薄荷深夜。
124
-
125
- ## 用法
126
-
127
- 触发词:做一个视频 / 生成宣传片 / 把报告变成视频 / 做动画 / 配音配字幕 / 出成片 /
128
- 修视频音画不同步 / 视频画质糊,或提到 ffmpeg、edge-tts、逐帧渲染、字幕、分镜、配乐、混音。
129
-
130
- 最短路径(技能 `SKILL.md` 第 1 节有完整版):
131
-
132
- ```bash
133
- mkdir -p myfilm && cd myfilm
134
- cp <SKILL_DIR>/assets/film.json . # 剧本模板("style": "auto")
135
- cp <SKILL_DIR>/assets/scenes.py . # 场景模板
136
- cp <SKILL_DIR>/scripts/*.py . # filmkit/stylekit/voicekit/render/selfcheck + sfxkit/scorekit/qa_frames/webengine
137
- # v0.8 还含 preflight/qaasr/qavmaf(可选:缺了对应门禁记 skipped)
138
- cp -r <SKILL_DIR>/assets/web ./web # 只在走浏览器引擎时需要
139
-
140
- python selfcheck.py # 51 条环境/回归断言(20 秒内,不联网)
141
- python <REPO>/tools/estimate.py --script film.json # v0.6:开渲前先算耗时/磁盘/分块(仓库/包里的工具,
142
- # 不在 skills/video-studio/ 内,quickstart 拷出来的目录没有它)
143
- # v0.8:已含 preflight/vmaf/asr 三段;29 s 模板片
144
- # 预演 total 28.4 s -> 37.5-83.0 s(区间上界,实测 47.3 s)
145
- python render.py --stage stills --stills "l01:3,l02:5" # 母版预览(缺 tts/layout 会自动补跑)
146
- python render.py --script film.json --scenes scenes.py --out out/film.mp4 --work work
147
- cat out/QC-REPORT.md # v0.6:机器可读交付结论(pass/fail/skipped)
148
- python render.py --stage accept --gate release # v0.6:人工签核(绑内容指纹)
149
- ```
150
-
151
- 分阶段(每步落盘、可单独重跑):
152
-
153
- ```
154
- tts → layout → cues → score → sfx → audio → frames → mux → qa
155
- ```
156
-
157
- **三种玩法**:
158
-
159
- | 想要 | 怎么做 |
160
- |---|---|
161
- | 只加"该响的地方响一下" | 写 `film.json` 的 `sfx.cues` 或 `scenes.py` 的 `cues()` 钩子 → `--stage cues sfx audio` |
162
- | 整片要一段像样的配乐 | 设 `bpm` / `music.mode=score` → `--stage score` |
163
- | 画面要粒子/形变/着色器 | `--engine web` + 拷 `assets/web/`,改页面里的场景代码 |
164
-
165
- **v0.4 的两个新开关**(都是"让门禁真的会失败",不是新玩具):
166
-
167
- | 想要 | 怎么做 |
168
- |---|---|
169
- | 让 PIL 路线的音画同步门禁真的生效 | cue 加 `"visual_at": 绝对秒`;再把 `QA_REQUIRE_SYNC=1` 加进你自己的交付流水线(本仓库的 workflow 没设它) |
170
- | 浏览器渲染要跨会话字节级可复现 | `--deterministic`(或 `WEBENGINE_DETERMINISTIC=1`),代价约 +22%/帧 |
171
-
172
- `<SKILL_DIR>` 是 `skill` 工具加载时回报的 resourceBase 目录(`.../skills/video-studio/`);
173
- `<REPO>` 是包根(仓库根,或装好后 profile 里的 `node_modules/@dsh-gis/dsh-video-studio-skill/`),即 `<SKILL_DIR>` 往上两级——`tools/`、`schemas/` 都在 `<REPO>` 下,`cp` 到 `myfilm/` 后那里**没有** `tools/`。
174
-
175
- 分阶段(v0.2 起**每个 stage 只做自己的事**):`--stage style | tts | layout | cues | score | sfx | audio | frames | mux | qa | stills | accept | explain`。
176
-
177
- **v0.6 的三个新开关**(都是"让结论可追责",不是新玩具):
178
-
179
- | 想要 | 怎么做 |
180
- |---|---|
181
- | 交付前把"没执行"也算失败 | `--stage qa --strict-gates`(对齐 `QA_REQUIRE_SYNC` 语义) |
182
- | 改完东西不知道要重跑什么 | `--stage explain`(机器判断过时阶段 + 给最小重跑命令),表见 [references/change-impact.md](skills/video-studio/references/change-impact.md) |
183
- | 规整 `film.json` 避免静默失效 | `python skills/video-studio/scripts/filmcheck.py film.json`(`holds`→提示写成 `hold`) |
184
-
185
- **v0.8 的四个新开关**(前三个会改变门禁结果,第四个只是看片更快):
186
-
187
- | 想要 | 怎么做 |
188
- |---|---|
189
- | 交付 720p / 换帧率 | `film.json` 写 `"video": {"width":1280,"height":720,"fps":24}`(只做 16:9 横屏、只能下采样;720p 已实测全门通过) |
190
- | 批量出片 | `python render.py --batch films.json`(≤100 条、开跑前全量预检、单条失败不阻断、末尾 `batch-report.json`) |
191
- | 只渲前 N 秒给人看 | `--preview 15`(出 `out/preview/*.mp4` + `.gif`,不写交付账本) |
192
- | 让 QA 快一点 | `--vmaf sample`(每 5 帧取 1,实测 8.0 s vs 全片 14.2 s,VMAF 只差 0.34)或 `--vmaf off`(G11 记 skipped) |
193
-
194
- 长片:`--stage frames --jobs 4`(按绝对帧号分块并行)+ `--resume`(中断只补缺块)。
195
-
196
- ## 这个技能解决什么
197
-
198
- | 铁律 | 怎么保证 |
199
- |---|---|
200
- | 音画不同步 | 时间轴由 TTS **实测时长**反推,绝不按字数估算 |
201
- | 文字发虚 | PIL 帧走 `rawvideo` 直通 libx264,不用 cv2 中间文件二次压缩 |
202
- | 后半段静音 | numpy 采样级混音,不用一条 ffmpeg 命令喂上百个输入 |
203
- | 该有的淡入/字幕静默消失 | 质检门禁查"必须有"和"不能有"两类断言 |
204
- | 成片"像草稿" | -16 LUFS / 真峰 ≤ -1 dBTP / 编码锐度比 ≥ 0.85 |
205
- | **声音和画面对不上(v0.3)** | **提示点系统**:画面登记 cue → 音效按 cue 合成,改节奏不用重新对时间 |
206
- | **声音单薄、只有"叮叮咚咚"(v0.3)** | `sfxkit` 物理建模音效 + `scorekit` 一张和弦表贯穿全片 |
207
- | **一帧白闪/两秒空窗没人发现(v0.3)** | `qa_frames` 帧级深检:单帧闪烁、画面空窗、音画同步 |
208
- | **"我查过了"无法复现(v0.6)** | `out/QC-REPORT.md` + `work/gates.json`:三档 gate matrix,"没执行"独立成 `skipped` |
209
- | **"我签过了"变成空头支票(v0.6)** | 签核绑内容指纹:改剧本 / `scenes.py` / 引擎,旧签核自动失效 |
210
- | **改一句台词不知道要重跑什么(v0.6)** | `work/manifest.json` 记每阶段输入/输出指纹,`--stage explain` 直接给最小重跑命令 |
211
- | **`holds` 写成拼写错误却静默失效(v0.6)** | `schemas/film.schema.json` + `filmcheck.py`,并接进 `ci_check` 第 12 项 |
212
-
213
- ## 文件结构
214
-
215
- ```
216
- index.js 插件入口:把 skills/ 挂成 bundled 技能根
217
- cordis.patch.yml 组合包 patch(insert: video-studio)
218
- icon.svg / locale/*.json 插件页展示元数据
219
- skills/video-studio/
220
- SKILL.md 主线:上手 / 八阶段 / 引擎选型 / 画质 / 声音 / 提示点 / 停留窗口 / 质检 / 故障速查
221
- references/ pipeline · scene-authoring · audio · audio-variation · sfx-design · web-engine
222
- frame-qa · quality-gates · change-impact · style-packs · pitfalls
223
- word-timeline(v0.8)· v08-quality(v0.8)
224
- scripts/filmkit.py 生产内核(字体/排版/字幕/音频总线/CueBus/TTS/时间轴/编码/质检)
225
- scripts/gates.py v0.6 门禁账本 / QC 报告渲染 / 人工签核(绑内容指纹)
226
- scripts/stagewatch.py v0.6 阶段新鲜度(work/manifest.json + --stage explain)
227
- scripts/filmcheck.py v0.6 film.json 契约校验(未知键/枚举/跨字段)
228
- scripts/render.py 编排器(13 个 stage、pil|web 双引擎、分块并行、断点续跑、母版预览、门禁账本;
229
- v0.8 增 --batch / --preview / --run-id / --vmaf / --no-preflight)
230
- scripts/preflight.py v0.8 渲染前资源预检(字形 / TTS 音频 / 字体 / web 入口页,门禁 G0)
231
- scripts/qavmaf.py v0.8 全片 VMAF/SSIM(参考帧由场景函数实时重渲,门禁 G11)
232
- scripts/qaasr.py v0.8 ASR 回读(成片音轨转文字对账,门禁 G12)
233
- scripts/selfcheck.py 回归自检(51 条"曾真的坏过"的断言)
234
- scripts/sfxkit.py 物理建模音效库(24 配方,scipy 可选)
235
- scripts/scorekit.py 程序化配乐(和弦表 / 分段能量 / 吸气)
236
- scripts/webengine.py 浏览器逐帧渲染(CDP 截图、分块并行、崩溃重开、cue 导出、文字质检)
237
- scripts/qa_frames.py 帧级深检(单帧闪烁 / 画面空窗 / 画面静止 / 音画同步 / 亮度响度曲线)
238
- requirements.txt Python 依赖(必需 / 强烈建议 / 可选三档,带注释)
239
- assets/film.json 剧本模板(含 bpm / music / sfx.cues / 逐句 hold;顶层 hold 可选,缺省用风格 pacing)
240
- assets/scenes.py 场景模板(开场 / 正文卡片 / 收尾 + cues() 钩子)
241
- assets/golden_frames.json v0.8 金帧基线(3 帧 sha256 + 字体/环境指纹,改绘制代码后重录)
242
- assets/web/ 浏览器页面模板(原生 Canvas2D 确定性时间轴;v0.8 读 window.__STYLE__)
243
- tools/ci_check.py 仓库级体检(12 项;语法/JSON/依赖白名单/打包卫生/文档引用/film 契约,不需 ffmpeg)
244
- tools/estimate.py 开渲前成本预演(帧数/耗时/磁盘/分块建议,--json 可机读;v0.8 含 preflight/vmaf/asr)
245
- tools/golden_frames.py v0.8 金帧像素回归(--write 重录 / --check 校验;同环境像素变了 = fail)
246
- tools/audio_similarity.py 音频差异/相似度验收(--strict 阈值判定,改音频代码后必跑)
247
- tools/selftest_noscipy.py 无 scipy 兜底路径自检(CI 用;屏蔽 scipy 后跑 sfxkit/scorekit 自检)
248
- schemas/film.schema.json film.json 的契约(draft-07 子集)
249
- .github/workflows/ci.yml CI:repo 体检(ubuntu+windows)+ 技能自检(ubuntu)
250
- ```
251
-
252
- ## 环境前提
253
-
254
- **插件运行**:Node.js ≥ 20(`package.json` 的 `engines`;这是 DSH 加载插件用的运行时,不必另装)。
255
- **必需**:ffmpeg + Python 的 numpy / Pillow / edge-tts。
256
- **可选**:cv2(编码锐度比)、scipy(音效滤波加速,缺了走 FFT 卷积)、
257
- playwright + Chromium/Edge(只在 `--engine web` 时需要)、
258
- faster-whisper(v0.8 的 ASR 回读门禁 G12;没装会降级到 ffmpeg whisper 滤镜,仍不可用则记 skipped)。
259
- v0.8 的 G11(全片 VMAF)不需要新依赖,但要求 ffmpeg 构建**带 libvmaf**(9.0.2 full_build 有)。
260
- 不需要 moviepy / pydub / soundfile / librosa / manim——本技能一行都不 import 它们。
261
-
262
- 依赖清单有机器可读的一份,别再手抄:
263
-
264
- ```bash
265
- pip install -r skills/video-studio/requirements.txt # 必需 + 强烈建议;可选项目已注释,按需打开
266
- ```
267
-
268
- `SKILL.md` 第 12 节是作者机器(Windows 11 + Ryzen AI 9 HX 370)的实测基准,**换机请先重测**:
269
- `ffmpeg -version`、`python -c "import numpy,PIL,cv2"`、中文字体文件、`edge-tts --list-voices`。
270
- ffmpeg 路径可用环境变量 `FILMKIT_FFMPEG` 覆盖,字体候选在 `filmkit.FONT_CANDIDATES`。
271
-
272
- ## 更新日志
273
-
274
- 见 [CHANGELOG.md](CHANGELOG.md)。
275
-
276
- ## 兼容性
277
-
278
- peer 范围 `@deepseek-ai/dsh-skill-filesystem >=0.1.0-rc.6 <0.3.0-0`,覆盖 DSH 0.1.x / 0.2.x 的**正式版**。
279
-
280
- ⚠️ **预发布版按 semver 规则不满足这个范围**:`>=0.1.0-rc.6 <0.3.0` 这组比较器里没有带预发布标签的
281
- 基准,所以 `0.2.2-rc.1` 这类版本 `semver.satisfies()` 返回 false(实测)。因为该 peer 标了
282
- `optional`,pnpm 不会因此阻断安装;插件入口也已经把依赖改成 `apply` 内按需 `import`——
283
- 缺这个包时**只降级(不挂载 bundled 技能根)并打一条能照着做的日志,不会让整个插件行加载失败**。
284
-
285
- ## 仓库自检(给贡献者与 CI 用,不是给用户用的)
286
-
287
- ```bash
288
- python tools/ci_check.py -v # 12 项:py 语法(含 tools/,SyntaxWarning 记失败)/ node --check /
289
- # JSON + 版本号一致性(package.json vs README 徽章)/ 技能清单 /
290
- # 依赖白名单 / npm pack 打包卫生 / 文档路径 + 正文相对链接 /
291
- # Python 3.9 语法 / Markdown 围栏(状态机)/ CI workflow
292
- # (裸冒号 + run 里的 python 脚本是否存在)/ 单文件体积 /
293
- # film.json 契约(调 filmcheck.py,规则只留一份)
294
- ```
295
-
296
- 它**不需要 ffmpeg、字体或网络**,任何机器都能跑;它检查的是"这个仓库作为可分发包是否完整"。
297
- **它不能替代** `skills/video-studio/scripts/selfcheck.py`——那个要 ffmpeg + 中文字体,真的调编码器,
298
- 查的是"技能本身还能不能出片"。两层都在 `.github/workflows/ci.yml` 里跑。
299
-
300
- ## License
301
-
302
- MIT。新增的四个模块(sfxkit / scorekit / webengine / qa_frames)的**算法思想**改编自
303
- [ai-history-film](https://github.com/Re-Summer75/ai-history-film)(MIT),未复制其文件、未引入其三方依赖;
304
- 详见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。
1
+ # @dsh-gis/dsh-video-studio-skill
2
+
3
+ ![version](https://img.shields.io/badge/version-1.0.2-blue) ![license](https://img.shields.io/badge/license-MIT-green)
4
+
5
+ **DeepSeek Harness 技能插件:用代码从零生成中文视频。**
6
+
7
+ 写剧本 → edge-tts 旁白 → **实测时长**排时间轴 → **提示点**驱动配乐与音效 → PIL 或浏览器逐帧渲染 →
8
+ ffmpeg 编码 → 采样级混音 → **四层质检**(容器 / 信号 / 时间 / 页面)+ **v0.8 的四个新闸**
9
+ (渲前资源预检 `G0` / 词级时间戳 `G10` / 全片 VMAF `G11` / ASR 回读 `G12`)。
10
+ 零素材、可复现、可断点续跑、可脚本化验收;装成插件后,整片生产流程随技能一起进入每个会话。
11
+
12
+ > **v1.0.2(当前)**:**零拷贝出片**——技能脚本留在技能目录里直接跑,工程目录里只需要一个 `film.json`;
13
+ > `render.py` 不写 `--scenes` 就先用剧本同目录的 `scenes.py`、再回落到技能内置的 `assets/scenes.py`,
14
+ > 不需要再拷脚本/模板。设计与画面新增两块可调:**字幕样式** `visual.subtitle`
15
+ > (字号/位置/对齐/背板透明度/圆角/字族/颜色/最多几行,不写 = 与过去逐像素一致)与
16
+ > **片内版式轮换** `visual.layout_cycle`(按章节换骨架,默认派生 2–3 种,防"全片一张版式")。
17
+ > 同时修掉一批"照文档做就崩"的命令(`--stage style` 不再 KeyError、`--stage cues` 可单跑、
18
+ > 已删除 API 改为明确报错 exit 2 而不是 NameError/假绿),并给"不同片不重复"加了**片间去重台账**
19
+ > (`--confirm` 记录交付过的设计,下次提案主动避开)。
20
+ > 另外 brief 里写「2 分钟 / 90 秒」现在会被接住:解析成 `duration_target`,决定候选段落数,
21
+ > 渲染时对账并在差 >15% 时告警——但**成片长度仍由实测旁白决定,不会截断**。自检 **67 条**全绿。
22
+
23
+ > 源自 `dsh-v` 资产包的 `02-技能包-video-studio`(817 个 DSH 会话的考古分析 + 5 套现存工程逆向 + 本机实测)。
24
+ > 版本演进与每一版的实测证据都在 [CHANGELOG.md](CHANGELOG.md);这里只留一句方向:
25
+ > **v1.0 起不再提供任何模板/风格目录**——技能给的是「生成视频的技术」,外观由每次现场采样的设计决定。
26
+ >
27
+ > 重要节点:v0.6 交付可信化(门禁账本 / QC 报告 / 签核)→ v0.7 声音片间差异 → v0.8 词级时间轴 + 四道新门禁
28
+ > → v0.9 场景语法(10 类构图)与视觉语言 → **v1.0 提案优先**(先出方案再出片)→ **v1.0.1 清除全部模板**
29
+ > → **v1.0.2 零拷贝 + 可定制字幕/版式轮换 + 片间去重台账**。
30
+ >
31
+ > 想直接看「这一版改了什么、为什么改、怎么验证」,读 [CHANGELOG.md](CHANGELOG.md) 的 1.0.2 段;
32
+ > 想学怎么控制画面/声音/节奏,读 [SKILL.md](skills/video-studio/SKILL.md)。
33
+ ## 安装
34
+
35
+ 桌面版:插件管理器 → 填 `@dsh-gis/dsh-video-studio-skill`(或你的本地 checkout 目录,如 `D:/path/to/dsh-video-studio-skill`)
36
+
37
+ 命令行:
38
+
39
+ ```bash
40
+ dsh plugin --profile desktop add "@dsh-gis/dsh-video-studio-skill"
41
+ # 本地调试(不发布也能装):
42
+ dsh plugin --profile desktop add "D:/path/to/dsh-video-studio-skill"
43
+ ```
44
+
45
+ 安装后在「插件」页启用 `video-studio` 这一行,新开会话即可在技能目录看到 **video-studio**。
46
+
47
+ ### 与手工技能目录的关系
48
+
49
+ 技能按 rank 解析:`~/.dsh/skills`(rank 400)**优先于**插件提供的 bundled 技能根(rank 600)。
50
+ 如果你之前手工装过 `~/.dsh/skills/video-studio`,它会把插件版本遮住。装好插件后**把旧目录移出 `~/.dsh/skills` 根目录**(只改名不够——扫描认的是 `<root>/<name>/SKILL.md`,`.bak` 后缀的目录照样会被扫到):
51
+
52
+ ```bash
53
+ mkdir -p ~/.dsh/backup
54
+ mv ~/.dsh/skills/video-studio ~/.dsh/backup/video-studio.bak-$(date +%Y%m%d)
55
+ ```
56
+
57
+ 需要回滚时把目录移回 `~/.dsh/skills/video-studio` 即可。
58
+
59
+ ## 效果:同一个 brief,两次就是两部不同的片(可复现)
60
+
61
+ 这一节不贴"宣传图"——**贴的是你现在就能跑出来的东西**。向同一个 brief 连续提案两次,
62
+ 配色、母题、转场、配乐、声线、版式轮换、字幕样式都会不同(这就是 v1.0 提案优先 + v1.0.2 片间去重的目标):
63
+
64
+ ```bash
65
+ # 第一轮:看 3 个候选并排(每个候选 = 一份完整设计 + 静帧联系表 + 与其它候选的设计距离)
66
+ python <SKILL_DIR>/scripts/propose.py --brief "AI 大模型的三年,30 秒科普,深蓝" --script film.json --work work
67
+ # 候选 A 深色 h201·四角括线 3 帧 0.9s -> work/proposals/rev1/A/_sheet.png
68
+ # 候选 B 深色 h220·细线页眉 3 帧 0.6s -> work/proposals/rev1/B/_sheet.png
69
+ # 候选 C 深色 h213·极简留白 3 帧 0.6s -> work/proposals/rev1/C/_sheet.png
70
+ # 联系表(并排对比): work/proposals/rev1/_compare.png
71
+
72
+ # 换一个 work 目录再跑一次同一句 brief —— 会得到另一组设计(不传 --seed 就是每次新 nonce)
73
+ python <SKILL_DIR>/scripts/propose.py --brief "AI 大模型的三年,30 秒科普,深蓝" --script film.json --work work2
74
+ ```
75
+
76
+ > 实测(作者机器,2026-11-11):同一 brief 连跑 3 次,9 个候选的 `design_fingerprint` **两两不同**;
77
+ > 每批 3 个候选的 `layout_cycle` 都是 2–3 种版式,`subtitle` 的字号/对齐/背板透明度/圆角/字族也各不相同。
78
+ > 带「深蓝」这类配色约束时,v1.0.2 之前 n=3 有近一半概率采样失败(约束窗口只有 52°,
79
+ > 而旧实现按 24° 分桶判重),现在实测 **10/10 成功**。
80
+
81
+ **三个可复现的卖点**:
82
+
83
+ | 卖点 | 怎么自己验证 | 看什么 |
84
+ |---|---|---|
85
+ | 同一个 brief 两次结果不同 | 同一句 `--brief` 换 `--work` 目录跑两次 | 候选表的「立意」与配色色相都不一样;`design_fingerprint` 不同 |
86
+ | 三个候选并排对比 | `propose.py` 末尾会打印联系表路径 | `work/proposals/rev1/_compare.png`:一行一个候选,带中文立意标签 |
87
+ | 版式与字幕可变 | `render.py --stage layout` / `--stage style` | `storyboard.json` 每段的 `layout` 字段;`--stage style` 打印的「版式轮换」与「字幕」行 |
88
+
89
+ **画面长什么样,由设计决定而不是由"第几套模板"决定**:10 类构图(hero / statement / list / stat /
90
+ compare / process / quote / chapter / chart / outro)× 8 种装饰母题 × 6 种转场 × 连续色相配色 ×
91
+ 字幕样式 × 按章节轮换的版式——而且每个候选都要过 `theme_lint` 对比度体检和 G13 剪影可区分门禁。
92
+
93
+ > 说明:仓库里的 `docs/` 图片是 **v0.5/v0.9 时期的历史快照**,对应的 `style:auto` 选型与风格表
94
+ > 在 v1.0.1 已删除,**这些图不能再当"现在跑出来就是这样"的证据**,所以本 README 不再引用它们。
95
+ > 现在的证据是**命令 + 你机器上的实测输出**。
96
+
97
+ ## 用法(零拷贝:不拷脚本、不拷模板)
98
+
99
+ 触发词:做一个视频 / 生成宣传片 / 把报告变成视频 / 做动画 / 配音配字幕 / 出成片 /
100
+ 修视频音画不同步 / 视频画质糊,或提到 ffmpeg、edge-tts、逐帧渲染、字幕、分镜、配乐、混音。
101
+
102
+ **最短路径**([SKILL.md §1](skills/video-studio/SKILL.md) 有带注释的完整版):
103
+
104
+ ```bash
105
+ mkdir -p myfilm && cd myfilm
106
+ # 1) 只写一个 film.json(工程目录里唯一需要你手写的文件;最小骨架见 SKILL.md §1)
107
+
108
+ # 2) 环境自检(可选,67 条断言,不联网)
109
+ python <SKILL_DIR>/scripts/selfcheck.py
110
+
111
+ # 3) 先出方案:3 个候选,各带静帧联系表;2 秒级、全程离线
112
+ python <SKILL_DIR>/scripts/propose.py --brief "AI 大模型的三年,30 秒科普" --script film.json --work work
113
+
114
+ # 4) 确认候选,冻结设计 -> work/design.json(此后渲染只认这份设计)
115
+ python <SKILL_DIR>/scripts/propose.py --confirm --candidate A --work work
116
+
117
+ # 5) 先看静帧,再出全片。--scenes 不写 = 剧本同目录 scenes.py -> 技能内置 assets/scenes.py
118
+ python <SKILL_DIR>/scripts/render.py --script film.json --work work --stage stills --stills "l01:3,l02:5"
119
+ python <SKILL_DIR>/scripts/render.py --script film.json --work work --out out/film.mp4 --stage all
120
+
121
+ # 6) 交付凭据 + 人工签核
122
+ cat out/QC-REPORT.md
123
+ python <SKILL_DIR>/scripts/render.py --script film.json --work work --stage accept --gate release
124
+ ```
125
+
126
+ `<SKILL_DIR>` 是 `skill` 工具加载时回报的 resourceBase 目录(`.../skills/video-studio/`);
127
+ `<REPO>` 是包根(仓库根,或装好后 profile 里的 `node_modules/@dsh-gis/dsh-video-studio-skill/`),
128
+ 即 `<SKILL_DIR>` 往上两级——`tools/`、`schemas/` 在 `<REPO>` 下。
129
+
130
+ **分阶段**(`--stage` 每个只做自己的事,落盘后可单独重跑):
131
+ `style | tts | layout | cues | score | sfx | audio | frames | mux | qa | stills | accept | explain | all`。
132
+
133
+ **你想控制什么,就改哪里**:
134
+
135
+ | 想控制 | 改哪里 | 怎么验证 |
136
+ |---|---|---|
137
+ | 画面配色/字体/装饰/转场/版式 | `work/design.json` 的 `visual.*`(或重新提案 `--revise`) | `render.py --stage style`;`designkit.py --lint work/design.json` |
138
+ | 字幕字号/位置/对齐/背板/圆角/字族/颜色/行数 | `visual.subtitle`(v1.0.2) | `--stage style` 打印的「字幕」行;改前后抽帧对比 |
139
+ | 片内版式轮换(防全片一张版式) | `visual.layout_cycle`(v1.0.2),不写则自动派生 2–3 种 | `work/storyboard.json` 每段的 `layout` |
140
+ | 这段画面的构图类型 | `film.json` 的 `lines[].type`(10 类之一),不写由 grammar 选 | `--stage layout` 打印的分镜表 |
141
+ | 配乐调式/BPM/调性/情绪 | `work/design.json` 的 `audio.music.*`(`film.json` 的 `music.*` 可覆盖) | `--stage score` 的打印 + 听 |
142
+ | 旁白声线与语气 | `audio.voice.*`(裸 edge voice id + tone);`voicekit.py --list` 查音色 | `--stage tts`;`work/voice_plan.json` |
143
+ | 音效密度与提示点 | `audio.sfx.*`;提示点写 `film.json` 的 `sfx.cues` 或 `scenes.py` 的 `cues()` | `--stage cues` / `--stage sfx` |
144
+ | 节奏(停顿/最小段长/条目步进) | `pacing.*`;单句停留写 `film.json` 的 `lines[].hold` | `--stage layout` 的总时长 |
145
+ | 目标时长(如「2 分钟」) | `--brief` 里写出来 → `design.structure.target_sec` | `propose` 打印目标时长;渲染时对账,差 >15% 告警。**成片长度仍由实测旁白决定,不会截断** |
146
+ | 画面本身(绘制代码) | 剧本同目录放自己的 `scenes.py`(实现 `draw_frame`,可选 `cues()`) | `--stage stills` 抽帧看 |
147
+
148
+ **常用开关**:
149
+
150
+ | 想要 | 怎么做 |
151
+ |---|---|
152
+ | 交付 720p / 换帧率 | `film.json` 写 `"video": {"width":1280,"height":720,"fps":24}`(只做 16:9 横屏、只能下采样) |
153
+ | 批量出片 | `python <SKILL_DIR>/scripts/render.py --batch films.json`(≤100 条、开跑前全量预检、单条失败不阻断) |
154
+ | 只渲前 N 秒给人看 | `--preview 15`(出 `out/preview/*.mp4` + `.gif`,不写交付账本) |
155
+ | 让 QA 快一点 | `--vmaf sample`(每 5 帧取 1)或 `--vmaf off`(G11 记 skipped) |
156
+ | 交付前把「没执行」也算失败 | `--strict-gates` |
157
+ | 改完东西不知道要重跑什么 | `--stage explain`(机器判断过时阶段 + 给最小重跑命令) |
158
+ | 换一个候选/方向重出方案 | `propose.py --revise "再冷一点,少装饰,换女声"`;旧 rev 留着眼 diff |
159
+ | 复现某一次提案 | 首次提案加 `--seed 42`(不传 seed = 每次新 nonce) |
160
+ | 忽略/查看片间去重台账 | `--no-ledger` / `--show-ledger`;路径可用 `VIDEO_STUDIO_LEDGER` 覆盖 |
161
+ | 浏览器渲染要跨会话字节级可复现 | `--deterministic`(或 `WEBENGINE_DETERMINISTIC=1`),代价约 +22%/帧 |
162
+
163
+ 长片:`--stage frames --jobs 4`(按绝对帧号分块并行)+ `--resume`(中断只补缺块)。
164
+
165
+ ## 这个技能解决什么
166
+
167
+ | 铁律 | 怎么保证 |
168
+ |---|---|
169
+ | 音画不同步 | 时间轴由 TTS **实测时长**反推,绝不按字数估算 |
170
+ | 文字发虚 | PIL 帧走 `rawvideo` 直通 libx264,不用 cv2 中间文件二次压缩 |
171
+ | 后半段静音 | numpy 采样级混音,不用一条 ffmpeg 命令喂上百个输入 |
172
+ | 该有的淡入/字幕静默消失 | 质检门禁查"必须有"和"不能有"两类断言 |
173
+ | 成片"像草稿" | -16 LUFS / 真峰 ≤ -1 dBTP / 编码锐度比 ≥ 0.85 |
174
+ | **声音和画面对不上(v0.3)** | **提示点系统**:画面登记 cue → 音效按 cue 合成,改节奏不用重新对时间 |
175
+ | **声音单薄、只有"叮叮咚咚"(v0.3)** | `sfxkit` 物理建模音效 + `musicgen` 按参数现场编排配乐(没有现成曲风可选) |
176
+ | **一帧白闪/两秒空窗没人发现(v0.3)** | `qa_frames` 帧级深检:单帧闪烁、画面空窗、音画同步 |
177
+ | **"我查过了"无法复现(v0.6)** | `out/QC-REPORT.md` + `work/gates.json`:三档 gate matrix,"没执行"独立成 `skipped` |
178
+ | **"我签过了"变成空头支票(v0.6)** | 签核绑内容指纹:改剧本 / `scenes.py` / 引擎,旧签核自动失效 |
179
+ | **改一句台词不知道要重跑什么(v0.6)** | `work/manifest.json` 记每阶段输入/输出指纹,`--stage explain` 直接给最小重跑命令 |
180
+ | **`holds` 写成拼写错误却静默失效(v0.6)** | `schemas/film.schema.json` + `filmcheck.py`,并接进 `ci_check` 第 12 项 |
181
+ | **机器替你选风格、你从头到尾没参与(v1.0)** | **提案优先**:`propose.py` 先出 N 个候选(各带静帧联系表 + 设计距离),人 `--confirm` 后才冻结 `design.json` |
182
+ | **每个视频都差不多(v1.0/v1.0.2)** | 设计 DSL 现场采样(每次新 nonce)+ 候选两两 ≥2 维不同 + 底色色相分叉 + **片间去重台账**(默认记录交付过的设计并主动避开) |
183
+ | **外观只能从几套模板里挑(v1.0.1)** | 没有内置风格表:配色是连续色相空间、母题/转场/缓动/版式/字幕全字段开放,且必须过 `theme_lint` 与 G13 剪影门禁 |
184
+
185
+ ## 文件结构
186
+
187
+ ```
188
+ index.js 插件入口:把 skills/ 挂成 bundled 技能根
189
+ cordis.patch.yml 组合包 patch(insert: video-studio)
190
+ icon.svg / locale/*.json 插件页展示元数据
191
+ skills/video-studio/
192
+ SKILL.md 主线:零拷贝上手 / 提案 / 设计 DSL / 八阶段 / 引擎 / 画质 / 声音 / 提示点 / 质检 / 升级
193
+ references/ proposal · scene-grammar · pipeline · scene-authoring · audio · audio-variation
194
+ sfx-design · web-engine · frame-qa · quality-gates · word-timeline · v08-quality
195
+ change-impact · style-packs(v1.0.2 重写为设计 DSL 外观定制)· pitfalls
196
+ scripts/propose.py v1.0 提案器(--brief/--revise/--confirm/--diff;v1.0.2 片间去重台账)
197
+ scripts/designkit.py v1.0 设计 DSL(采样/校验/转计划/设计距离/字幕参数)
198
+ scripts/previewkit.py v1.0 离线预览(合成时间轴 + 联系表,不联网)
199
+ scripts/grammar.py v0.9 场景语法(10 类构图 -> storyboard.json)
200
+ scripts/voicekit.py v1.0 声线/语气计划(裸 edge voice id + 响度补偿)
201
+ scripts/filmkit.py 生产内核(字体/排版/字幕/音频总线/CueBus/TTS/时间轴/编码/质检)
202
+ scripts/gates.py v0.6 门禁账本 / QC 报告渲染 / 人工签核(绑内容指纹)
203
+ scripts/stagewatch.py v0.6 阶段新鲜度(work/manifest.json + --stage explain)
204
+ scripts/filmcheck.py v0.6 film.json 契约校验(未知键/枚举/跨字段;style 键为 inert 警告)
205
+ scripts/render.py 编排器(14 个 stage、pil|web 双引擎、分块并行、断点续跑、母版预览、门禁账本;
206
+ v1.0.2 起 --scenes 缺省回落到技能内置 scenes.py)
207
+ scripts/preflight.py v0.8 渲染前资源预检(字形 / TTS 音频 / 字体 / web 入口页,门禁 G0)
208
+ scripts/qavmaf.py v0.8 全片 VMAF/SSIM(参考帧由场景函数实时重渲,门禁 G11)
209
+ scripts/qaasr.py v0.8 ASR 回读(成片音轨转文字对账,门禁 G12)
210
+ scripts/selfcheck.py 回归自检(67 条"曾真的坏过"的断言)
211
+ scripts/sfxkit.py 物理建模音效库(24 配方,scipy 可选)
212
+ scripts/scorekit.py 配乐合成原语(和声 / 律动 / 混音 / 响度 / 24-bit 落盘)
213
+ scripts/musicgen.py 参数化配乐编排器(没有风格表:和弦进行 / 动机 / 鼓型 / 音色全可传参)
214
+ scripts/webengine.py 浏览器逐帧渲染(CDP 截图、分块并行、崩溃重开、cue 导出、文字质检)
215
+ scripts/qa_frames.py 帧级深检(单帧闪烁 / 画面空窗 / 画面静止 / 音画同步 / 亮度响度曲线)
216
+ requirements.txt Python 依赖(必需 / 强烈建议 / 可选三档,带注释)
217
+ assets/film.json 测试夹具(含 bpm / music / sfx.cues / 逐句 hold;不是给用户抄的模板)
218
+ assets/scenes.py 技能内置渲染器(10 类构图 + draw_frame + cues() 钩子;--scenes 的默认回退)
219
+ assets/design_fixture.json 金帧基准设计(像素回归绑它,不绑任何内置风格)
220
+ assets/voice_loudness.json 音色响度补偿实测表
221
+ assets/golden_frames.json v0.8 金帧基线(3 帧 sha256 + 字体/环境指纹,改绘制代码后重录)
222
+ assets/web/ 浏览器页面示例(--engine web 需要你自己的页面;不是出片模板)
223
+ schemas/design.schema.json 设计 DSL 契约(v1.0;含 visual.subtitle / layout_cycle)
224
+ schemas/proposal.schema.json 提案契约(v1.0)
225
+ schemas/film.schema.json film.json 的契约(draft-07 子集)
226
+ tools/ci_check.py 仓库级体检(12 项;语法/JSON/依赖白名单/打包卫生/文档引用/film 契约,不需 ffmpeg)
227
+ tools/estimate.py 开渲前成本预演(帧数/耗时/磁盘/分块建议,--json 可机读;含 preflight/vmaf/asr)
228
+ tools/golden_frames.py v0.8 金帧像素回归(--write 重录 / --check 校验;同环境像素变了 = fail)
229
+ tools/silhouette_qa.py v0.9 剪影可区分门禁 G13(换设计不能只是换色)
230
+ tools/audio_similarity.py 音频差异/相似度验收(--strict 阈值判定,改音频代码后必跑)
231
+ tools/selftest_noscipy.py 无 scipy 兜底路径自检(CI 用;屏蔽 scipy 后跑 sfxkit/musicgen 自检)
232
+ .github/workflows/ci.yml CI:repo 体检(ubuntu+windows)+ 技能自检(ubuntu)
233
+ ```
234
+
235
+ ## 环境前提
236
+
237
+ **插件运行**:Node.js ≥ 20(`package.json` 的 `engines`;这是 DSH 加载插件用的运行时,不必另装)。
238
+ **必需**:ffmpeg + Python 的 numpy / Pillow / edge-tts。
239
+ **可选**:cv2(编码锐度比)、scipy(音效滤波加速,缺了走 FFT 卷积)、
240
+ playwright + Chromium/Edge(只在 `--engine web` 时需要)、
241
+ faster-whisper(v0.8 的 ASR 回读门禁 G12;没装会降级到 ffmpeg whisper 滤镜,仍不可用则记 skipped)。
242
+ v0.8 的 G11(全片 VMAF)不需要新依赖,但要求 ffmpeg 构建**带 libvmaf**(9.0.2 full_build 有)。
243
+ 不需要 moviepy / pydub / soundfile / librosa / manim——本技能一行都不 import 它们。
244
+
245
+ 依赖清单有机器可读的一份,别再手抄:
246
+
247
+ ```bash
248
+ pip install -r skills/video-studio/requirements.txt # 必需 + 强烈建议;可选项目已注释,按需打开
249
+ ```
250
+
251
+ `SKILL.md` 第 12 节是作者机器(Windows 11 + Ryzen AI 9 HX 370)的实测基准,**换机请先重测**:
252
+ `ffmpeg -version`、`python -c "import numpy,PIL,cv2"`、中文字体文件、`edge-tts --list-voices`。
253
+ ffmpeg 路径可用环境变量 `FILMKIT_FFMPEG` 覆盖,字体候选在 `filmkit.FONT_CANDIDATES`。
254
+
255
+ ## 更新日志
256
+
257
+ 见 [CHANGELOG.md](CHANGELOG.md)。
258
+
259
+ ## 兼容性
260
+
261
+ peer 范围 `@deepseek-ai/dsh-skill-filesystem >=0.1.0-rc.6 <0.3.0-0`,覆盖 DSH 0.1.x / 0.2.x 的**正式版**。
262
+
263
+ ⚠️ **预发布版按 semver 规则不满足这个范围**:`>=0.1.0-rc.6 <0.3.0` 这组比较器里没有带预发布标签的
264
+ 基准,所以 `0.2.2-rc.1` 这类版本 `semver.satisfies()` 返回 false(实测)。因为该 peer 标了
265
+ `optional`,pnpm 不会因此阻断安装;插件入口也已经把依赖改成 `apply` 内按需 `import`——
266
+ 缺这个包时**只降级(不挂载 bundled 技能根)并打一条能照着做的日志,不会让整个插件行加载失败**。
267
+
268
+ ## 仓库自检(给贡献者与 CI 用,不是给用户用的)
269
+
270
+ ```bash
271
+ python tools/ci_check.py -v # 12 项:py 语法(含 tools/,SyntaxWarning 记失败)/ node --check /
272
+ # JSON + 版本号一致性(package.json vs README 徽章)/ 技能清单 /
273
+ # 依赖白名单 / npm pack 打包卫生 / 文档路径 + 正文相对链接 /
274
+ # Python 3.9 语法 / Markdown 围栏(状态机)/ CI workflow
275
+ # (裸冒号 + run 里的 python 脚本是否存在)/ 单文件体积 /
276
+ # film.json 契约(调 filmcheck.py,规则只留一份)
277
+ ```
278
+
279
+ 它**不需要 ffmpeg、字体或网络**,任何机器都能跑;它检查的是"这个仓库作为可分发包是否完整"。
280
+ **它不能替代** `skills/video-studio/scripts/selfcheck.py`——那个要 ffmpeg + 中文字体,真的调编码器,
281
+ 查的是"技能本身还能不能出片"(**67 条**断言)。两层都在 `.github/workflows/ci.yml` 里跑。
282
+
283
+ ## License
284
+
285
+ MIT。新增的四个模块(sfxkit / scorekit / webengine / qa_frames)的**算法思想**改编自
286
+ [ai-history-film](https://github.com/Re-Summer75/ai-history-film)(MIT),未复制其文件、未引入其三方依赖;
287
+ 详见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。