@dsh-gis/dsh-video-studio-skill 0.8.1 → 0.9.1
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.
- package/CHANGELOG.md +158 -0
- package/README.md +37 -14
- package/docs/styles/sheet-8-styles.png +0 -0
- package/docs/styles/sheet-before-after.png +0 -0
- package/package.json +4 -2
- package/schemas/film.schema.json +167 -0
- package/skills/video-studio/SKILL.md +66 -9
- package/skills/video-studio/assets/golden_frames.json +8 -8
- package/skills/video-studio/assets/scenes.py +2162 -1190
- package/skills/video-studio/references/audio-variation.md +1 -1
- package/skills/video-studio/references/audio.md +1 -1
- package/skills/video-studio/references/quality-gates.md +1 -1
- package/skills/video-studio/references/scene-grammar.md +306 -0
- package/skills/video-studio/references/style-packs.md +101 -0
- package/skills/video-studio/scripts/filmcheck.py +97 -0
- package/skills/video-studio/scripts/grammar.py +559 -0
- package/skills/video-studio/scripts/render.py +45 -0
- package/skills/video-studio/scripts/selfcheck.py +209 -0
- package/skills/video-studio/scripts/stylekit.py +199 -0
- package/tools/ci_check.py +3 -1
- package/tools/silhouette_qa.py +910 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,164 @@
|
|
|
6
6
|
与 `package.json` 的 `version` 字段只差前缀。历史上曾同时出现 `0.7.1` 与 `v0.7.1` 两种写法
|
|
7
7
|
(前者指向一个未推送的孤儿提交,已删除),此后不再产生不带 `v` 的 tag。
|
|
8
8
|
|
|
9
|
+
## 0.9.1 — 把装饰母题烘焙进底版:消掉 5.6 ms/帧的固定开销(2026-11-10)
|
|
10
|
+
|
|
11
|
+
> 0.9.0 落地后量了一笔账:单帧预算 25 ms,而"逐帧把全屏 RGBA 母题 paste 到画面上"
|
|
12
|
+
> 实测是 **5.6 ms/帧**(Pillow 13 / 1080p),是预算里最大的一笔固定开销——
|
|
13
|
+
> 比 list/hero 的绘制本体(约 3 ms)还贵。
|
|
14
|
+
>
|
|
15
|
+
> 0.9.0 的注释写的是"paste 只要 0.3 ms",这是估算不是实测;这次用
|
|
16
|
+
> `draw_frame` 分段计时才发现差了近 20 倍。**估算当实测写进文档,就是下一个坑。**
|
|
17
|
+
|
|
18
|
+
### 改了什么
|
|
19
|
+
|
|
20
|
+
| 项 | 0.9.0 | 0.9.1 |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| 装饰母题的合成方式 | 母题单独烘焙成 RGBA 图层,**逐帧 `img.paste(lay, (0,0), lay)`** | 母题直接烘焙进**背景底版**(`_plate`),逐帧只 `copy` + `EXTENT`,不再单独 paste |
|
|
23
|
+
| 单帧固定开销 | 约 5.6 ms(paste) | 约 **1.3–2.0 ms**(底版 copy) |
|
|
24
|
+
| 装饰与镜头缓推 | 背景推、装饰不动(cinema / epic 的强 push 下会穿帮:框线留在原地,背景在动) | 装饰跟着底版一起推,两者同一张图,**不再穿帮** |
|
|
25
|
+
|
|
26
|
+
实现位置:`assets/scenes.py` 的 `_motif_key` / `_motif_layer` / `_plate`(母题图层与
|
|
27
|
+
合成底版共用同一把缓存键,改主题色时一起失效,否则会拿到"新图层 + 旧底版"的错配画面)。
|
|
28
|
+
|
|
29
|
+
### 实测数据(本机 Windows 11 / Python 3.12 / ffmpeg 9.0.2;换机请重测)
|
|
30
|
+
|
|
31
|
+
| 项 | 实测 |
|
|
32
|
+
|---|---|
|
|
33
|
+
| 模板片 frames 阶段 | **54–61 fps(约 16.7 s / 870 帧 ≈ 19 ms/帧)**;v0.8.1 约 75 fps(约 13 ms/帧);0.9.0 未优化时 41–50 fps |
|
|
34
|
+
| `draw_frame` 本体(1080p) | `list` **3.1 ms** / `hero` **3.0 ms**(优化前 7.4 / 7.3 ms) |
|
|
35
|
+
| 最贵组合(10 类场景 + 字幕 + `tobytes`) | `epic·outro` **15.1 ms**,仍在 25 ms/帧预算内 |
|
|
36
|
+
| 金帧基线 | 再次重录(3 帧);最终以仓库里的 `assets/golden_frames.json` 为准 |
|
|
37
|
+
|
|
38
|
+
### 结论口径(写文档时别写反)
|
|
39
|
+
|
|
40
|
+
**仍在预算内(约 19 ms/帧 vs 25 ms),但比 v0.8.1 的约 13 ms/帧慢**。
|
|
41
|
+
慢的原因是 10 类构图各自多了装饰与几何——这是功能换来的,不是回退;
|
|
42
|
+
0.9.1 只是把其中那笔 5.6 ms 的固定开销收掉了。
|
|
43
|
+
|
|
44
|
+
### 行为变化
|
|
45
|
+
|
|
46
|
+
| 变化 | 0.9.0 | 0.9.1 | 影响 |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| frames 速度 | 约 41–50 fps | **约 54–61 fps** | 更接近 v0.8.1,但仍慢于它 |
|
|
49
|
+
| 强 push 风格(cinema / epic) | 装饰层不随镜头推,边框与背景分离 | 装饰与背景一起推 | 观感更整;这两个风格的静帧像素与 0.9.0 不同 |
|
|
50
|
+
| 金帧基线 | v0.9.0 的 3 帧 | **重录** | 自己复刻过基线快照的要再 `--write` 一次 |
|
|
51
|
+
|
|
52
|
+
## 0.9.0 — 场景语法 + 视觉语言包:换风格不再只是换色(2026-11-10)
|
|
53
|
+
|
|
54
|
+
> 本轮解决的是 v0.5 没有解决的那一半问题。v0.5 的风格包让"画风/配乐/旁白一起变",
|
|
55
|
+
> 但它只覆盖**皮肤**:配色、字体、纹理、颗粒、字距、缓动、HUD、3 种版式几何。
|
|
56
|
+
> 画面骨架(剪影)没变——用户的原话是"每个视频都差不多,只是主题和颜色不同"。
|
|
57
|
+
>
|
|
58
|
+
> 根因在代码里摆着:`assets/scenes.py` 当时只有 3 个绘制器(hook / body / outro),
|
|
59
|
+
> quote / emphasis / calm 三种 kind 全部回落到 body;三个绘制器共用同一套"背景板 → 眉标 →
|
|
60
|
+
> 大字 → 副标 → 强调线 → HUD"骨架,8 套风格换完只剩配色不同。
|
|
61
|
+
> 用剪影判据量改造前的 HEAD 快照:8 套风格两两 28 对里 **4 对完全不达标**(同明暗族 12 对里
|
|
62
|
+
> 只过 8 对)——换风格真的只是换色,这不是审美口水。
|
|
63
|
+
>
|
|
64
|
+
> v0.9 的做法不是"再加几套风格",而是把"内容 → 构图"独立成一层,
|
|
65
|
+
> 再给每套风格补**结构签名**。三层正交:场景语法(选构图)→ 视觉语言包(怎么画)→
|
|
66
|
+
> 片内编排(同一部片里不复制粘贴)。
|
|
67
|
+
|
|
68
|
+
### 一、改了什么:三层正交
|
|
69
|
+
|
|
70
|
+
| 层 | 新增/改动 | 落点 |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| **① 场景语法** | 新模块 `scripts/grammar.py`(纯标准库,可单测、可被 `scenes.py` 反向 import)。按内容给 **10 类构图**打分选型:`hero` / `statement` / `list` / `stat` / `compare` / `process` / `quote` / `chapter` / `chart` / `outro`。规则:字段存在性 > 关键词 > 结构位置;段长门(每类有最短时长);连续同类型 ≤2 段;平手按固定顺序取位 | `grammar.SCENE_TYPES`(grammar.py:30)、`MIN_DUR`(:49)、`DOWNGRADE`(:63)、`plan_scenes` → `work/storyboard.json` |
|
|
73
|
+
| **② 视觉语言包** | `stylekit.VISUAL_LANGUAGES`:8 套风格 + legacy,每套在主题色之上补**五组结构签名**——`motion`(缓动/入场区间/镜头 push/呼吸频率)、`motif`(装饰母题:brackets / hairlines / handdrawn / slabs / minimal / letterbox / signal / rays)、`transition`(段界转场:dip / wash / paper / wipe / cut / iris)、`typography`(字距/行高/对齐/编号写法/字号比)、`bias`(整体重心偏移 px)。装饰母题**预烘焙**成一张全屏 RGBA 图层,逐帧 paste。当时注释写的是"paste 约 0.3 ms"——**这是估算不是实测**,0.9.1 实测为 5.6 ms/帧,随即改成烘焙进底版(见 0.9.1 段) | `stylekit.py:568`(`VISUAL_LANGUAGES`)、`:681`(`visual_lint`)、`scenes.py:888`(`_motif_layer`)、`scenes.py:1020`(`_plate`,v0.9.1)、`:1068`(`_apply_veil`) |
|
|
74
|
+
| **③ 片内编排** | 版式变体(每类型 3 个、相邻段强制不同)、装饰密度 3 档(0.55 / 0.75 / 1.0,每 3 段回落)、相位偏移(防同频"复印")。全部由 sha1 派生,**不读 random / time / hash()** | `grammar.variant_of / decor_of / phase_of`,写进 timeline 的 `scene_variant / scene_decor / scene_phase` |
|
|
75
|
+
|
|
76
|
+
配套改动:
|
|
77
|
+
|
|
78
|
+
- **`assets/scenes.py` 第三节重写**:3 个老绘制器 → **10 类构图绘制器**(`_DRAWERS`,
|
|
79
|
+
scenes.py:1979),每类独立的视觉重心、留白与持续动效;新增段内 veil 转场
|
|
80
|
+
(`_apply_veil`,只在段首 ≤0.45 s 内生效——相邻两段可能是完全不同的构图,整屏瞬切会
|
|
81
|
+
精确触发闪烁门禁)。
|
|
82
|
+
- **film.json 新增 7 个行级可选字段**:`type` / `quote` / `by` / `stats[]` / `series[]` /
|
|
83
|
+
`steps[]` / `sides{}`。全部可选;不写就从 `text` / `items` 推导(`grammar.derive_*`)。
|
|
84
|
+
`type` 与 `kind` **正交**:kind 管声线与配乐能量,type 只管构图。**没有新增 kind 值**
|
|
85
|
+
(会撞 voicekit 的语气 id 与 filmcheck 的 `KINDS`)。
|
|
86
|
+
- **`--stage layout` 打印分镜**:每段一行"id / kind → type / 变体 / 密度 / 为什么",
|
|
87
|
+
同时落 `work/storyboard.json`(审计产物:能看到每段为什么选这个构图
|
|
88
|
+
→ render.py:553)。
|
|
89
|
+
- **`--stage style` 打印视觉语言**:母题 / 转场 / 字距 / 编号写法 / 重心偏移各一行,
|
|
90
|
+
`visual_lint` 在同一个 stage 就拦坏配置(render.py:322)。
|
|
91
|
+
- **新工具 `tools/silhouette_qa.py`**:跨风格剪影可区分门禁 **G13**(见下"门禁与兼容")。
|
|
92
|
+
|
|
93
|
+
### 二、门禁与兼容
|
|
94
|
+
|
|
95
|
+
| 项 | 内容 |
|
|
96
|
+
|---|---|
|
|
97
|
+
| **legacy 逐字节不变** | 不写 `style` 字段 = 走 v0.4 三个老绘制器(`_LEGACY_DRAWERS`,scenes.py:232),timeline 不注入场景字段、不写 storyboard。selfcheck 第 26 条查 legacy 的配乐/旁白/节奏参数;**逐字节**另有实测:用 `git show HEAD` 取 v0.8.1 的 scenes/stylekit/filmkit,与当前树对同一份 legacy 剧本(4 句:hook/body/quote/outro,且故意塞入 `scene_type` 等新字段)各渲 4 帧比 sha256,**4/4 完全一致**(证据 `.team/legacy_byte_compare.json`,可复跑 `.team/legacy_evidence.py`)。注意金帧基线**不覆盖**这条——它渲的是 `style: auto` 的模板片,不走 legacy 路径 |
|
|
98
|
+
| **新判据 G13(剪影可区分)** | 同一份合成剧本只换 style,每个场景类型渲 3 帧(t=0.05/0.5/0.9×dur)→ 灰度 → 降采样 480×270 → 以四角亮度中位数为基准三值化 → 量五项:前景占比 F / 前景质心 (Cx,Cy) / 四边覆盖率 B / 左右对称度 S。两两五项里**至少一项达标**即算可区分(ΔF≥6pp、|ΔCx|≥8pp、|ΔCy|≥8pp、ΔB≥14pp、ΔS≥0.20),且同一指标必须在 3 帧上全部达标。判据写死在 `tools/silhouette_qa.py:125` |
|
|
99
|
+
| **G13 挂在哪** | 可选离线工具 + `selfcheck` 第 55 条(缺工具则 skip,不阻塞 CI);**不进 `--stage qa` 的账本**——它渲的是合成剧本,不是成片。口径见 `references/scene-grammar.md` 与 `references/style-packs.md` |
|
|
100
|
+
| **`visual_lint`** | 母题名 / 转场名 / 转场时长(0–0.60 s)/ 编号写法 / 字号比(1.0–3.6)/ 字距(0–8 px)/ 行高(1.15–1.55)/ 母题密度 / 入场区间 / push(0–0.16)越界,`--stage style` 直接 `SystemExit`,不等到渲完 300 帧 |
|
|
101
|
+
| **ci_check** | `LOCAL_MODULES` 加 `grammar`(第 5 项依赖白名单);`package.json` 的 `files` 加 `tools/silhouette_qa.py`(第 6 项打包卫生)。仍是 12 项 |
|
|
102
|
+
| **schema / filmcheck** | `lines[].type` 枚举 + 四个嵌套结构(stats / series / steps / sides)写进 `schemas/film.schema.json` 与 `filmcheck.py`。`type` 写错会被 filmcheck 报 **ERROR**;嵌套键拼错报 WARN("是不是想写 X") |
|
|
103
|
+
| **金帧基线** | 已重录(3 帧,人工看过帧再 `--write`,不是盲写)。`assets/golden_frames.json` 的 `env_fp` 与三个 sha256 同时更新 |
|
|
104
|
+
| **selfcheck** | 51 → **55** 条:52 场景语法(10 类分流/确定性/段长门/显式 type)、53 视觉语言包(8 套签名齐全且无重复)、54 场景类型单真值(4 处集合相等)、55 剪影可区分(G13) |
|
|
105
|
+
|
|
106
|
+
### 三、行为变化(升级前先看这几条)
|
|
107
|
+
|
|
108
|
+
| 变化 | v0.8.1 | v0.9.0 | 影响 |
|
|
109
|
+
|---|---|---|---|
|
|
110
|
+
| 画面骨架 | 8 套风格共用 3 个绘制器,换风格只换色 | 全新构图 + 结构签名;同一段内容可画成 10 类构图 | **升级后必须重看静帧**:`--stage stills` 的图会明显不同,这是本次的目的 |
|
|
111
|
+
| `work/golden_frames.json` 基线 | 3 帧 sha256(v0.8 值) | 已重录为 v0.9 值 | 自己复刻过金帧基线的项目要 `--write` 重录一次 |
|
|
112
|
+
| `lines[].type` 写错 | 字段不存在,filmcheck 报未知键 WARN | **ERROR**(枚举校验) | 以前"写了不生效"的脚本会当场失败——这是契约兑现 |
|
|
113
|
+
| 场景数据超容量 | 静默截断,无提示 | filmcheck 报 **`scene_capacity` WARN**:`stats` >3 / `series` >6 / `steps` >5 / `sides` 每侧 >3(绘制器只画前几条) | 有 WARN 不阻断,但那些条目**不会出现在画面上**,该拆段就拆段 |
|
|
114
|
+
| `--stage style` 输出 | 风格 / 主题 / 配乐 / 旁白 / 节奏 | 多一行"视觉语言: 母题=… 转场=… 字距=… 编号=… 重心=(+x,+y)" | grep 旧输出的脚本不受影响(只多不少) |
|
|
115
|
+
| `--stage layout` 输出 | 时间轴统计 | 多"分镜: N 段 / 类型×次数"与每段选型理由 | 同上 |
|
|
116
|
+
| 渲染速度 | 模板片 frames 约 75 fps(约 13 ms/帧) | **约 41–50 fps(约 20–24 ms/帧)**;0.9.1 优化后回到 **54–61 fps(约 19 ms/帧)** | 单帧预算 25 ms。如实说:**比 v0.8.1 慢**,慢在 10 类构图各自多了装饰与几何;换机必须重测 |
|
|
117
|
+
| `selfcheck` 条数 | 51 | **55** | `grep 'PASS 51'` 的脚本要改 |
|
|
118
|
+
| `ci_check` 项数 | 12 | 12(白名单扩展) | 本地模块白名单加 `grammar`;打包 `files` 加 `tools/silhouette_qa.py` |
|
|
119
|
+
|
|
120
|
+
### 四、已知限制(本版没做,写下来别装看不见)
|
|
121
|
+
|
|
122
|
+
- **web 引擎不跟随场景语法**:`--engine web` 的页面由用户自己写(`assets/web/film.js`),
|
|
123
|
+
本次不改造。web 路线的画风仍只有主题色,没有 10 类构图;剪影门禁也只覆盖 PIL 渲染器。
|
|
124
|
+
- **同一部片仍锁一个明暗族**:段界跨明暗族会整屏换底、精确触发闪烁门禁,观感也像换片。
|
|
125
|
+
主题覆盖(`scene["theme"]`)只允许同族。
|
|
126
|
+
- **`lines[].type` 写错只有 filmcheck 拦**:grammar 对非法值**静默回落**(当没写,按内容
|
|
127
|
+
自动选)。不跑 filmcheck 的流水线,写错就只是"没生效"。
|
|
128
|
+
- **场景类型有 4 份真值来源**(`filmcheck.SCENE_TYPES` / `grammar.SCENE_TYPES` /
|
|
129
|
+
`scenes._DRAWERS` / schema enum),靠 selfcheck 第 54 条断言"集合相等"兜底。
|
|
130
|
+
**顺序允许不同**:grammar 的那份顺序用于平手取位,另外三份只看成员。
|
|
131
|
+
- **版式变体只有 4 类绘制器读**:`variant_of` 对每段都算并写进 storyboard,
|
|
132
|
+
但当前只有 hero / statement / list / stat 消费它,其余六类构图唯一。
|
|
133
|
+
"每类型 3 个变体"目前只在四类上成立。
|
|
134
|
+
- **部分视觉语言字段"已声明、已体检、但绘制器没读"**:`motion.enter`、`motion.push`、
|
|
135
|
+
`typography.align`、`typography.ratio`、`layout_cycle`——写了不报错,也不改变画面。
|
|
136
|
+
详见 `references/style-packs.md`。
|
|
137
|
+
- **`work/storyboard.json` 是审计产物,不是输入**:改它不改变渲染结果;要固定构图请写
|
|
138
|
+
`film.json` 的 `lines[].type`。
|
|
139
|
+
|
|
140
|
+
### 五、验证数据(本机 Windows 11 / Python 3.12 / ffmpeg 9.0.2;换机请重测)
|
|
141
|
+
|
|
142
|
+
| 项 | 实测 |
|
|
143
|
+
|---|---|
|
|
144
|
+
| 场景语法自检 | `selfcheck` 第 52 条:10 段稿子分出 ≥5 种构图、同一稿两次选型与变体一致、2 秒段里的 chart 被降级且理由写明、显式 `type=hero` 生效 |
|
|
145
|
+
| 视觉语言自检 | 第 53 条:8 套风格签名齐全、`visual_lint_all` 全过、无重复签名(母题/转场/重心三元组不撞) |
|
|
146
|
+
| 单真值自检 | 第 54 条:grammar / filmcheck / `scenes._DRAWERS` / schema enum 四处集合一致 |
|
|
147
|
+
| **剪影 G13(改造后)** | **28 对全部通过**(同明暗族 **12/12**,跨族 16/16);同族对靠 Cx/Cy/S 等结构指标通过,不是靠明暗差 |
|
|
148
|
+
| **剪影 G13(改造前基线,同一工具跑 HEAD 快照)** | 28 对通过 **24**、失败 **4**(`vivid×epic` / `cinema×epic` / `paper×lo-fi` / `vivid×cinema`);同明暗族只过 **8/12**。这 4 对就是"换风格=换色"的直接证据 |
|
|
149
|
+
| 模板片渲染 | 0.9.0 落地时 frames 阶段约 **41–50 fps(约 20–24 ms/帧)**;0.9.1 把装饰烘焙进底版后为 **54–61 fps(约 19 ms/帧)**,v0.8.1 约 **75 fps(约 13 ms/帧)**。见 0.9.1 段 |
|
|
150
|
+
| 金帧 | 3 帧(36 / 270 / 369)重录后与当前渲染像素逐位一致;legacy 路径仍走基线 |
|
|
151
|
+
| 自检 / 仓库体检 | `selfcheck` **PASS 55 / FAIL 0 / SKIP 0**;`ci_check` **PASS 12 / FAIL 0**;`filmcheck` 模板片 0 error / 0 warning |
|
|
152
|
+
|
|
153
|
+
### 六、升级须知(v0.8.1 → v0.9.0)
|
|
154
|
+
|
|
155
|
+
1. **画面一定会变**。这是本次的目的,不是回归。升级后先跑
|
|
156
|
+
`--stage stills --stills "l01:3,l02:5,l03:2.5"` 亲眼看静帧,再决定要不要调 `lines[].type`。
|
|
157
|
+
2. **想要稳定的观感,写显式 `style`**(不要 `"auto"`):`auto` 会按内容换风格,
|
|
158
|
+
而不同风格现在连骨架都不同;锁定 id 才能保证"这一版和上一版看起来是同一部片"。
|
|
159
|
+
3. **想沿用老画面**:`film.json` 不写 `style` 字段即可回到 v0.4 三个老绘制器(逐字节不变),
|
|
160
|
+
代价是同时失去 v0.5 的配乐/旁白风格包。
|
|
161
|
+
4. **跑一遍 `filmcheck`**:`lines[].type` 拼错会变成 ERROR,`stats/series/steps/sides`
|
|
162
|
+
超容量会给 `scene_capacity` WARN——这两类以前都不会报。
|
|
163
|
+
5. **金帧基线变了**:自己维护过基线快照的,要按当前渲染重新 `--write`(先人工看帧)。
|
|
164
|
+
6. **新增模块要一起拷**:`scripts/grammar.py`(纯标准库,缺了 `scenes.py` 会退到兼容构图
|
|
165
|
+
并打 WARN)。`tools/silhouette_qa.py` 只在仓库工具链里,不进技能目录。
|
|
166
|
+
|
|
9
167
|
## 0.8.1 — 全项目深审:修掉 60+ 处「看着没问题、其实没在查」(2026-11-10)
|
|
10
168
|
|
|
11
169
|
> 本轮没有新功能。起因是一次**全量复核**:把 14 个 Python 模块(约 3.4 万行)、5 个前端文件、
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @dsh-gis/dsh-video-studio-skill
|
|
2
2
|
|
|
3
|
-
 
|
|
4
4
|
|
|
5
5
|
**DeepSeek Harness 技能插件:用代码从零生成中文视频。**
|
|
6
6
|
|
|
@@ -48,16 +48,32 @@ ffmpeg 编码 → 采样级混音 → **四层质检**(容器 / 信号 / 时
|
|
|
48
48
|
> `tools/golden_frames.py`。**代价要说清**:29 s 模板片全链从约 28 s 涨到 **47.3 s**,其中 `qa` **23.9 s**
|
|
49
49
|
> 已经**超过渲染本身**(`frames` 12.5 s);`estimate` 预演也从 28.4 s 变成 **58.8–108.2 s**(vmaf 31–50 s 是瓶颈)。
|
|
50
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。
|
|
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
60
|
> 详见 [CHANGELOG.md](CHANGELOG.md) 的 0.8.1 段(含行为变化表与升级须知)。
|
|
61
|
+
> **v0.9.0(换风格不再只是换色)**:v0.5 的风格包只覆盖"皮肤"(配色/字体/纹理/字距/缓动),
|
|
62
|
+
> 8 套风格共用同样的构图骨架,用户反馈"每个视频都差不多,只是主题和颜色不同"。
|
|
63
|
+
> v0.9 把这条链路拆成三层:**场景语法**(按内容选 10 类构图:hero / statement / list / stat /
|
|
64
|
+
> compare / process / quote / chapter / chart / outro,落 `work/storyboard.json` 可审计)、
|
|
65
|
+
> **视觉语言包**(每套风格补五组结构签名:motion / motif / transition / typography / bias,
|
|
66
|
+
> 母题预烘焙并合成进背景底版,逐帧只 copy/EXTENT)、**片内编排**(版式变体 / 装饰密度 / 相位偏移,防"复印")。
|
|
67
|
+
> 新门禁 **G13 剪影可区分**(`tools/silhouette_qa.py`):8 套风格两两 **28 对全部通过**,
|
|
68
|
+
> 改造前同明暗族 12 对只过 8 对。**代价如实说**:模板片 frames 约 **19 ms/帧(54–61 fps)**,
|
|
69
|
+
> 仍在 25 ms 预算内,但比 v0.8.1 的约 13 ms/帧(约 75 fps)慢——慢在 10 类构图各自多了装饰与几何。
|
|
70
|
+
> 0.9.1 已经把装饰母题从"逐帧 paste(实测 5.6 ms)"改成"烘焙进背景底版(1.3–2.0 ms)",
|
|
71
|
+
> 这也是它比 0.9.0 首版快回来一截的原因。web 引擎本次不跟随场景语法;
|
|
72
|
+
> legacy(不写 `style`)仍逐字节不变。selfcheck 51 → **55 条**。
|
|
73
|
+
> **v0.9.1** 把"逐帧全屏贴装饰"(实测 5.6 ms/帧)改成"装饰烘焙进背景底版"(1.3–2.0 ms),
|
|
74
|
+
> 顺带让装饰跟着镜头缓推一起动(cinema / epic 的强 push 下不再穿帮)。
|
|
75
|
+
> 详见 [CHANGELOG.md](CHANGELOG.md) 的 0.9.0 / 0.9.1 段与
|
|
76
|
+
> [references/scene-grammar.md](skills/video-studio/references/scene-grammar.md)。
|
|
61
77
|
|
|
62
78
|
## 安装
|
|
63
79
|
|
|
@@ -101,12 +117,19 @@ TTS 实测时长、AAC 编码都会让真峰/响度/锐度浮动,**别 chasing
|
|
|
101
117
|
29.00 s / -16.5 LUFS / -1.4 dBTP / 锐度比 1.01(2026-11-10 另一台 Windows 机器复测)——
|
|
102
118
|
**不同机器、不同 TTS 结果,两组都对,别混着引用**。
|
|
103
119
|
|
|
104
|
-
## 效果:同一个模板,八种气质(v0.5)
|
|
120
|
+
## 效果:同一个模板,八种气质(v0.5 → v0.9)
|
|
105
121
|
|
|
106
|
-
|
|
122
|
+
同一份文字、同一个场景类型(`list`),只改 `"style"`。**v0.9 起不只是换色**:
|
|
123
|
+
每套风格有自己的装饰母题(括角 / 手绘框 / letterbox / 信号条 / 放射线…)、
|
|
124
|
+
字距与编号写法、段界转场、整体重心偏移,所以同一屏的骨架与留白也不同:
|
|
107
125
|
|
|
108
126
|
<p align="center"><img src="docs/styles/sheet-8-styles.png" width="100%" alt="8 套风格对比:科技深蓝 / 杂志暖白 / 手绘纸感 / 活力撞色 / 极简黑白 / 电影青橙 / 暖灰薄荷 / 深黑鎏金"></p>
|
|
109
127
|
|
|
128
|
+
> 这张图是 v0.9 用新代码重渲的(8 套风格 × 同一段内容),**换图不是换滤镜**:
|
|
129
|
+
> 标题锚点、装饰语言、编号写法、重心都在变。要看"这一段为什么画成这样",
|
|
130
|
+
> 跑 `--stage style` 会打印视觉语言(母题/转场/字距/编号/重心),
|
|
131
|
+
> 跑 `--stage layout` 会打印分镜(每段选哪类构图、为什么)并落 `work/storyboard.json`。
|
|
132
|
+
|
|
110
133
|
三份**不同题材**的短片(全流程真跑:TTS → 排轴 → 配乐 → 音效 → 混音 → 逐帧 → 编码 → 质检;数据见
|
|
111
134
|
`docs/styles/demo-results.json`,是 v0.5 时期的实测快照,片源脚本未随仓库分发,**不可直接复现**;
|
|
112
135
|
**别把这张表当成"现在跑出来就是这样"**——BPM/调性由内容指纹从风格梯度里选(v0.7 起指纹还参与配乐结构),
|
|
@@ -137,7 +160,7 @@ cp <SKILL_DIR>/scripts/*.py . # filmkit/stylekit/voice
|
|
|
137
160
|
# v0.8 还含 preflight/qaasr/qavmaf(可选:缺了对应门禁记 skipped)
|
|
138
161
|
cp -r <SKILL_DIR>/assets/web ./web # 只在走浏览器引擎时需要
|
|
139
162
|
|
|
140
|
-
python selfcheck.py #
|
|
163
|
+
python selfcheck.py # 55 条环境/回归断言(20 秒内,不联网)
|
|
141
164
|
python <REPO>/tools/estimate.py --script film.json # v0.6:开渲前先算耗时/磁盘/分块(仓库/包里的工具,
|
|
142
165
|
# 不在 skills/video-studio/ 内,quickstart 拷出来的目录没有它)
|
|
143
166
|
# v0.8:已含 preflight/vmaf/asr 三段;29 s 模板片
|
|
@@ -230,7 +253,7 @@ skills/video-studio/
|
|
|
230
253
|
scripts/preflight.py v0.8 渲染前资源预检(字形 / TTS 音频 / 字体 / web 入口页,门禁 G0)
|
|
231
254
|
scripts/qavmaf.py v0.8 全片 VMAF/SSIM(参考帧由场景函数实时重渲,门禁 G11)
|
|
232
255
|
scripts/qaasr.py v0.8 ASR 回读(成片音轨转文字对账,门禁 G12)
|
|
233
|
-
scripts/selfcheck.py 回归自检(
|
|
256
|
+
scripts/selfcheck.py 回归自检(55 条"曾真的坏过"的断言)
|
|
234
257
|
scripts/sfxkit.py 物理建模音效库(24 配方,scipy 可选)
|
|
235
258
|
scripts/scorekit.py 程序化配乐(和弦表 / 分段能量 / 吸气)
|
|
236
259
|
scripts/webengine.py 浏览器逐帧渲染(CDP 截图、分块并行、崩溃重开、cue 导出、文字质检)
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-gis/dsh-video-studio-skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Video Studio skill plugin for DeepSeek Harness: style-pack driven code-generated Chinese videos — one style id decides palette/typography/music style/voice persona/pacing, measured TTS timeline with word-level boundaries, deterministic PIL/browser rendering (16:9 landscape, 720p/1080p), programmatic SFX and score, cue-driven sound sync, ffmpeg encoding, sample-level mixing, batch production and multi-layer QA gates (preflight, full-film VMAF/SSIM, ASR readback).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"!skills/**/__pycache__",
|
|
30
30
|
"!skills/**/*.pyc",
|
|
31
31
|
"docs/styles/sheet-8-styles.png",
|
|
32
|
+
"docs/styles/sheet-before-after.png",
|
|
32
33
|
"docs/styles/sheet-ai.png",
|
|
33
34
|
"docs/styles/sheet-craft.png",
|
|
34
35
|
"docs/styles/sheet-night.png",
|
|
@@ -38,7 +39,8 @@
|
|
|
38
39
|
"tools/ci_check.py",
|
|
39
40
|
"tools/audio_similarity.py",
|
|
40
41
|
"tools/selftest_noscipy.py",
|
|
41
|
-
"tools/golden_frames.py"
|
|
42
|
+
"tools/golden_frames.py",
|
|
43
|
+
"tools/silhouette_qa.py"
|
|
42
44
|
],
|
|
43
45
|
"publishConfig": {
|
|
44
46
|
"access": "public"
|
package/schemas/film.schema.json
CHANGED
|
@@ -239,6 +239,173 @@
|
|
|
239
239
|
"voice": {
|
|
240
240
|
"type": "string",
|
|
241
241
|
"description": "显式 edge-tts voice id(覆盖 persona 底子)"
|
|
242
|
+
},
|
|
243
|
+
"type": {
|
|
244
|
+
"type": "string",
|
|
245
|
+
"enum": [
|
|
246
|
+
"hero",
|
|
247
|
+
"statement",
|
|
248
|
+
"list",
|
|
249
|
+
"stat",
|
|
250
|
+
"compare",
|
|
251
|
+
"process",
|
|
252
|
+
"quote",
|
|
253
|
+
"chapter",
|
|
254
|
+
"chart",
|
|
255
|
+
"outro"
|
|
256
|
+
],
|
|
257
|
+
"description": "视觉场景类型(v0.9,可选):决定这段画面长成什么构图——hero 封面 / statement 金句 / list 要点列表 / stat 数字卡 / compare 左右对比 / process 流程轴 / quote 引语 / chapter 章节卡 / chart 数据条 / outro 收尾。与 kind **正交**:kind 管声线、语气、配乐能量,type 只管构图,所以没有新增 kind 值;不写 = 由 grammar.py 按内容自动推导(写错值 filmcheck.py 会报 error)。枚举真值来自 grammar.SCENE_TYPES 与 assets/scenes.py 的 _DRAWERS 键,改那边要同步这里"
|
|
258
|
+
},
|
|
259
|
+
"quote": {
|
|
260
|
+
"type": "string",
|
|
261
|
+
"description": "引语原文(type=quote 时用):打在屏幕上的引文。它和 text 是两件事——text 是 TTS 念的那句,quote 是画面上那句话本身"
|
|
262
|
+
},
|
|
263
|
+
"by": {
|
|
264
|
+
"type": "string",
|
|
265
|
+
"description": "引语出处/作者(type=quote 时用),如“—— 某本书 · 某作者”;与 quote 配套,缺省不画署名"
|
|
266
|
+
},
|
|
267
|
+
"stats": {
|
|
268
|
+
"type": "array",
|
|
269
|
+
"description": "数字卡原料(type=stat):每项 {value, unit, label, note}。value 必填(数字或字符串,字符串用于“>3x”“1/2”这类写法);unit 是单位后缀,label 是指标名,note 是小字补充",
|
|
270
|
+
"items": {
|
|
271
|
+
"type": "object",
|
|
272
|
+
"required": [
|
|
273
|
+
"value"
|
|
274
|
+
],
|
|
275
|
+
"additionalProperties": true,
|
|
276
|
+
"properties": {
|
|
277
|
+
"value": {
|
|
278
|
+
"type": [
|
|
279
|
+
"number",
|
|
280
|
+
"string"
|
|
281
|
+
],
|
|
282
|
+
"description": "数字主体(必填):数字,或“>3x”“1/2”这类字符串写法"
|
|
283
|
+
},
|
|
284
|
+
"unit": {
|
|
285
|
+
"type": "string",
|
|
286
|
+
"description": "单位/后缀,如“秒”“%”“fps”"
|
|
287
|
+
},
|
|
288
|
+
"label": {
|
|
289
|
+
"type": "string",
|
|
290
|
+
"description": "指标名,如“帧率”"
|
|
291
|
+
},
|
|
292
|
+
"note": {
|
|
293
|
+
"type": "string",
|
|
294
|
+
"description": "补充说明(小字),可省略"
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
"series": {
|
|
300
|
+
"type": "array",
|
|
301
|
+
"description": "数据条原料(type=chart):每项 {label, value, unit}。label 是条形名(必填),value 是条长(必填,数字或数值字符串)",
|
|
302
|
+
"items": {
|
|
303
|
+
"type": "object",
|
|
304
|
+
"required": [
|
|
305
|
+
"label",
|
|
306
|
+
"value"
|
|
307
|
+
],
|
|
308
|
+
"additionalProperties": true,
|
|
309
|
+
"properties": {
|
|
310
|
+
"label": {
|
|
311
|
+
"type": "string",
|
|
312
|
+
"description": "条形名(必填)"
|
|
313
|
+
},
|
|
314
|
+
"value": {
|
|
315
|
+
"type": [
|
|
316
|
+
"number",
|
|
317
|
+
"string"
|
|
318
|
+
],
|
|
319
|
+
"description": "条长(必填):数字或数值字符串(“0.8”“80%”由绘制器解析)"
|
|
320
|
+
},
|
|
321
|
+
"unit": {
|
|
322
|
+
"type": "string",
|
|
323
|
+
"description": "单位/后缀,如“GB”“%”"
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
"steps": {
|
|
329
|
+
"type": "array",
|
|
330
|
+
"description": "流程轴原料(type=process):每项 {label, note},数组顺序即节点顺序",
|
|
331
|
+
"items": {
|
|
332
|
+
"type": "object",
|
|
333
|
+
"required": [
|
|
334
|
+
"label"
|
|
335
|
+
],
|
|
336
|
+
"additionalProperties": true,
|
|
337
|
+
"properties": {
|
|
338
|
+
"label": {
|
|
339
|
+
"type": "string",
|
|
340
|
+
"description": "节点名(必填)"
|
|
341
|
+
},
|
|
342
|
+
"note": {
|
|
343
|
+
"type": "string",
|
|
344
|
+
"description": "节点补充说明(小字),可省略"
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
"sides": {
|
|
350
|
+
"type": "object",
|
|
351
|
+
"additionalProperties": true,
|
|
352
|
+
"description": "左右对比原料(type=compare):{left, right},每侧 {head, items[]};items 里每项可写字符串,也可写对象 {text}(两种都认:短条目直接写字符串更省事)",
|
|
353
|
+
"properties": {
|
|
354
|
+
"left": {
|
|
355
|
+
"type": "object",
|
|
356
|
+
"additionalProperties": true,
|
|
357
|
+
"description": "左侧",
|
|
358
|
+
"properties": {
|
|
359
|
+
"head": {
|
|
360
|
+
"type": "string",
|
|
361
|
+
"description": "左侧小标题"
|
|
362
|
+
},
|
|
363
|
+
"items": {
|
|
364
|
+
"type": "array",
|
|
365
|
+
"description": "左侧条目:字符串或对象 {text} 两种写法都行",
|
|
366
|
+
"items": {
|
|
367
|
+
"type": [
|
|
368
|
+
"string",
|
|
369
|
+
"object"
|
|
370
|
+
],
|
|
371
|
+
"properties": {
|
|
372
|
+
"text": {
|
|
373
|
+
"type": "string",
|
|
374
|
+
"description": "条目文字(写对象时用它;写字符串时字符串本身就是文字)"
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
"right": {
|
|
382
|
+
"type": "object",
|
|
383
|
+
"additionalProperties": true,
|
|
384
|
+
"description": "右侧",
|
|
385
|
+
"properties": {
|
|
386
|
+
"head": {
|
|
387
|
+
"type": "string",
|
|
388
|
+
"description": "右侧小标题"
|
|
389
|
+
},
|
|
390
|
+
"items": {
|
|
391
|
+
"type": "array",
|
|
392
|
+
"description": "右侧条目:字符串或对象 {text} 两种写法都行",
|
|
393
|
+
"items": {
|
|
394
|
+
"type": [
|
|
395
|
+
"string",
|
|
396
|
+
"object"
|
|
397
|
+
],
|
|
398
|
+
"properties": {
|
|
399
|
+
"text": {
|
|
400
|
+
"type": "string",
|
|
401
|
+
"description": "条目文字(写对象时用它;写字符串时字符串本身就是文字)"
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
242
409
|
}
|
|
243
410
|
}
|
|
244
411
|
}
|
|
@@ -48,15 +48,18 @@ cp <SKILL_DIR>/scripts/{sfxkit.py,scorekit.py,voicekit.py,qa_frames.py} .
|
|
|
48
48
|
cp <SKILL_DIR>/scripts/{preflight.py,qavmaf.py,qaasr.py} .
|
|
49
49
|
cp -r <SKILL_DIR>/assets/web ./web
|
|
50
50
|
|
|
51
|
-
# 2) 先跑一次自检:
|
|
51
|
+
# 2) 先跑一次自检:55 条回归护栏(v0.9 新增 52–55),20 秒内出结论(不联网;可选模块缺失会标 SKIP)
|
|
52
52
|
python selfcheck.py
|
|
53
53
|
|
|
54
54
|
# 3) 【v0.5 新步骤】先确认风格,再改文字
|
|
55
55
|
# film.json 的 "style": "auto" 会按内容自动选一套(画风+配乐+旁白一起变);
|
|
56
|
-
# 想锁定就写死风格 id。这条命令打印"为什么选这套"
|
|
56
|
+
# 想锁定就写死风格 id。这条命令打印"为什么选这套"与"视觉语言"(v0.9),并落盘 work/style.json。
|
|
57
57
|
python render.py --script film.json --stage style
|
|
58
58
|
|
|
59
59
|
# 3b) 改 film.json 的 lines[].text / sub / big / items
|
|
60
|
+
# v0.9:每段还能写 type(10 类构图之一)与 quote/by/stats/series/steps/sides;
|
|
61
|
+
# 不写就由 grammar 按内容选。排完轴看分镜:--stage layout 会打印"每段为什么是这个构图",
|
|
62
|
+
# 并落 work/storyboard.json(详见 <SKILL_DIR>/references/scene-grammar.md)。
|
|
60
63
|
# text = 朗读文本(自然口语);sub = 上屏字幕(短,一行优先)
|
|
61
64
|
|
|
62
65
|
# 4) 母版预览(P6):先只渲几张关键帧看构图/配色,别一上来渲全片
|
|
@@ -111,7 +114,7 @@ python render.py --script film.json --work work --stage accept --gate release
|
|
|
111
114
|
```bash
|
|
112
115
|
python render.py ... --stage style # 只解析风格 -> work/style.json(画风/配乐/旁白/节奏一次定死)
|
|
113
116
|
python render.py ... --stage tts # 只合成旁白 + 实测时长(带输入校验的缓存)
|
|
114
|
-
python render.py ... --stage layout # 只排时间轴 -> timeline.json / sub.srt / sub.ass(含 hold
|
|
117
|
+
python render.py ... --stage layout # 只排时间轴 -> timeline.json / sub.srt / sub.ass(含 hold 停留窗口;v0.9 还选构图、打印分镜、落 work/storyboard.json)
|
|
115
118
|
python render.py ... --stage cues # 只出提示点 -> work/cues.json(声音跟着画面走)
|
|
116
119
|
python render.py ... --stage score # 只出配乐 -> work/music.wav(scorekit)
|
|
117
120
|
python render.py ... --stage sfx # 只出音效轨 -> work/sfx.wav(sfxkit,按 cues.json)
|
|
@@ -375,6 +378,60 @@ python render.py ... --stage style # 用某份 film.json 解析风格并打印"
|
|
|
375
378
|
|
|
376
379
|
字段、指纹规则、加第 9 套风格的步骤见 **references/style-packs.md**。
|
|
377
380
|
|
|
381
|
+
### 5.5b 场景语法与视觉语言(v0.9):换风格不再只是换色
|
|
382
|
+
|
|
383
|
+
v0.5 解决了"画风/配乐/旁白一片一样",但只到**皮肤**层。骨架没变:当时 `assets/scenes.py`
|
|
384
|
+
只有 3 个绘制器(hook / body / outro),quote / emphasis / calm 全部回落到 body,
|
|
385
|
+
三个绘制器共用"背景板 → 眉标 → 大字 → 副标 → 强调线 → HUD"同一套结构。
|
|
386
|
+
于是 8 套风格换完,灰度量出来的构图骨架(前景占比/重心/边缘/对称)几乎不动——
|
|
387
|
+
用户说的"每个视频都差不多,只是主题和颜色不同"就是这么来的。
|
|
388
|
+
|
|
389
|
+
v0.9 把这件事拆成三层**正交**的:
|
|
390
|
+
|
|
391
|
+
| 层 | 决定什么 | 谁读它 | 产物 |
|
|
392
|
+
|---|---|---|---|
|
|
393
|
+
| 叙事 `kind` | 声线、语气、配乐能量 | voicekit / scorekit | 本版**没有新增 kind 值** |
|
|
394
|
+
| 场景 `type`(10 类构图) | 这段画面长什么样 | `assets/scenes.py` 的 10 个绘制器(`_DRAWERS`) | timeline 的 `scene_type`、`work/storyboard.json` |
|
|
395
|
+
| 视觉语言(风格 id) | 这套风格怎么画(母题/转场/字距/重心) | `stylekit.VISUAL_LANGUAGES` | `work/style.json` 的 `language` |
|
|
396
|
+
|
|
397
|
+
场景类型有 10 个:`hero` 封面 / `statement` 金句 / `list` 要点 / `stat` 数字卡 /
|
|
398
|
+
`compare` 左右对比 / `process` 流程轴 / `quote` 引语 / `chapter` 章节卡 /
|
|
399
|
+
`chart` 数据条 / `outro` 收尾。**不写就不管**——grammar 按内容自动选(字段存在性 >
|
|
400
|
+
关键词 > 结构位置,段长不足按固定表降级,连续同类型 ≤2 段);
|
|
401
|
+
要锁定就写行级 `lines[].type`。
|
|
402
|
+
|
|
403
|
+
看选型与环境:
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
python render.py --script film.json --scenes scenes.py --work work --stage layout
|
|
407
|
+
# 分镜: 4 段 / 封面×1 要点列表×2 收尾×1
|
|
408
|
+
# l01 hook -> hero v0 d0 首段/开场
|
|
409
|
+
# l02 body -> list v0 d2 items>=3
|
|
410
|
+
# ...
|
|
411
|
+
# 同时落 work/storyboard.json:每段的 type / 变体 / 装饰密度 / 理由,可审计
|
|
412
|
+
|
|
413
|
+
python render.py --script film.json --stage style
|
|
414
|
+
# 视觉语言: 母题=brackets 转场=dip(0.28s) 字距=0.0 编号=dim 重心=(+0,+0)
|
|
415
|
+
# (坏配置在这里就拦,不等渲完 300 帧)
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**legacy 边界(必须记住)**:不写 `style` 字段 = 走 v0.4 三个老绘制器,逐字节不变,
|
|
419
|
+
timeline 里不会出现场景字段。想要新构图,写 `"style": "auto"` 或任意风格 id。
|
|
420
|
+
|
|
421
|
+
**三条代价与边界**:
|
|
422
|
+
|
|
423
|
+
1. **比 v0.8.1 慢,但仍在预算内**:模板片 frames 约 **19 ms/帧(54–61 fps)**,预算 25 ms;
|
|
424
|
+
v0.8.1 约 13 ms/帧(约 75 fps)。慢在 10 类构图各自多了装饰与几何。
|
|
425
|
+
0.9.0 首版还要慢一截(约 20–24 ms/帧),0.9.1 把装饰母题从"逐帧 paste(实测 5.6 ms)"
|
|
426
|
+
改成"烘焙进背景底版(1.3–2.0 ms)"才回到现在这个数。换机必须重测。
|
|
427
|
+
2. **同一部片仍锁一个明暗族**:段界跨族会整屏换底、触发闪烁门禁,也像换片。
|
|
428
|
+
3. **web 引擎不跟随**:`--engine web` 的页面由你自己写,本次没有 10 类构图,
|
|
429
|
+
画风仍只有主题色。
|
|
430
|
+
|
|
431
|
+
选型规则、`storyboard.json` 字段、加第 11 类构图的步骤、常见误用,见
|
|
432
|
+
[scene-grammar.md](references/scene-grammar.md);五组视觉语言签名与加第 9 套风格要补什么,
|
|
433
|
+
见 [style-packs.md](references/style-packs.md)。
|
|
434
|
+
|
|
378
435
|
### 5.6 混音链(照着做,别自创)
|
|
379
436
|
|
|
380
437
|
```
|
|
@@ -507,7 +564,7 @@ python <REPO>/tools/audio_similarity.py --strict # A/B/C 三组阈值,失败
|
|
|
507
564
|
|
|
508
565
|
```bash
|
|
509
566
|
python render.py ... --stage qa # 只读质检:分辨率/音轨/时长/响度/真峰/锐度比/黑帧/字幕条数 + 帧级深检
|
|
510
|
-
python selfcheck.py # 技能自身回归(
|
|
567
|
+
python selfcheck.py # 技能自身回归(55 条曾真的坏过的点)
|
|
511
568
|
python qa_frames.py out/film.mp4 --cues work/cues.json # 单独跑帧级深检,出 JSON + 图
|
|
512
569
|
# v0.6:qa / all 收尾会自动写 out/QC-REPORT.md(机器可读交付结论)
|
|
513
570
|
# 并落 work/gates.json(三档 gate matrix)与 work/cost.jsonl(实测耗时台账)
|
|
@@ -838,7 +895,7 @@ python render.py ... --run-id hero-v3 # 不给就按时间戳生成 rYYYYMMD
|
|
|
838
895
|
| `scripts/gates.py` | **(v0.6)门禁账本**:pass / fail / skipped 三档、`out/QC-REPORT.md` 渲染、人工签核(绑内容指纹)、原子写 |
|
|
839
896
|
| `scripts/stagewatch.py` | **(v0.6)阶段新鲜度**:每 stage 记录输入/输出指纹到 `work/manifest.json`;上游一改,下游报过时并给出最小重跑命令 |
|
|
840
897
|
| `scripts/filmcheck.py` | **(v0.6)film.json 契约校验**:未知键提示"是不是想写 X"(以前静默忽略)、枚举与范围、跨字段(cue 引用的 id 必须存在) |
|
|
841
|
-
| `scripts/selfcheck.py` | 回归自检:**
|
|
898
|
+
| `scripts/selfcheck.py` | 回归自检:**55 条**"曾真的坏过"的断言,不联网 20 秒内出结论(可选模块缺失标 SKIP)。v0.8 新增 8 条:44 词级时间戳 / 45 画幅规划 / 46 金帧确定性 / 47 依赖漂移体检 / 48 批量清单解析 / 49 TTS 后端可替换 / 50 web 风格载荷(legacy 必须回落)/ 51 金帧回归(调 `tools/golden_frames.py`)。v0.9 新增 4 条:52 场景语法(10 类分流/确定性/段长门)/ 53 视觉语言包(8 套签名无重复)/ 54 场景类型单真值(4 处集合相等)/ 55 剪影可区分(调 `tools/silhouette_qa.py`) |
|
|
842
899
|
| `scripts/preflight.py` | **(v0.8)渲染前资源闸门**:剧本结构 + 全部上屏文本逐字过字形检测(按字段选字重)+ 已有 TTS 音频可解析 + 字体可加载 + web 入口页存在。`render.py` 在 `frames` 之前调用,记门禁 `G0`;也可单独跑 `python preflight.py --script film.json [--json] [--strict]` |
|
|
843
900
|
| `scripts/qavmaf.py` | **(v0.8)全片 VMAF/SSIM 门禁**:参考帧由场景函数**实时重渲**(不是成片抽帧),rawvideo 喂 ffmpeg 与成片逐帧比;一次调用同时算 VMAF 与 SSIM;门禁 `G11` |
|
|
844
901
|
| `scripts/qaasr.py` | **(v0.8)ASR 回读门禁**:成片音轨转文字与剧本对账(字符级多重集召回 + 每句偏移);引擎优先 faster-whisper,其次 ffmpeg whisper 滤镜,都不可用记 skipped;门禁 `G12` |
|
|
@@ -895,7 +952,7 @@ python render.py ... --run-id hero-v3 # 不给就按时间戳生成 rYYYYMMD
|
|
|
895
952
|
> 词级:4 句 / 64 词 / 末词偏差最大 0.09 s(G10)
|
|
896
953
|
> 画质:VMAF 97.22 / SSIM 0.9928 / 870 帧(G11,参考帧由场景函数重渲)
|
|
897
954
|
> 回读:字符召回 0.803(G12,faster-whisper small;中英混排专名会掉分,< 0.72 才 fail)
|
|
898
|
-
> 自检:selfcheck PASS
|
|
955
|
+
> 自检:selfcheck PASS 55 / FAIL 0 / SKIP 0;tools/ci_check.py PASS 12 / FAIL 0
|
|
899
956
|
> 音频:work/score.json 的 variation 非 0(指纹参与了结构变奏)、audio_similarity --strict 全 PASS
|
|
900
957
|
> 目检:work/qa/sheet.png,四帧分别为开场星射线、五步成片卡片、画质三件事卡片、收尾居中大字;
|
|
901
958
|
> 字幕黑底白字不压正文,大字边距均匀,无空洞帧。
|
|
@@ -969,11 +1026,11 @@ Pillow 路线: 墙钟秒数 ≈ 帧数 / 40 / 并行度 + 30% 余量
|
|
|
969
1026
|
| v0.6 → **v0.7** | 想吃到「配乐/音效随内容变化」就保持 `style: "auto"`,**不要**写死 `music.seed` 或关掉 `seed_from_content`;音效想更丰富就把提示点写进 `scenes.py` 的 `cues()` | CHANGELOG 0.7.0「升级须知(v0.6 → v0.7)」 |
|
|
970
1027
|
| v0.7 → **v0.7.1** | 配乐基线默认值从 `music.gain_db=-1.5` 变成 **-12**(模板也已改),有人声处再压配乐 6 dB / 音效 3 dB;**之前手调过 `gain_db`/`duck_db` 的片子要重新听一遍**(现在背景整体更低)。显式写 0 可关掉对应侧链 | CHANGELOG 0.7.1「修了什么」+ `assets/film.json` 的 `music` 默认值 |
|
|
971
1028
|
| v0.7.1 → **v0.7.2** | `QC-REPORT.md` 现在**只落在 `--out` 的目录**(以前 `accept` 分支按 `work` 的兄弟目录算,`--out deliver/film.mp4` 时签核会更新到另一份没人交付的文件)。如果你用 `--out` 指到了非 `out/` 的目录,交付时请看新位置;旧的 `out/QC-REPORT.md` 不会被再写 | `render._report_path()` 的 docstring + `selfcheck` 第 40 条(本轮新增) |
|
|
972
|
-
| v0.7.2 → **v0.8.0** | ① 新工作目录**多拷三个文件**:`scripts/preflight.py`、`scripts/qavmaf.py`、`scripts/qaasr.py`(都是**可选**:不拷对应门禁记 `skipped` 并写明原因,不会让渲染失败——但 `skipped != 通过`)。② **默认行为变了**:`film.json` 的 `words` 默认 **true**,老项目第一次跑 `--stage tts` 会**把每句重新联网合成一次**(老缓存没有词级记录);不想付这次网络成本就写 `"words": false`。③ **qa 变慢**:全片 VMAF 每片多渲一遍参考帧(29 s 片实测 14.2 s),ASR 8.7 s——全链从约 28 s 涨到 **47.3 s**,qa(23.9 s)已超过渲染本身(12.5 s)。④ **输出仍默认 1080p@30**:不写 `video` 块行为与 v0.7 完全一致。⑤ 自检 43 → **51** 条,三档门禁多了 `G0/G10/G11/G12` 四行 | CHANGELOG 0.8.0「升级须知(v0.7.2 -> v0.8.0)」+ 本节下方逐条说明 |
|
|
1029
|
+
| v0.7.2 → **v0.8.0** | ① 新工作目录**多拷三个文件**:`scripts/preflight.py`、`scripts/qavmaf.py`、`scripts/qaasr.py`(都是**可选**:不拷对应门禁记 `skipped` 并写明原因,不会让渲染失败——但 `skipped != 通过`)。② **默认行为变了**:`film.json` 的 `words` 默认 **true**,老项目第一次跑 `--stage tts` 会**把每句重新联网合成一次**(老缓存没有词级记录);不想付这次网络成本就写 `"words": false`。③ **qa 变慢**:全片 VMAF 每片多渲一遍参考帧(29 s 片实测 14.2 s),ASR 8.7 s——全链从约 28 s 涨到 **47.3 s**,qa(23.9 s)已超过渲染本身(12.5 s)。④ **输出仍默认 1080p@30**:不写 `video` 块行为与 v0.7 完全一致。⑤ 自检 43 → **51** 条,三档门禁多了 `G0/G10/G11/G12` 四行 | CHANGELOG 0.8.0「升级须知(v0.7.2 -> v0.8.0)」+ 本节下方逐条说明 |
|
|
973
1030
|
| v0.8.0 → **v0.8.1** | ① **删一次 `work/segments`**:`--resume` 的分块指纹新增 timeline 内容,旧计划会判"已变化"。② **退出码变严**:`--stage style/stills/frames/mux` 的门禁 fail(或 `--strict-gates` 下有 skipped)现在真的返回 1——靠退出码判定的交付脚本会开始"失败"。③ **`ci_check` 汇总变三档**:`PASS n / FAIL n / SKIP n`,用 `grep 'PASS 12'` 的脚本要改;要"没执行也算失败"加 `--strict`。④ **`filmcheck` 变严**:`video` 块走 `filmkit.video_plan`(1600x900 之类报 error),`qa.vmaf.enabled`/`qa.require_vmaf`/`qa.ssim.enabled` 三个惰性键报 WARN。⑤ **`webengine` 两处改成 fail-closed**:`style=None` + 720p 不再静默裁切、页面 FPS 与注入值不一致会报错。⑥ 金帧基线**不用重录**(像素逐位一致)。 | CHANGELOG 0.8.1「升级须知(v0.8.0 → v0.8.1)」+「行为变化」表 |
|
|
974
1031
|
|
|
975
1032
|
> 查当前版本:`python <REPO>/tools/ci_check.py -v` 里的 version 断言、或 `cat package.json` 的 `version`。
|
|
976
|
-
> 升级后建议按 §14 重跑一次自检(
|
|
1033
|
+
> 升级后建议按 §14 重跑一次自检(55 条),再按 §7 重新签核(改了代码/默认值,旧签核会自动失效,这是设计)。
|
|
977
1034
|
>
|
|
978
1035
|
> **v0.7.2 → v0.8.0 的具体迁移动作**(表里那一行的展开):
|
|
979
1036
|
> 1. 从 `<SKILL_DIR>/scripts/` 拷 `preflight.py` / `qavmaf.py` / `qaasr.py` 过来(不拷也能出片,只是三项门禁 `skipped`)。
|
|
@@ -1034,7 +1091,7 @@ Pillow 路线: 墙钟秒数 ≈ 帧数 / 40 / 并行度 + 30% 余量
|
|
|
1034
1091
|
|
|
1035
1092
|
```bash
|
|
1036
1093
|
cd <SKILL_DIR>/scripts
|
|
1037
|
-
python selfcheck.py #
|
|
1094
|
+
python selfcheck.py # 55 条断言;FAIL 就照提示修环境
|
|
1038
1095
|
python sfxkit.py --selftest # 音效库(可选模块,装了才跑)
|
|
1039
1096
|
python scorekit.py --selftest # 配乐
|
|
1040
1097
|
python webengine.py --selftest # 浏览器引擎(35 项,会真起无头浏览器,约 60 秒)
|