@dsh-gis/dsh-video-studio-skill 0.4.0 → 0.6.0
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/README.md +62 -12
- package/docs/styles/demo-results.json +76 -0
- package/docs/styles/sheet-8-styles.png +0 -0
- package/docs/styles/sheet-ai.png +0 -0
- package/docs/styles/sheet-craft.png +0 -0
- package/docs/styles/sheet-night.png +0 -0
- package/package.json +11 -3
- package/schemas/film.schema.json +528 -0
- package/skills/video-studio/SKILL.md +166 -14
- package/skills/video-studio/assets/film.json +84 -23
- package/skills/video-studio/assets/scenes.py +892 -34
- package/skills/video-studio/references/audio.md +29 -1
- package/skills/video-studio/references/change-impact.md +54 -0
- package/skills/video-studio/references/quality-gates.md +1 -1
- package/skills/video-studio/references/style-packs.md +178 -0
- package/skills/video-studio/requirements.txt +11 -0
- package/skills/video-studio/scripts/filmcheck.py +656 -0
- package/skills/video-studio/scripts/filmkit.py +682 -58
- package/skills/video-studio/scripts/gates.py +446 -0
- package/skills/video-studio/scripts/render.py +562 -34
- package/skills/video-studio/scripts/scorekit.py +1642 -25
- package/skills/video-studio/scripts/selfcheck.py +346 -0
- package/skills/video-studio/scripts/stagewatch.py +295 -0
- package/skills/video-studio/scripts/stylekit.py +924 -0
- package/skills/video-studio/scripts/voicekit.py +872 -0
- package/tools/ci_check.py +339 -0
- package/tools/estimate.py +578 -0
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/znlgis/dsh-video-studio-skill/schemas/film.schema.json",
|
|
4
|
+
"title": "video-studio film.json(剧本契约)",
|
|
5
|
+
"description": "video-studio 的剧本契约(唯一内容真源)。这是 JSON Schema draft-07 的**子集**:\n只用到 type / enum / required / properties / additionalProperties / items / minimum / maximum / pattern。\n\n为什么不写死 additionalProperties:false:draft-07 子集里没有 patternProperties,\n表达不了“下划线开头的扩展键豁免”这条规则,硬写 false 会把 _comment 这类注释键判死。\n所以未知键**不在 schema 层判死**,而是由 skills/video-studio/scripts/filmcheck.py 报 WARN\n(并给出“是不是想写 X”的建议)——schema 负责文档与 IDE 补全,filmcheck 负责执行。\n\n与 render.py 的 load_script() 的关系:load_script 是权威硬校验(title/lines 必填、lines 非空、\n每条有 text、id 不重复、bpm >0 或 auto)。本 schema 是它的补强(枚举/范围/嵌套键),不与之矛盾;\n两者都允许的脚本才能跑通。范围类约束以本文件为准,跨字段约束(cue 的 at 引用、hold 与 timeline\n对账)只有 filmcheck.py 能查。",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"title",
|
|
9
|
+
"lines"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"_comment": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "下划线开头的键是扩展位:schema 与 filmcheck 都不检查,渲染器也不读(模板用它写迁移说明)"
|
|
15
|
+
},
|
|
16
|
+
"title": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "片名(必填):顶栏常驻,也参与风格/配乐种子指纹"
|
|
19
|
+
},
|
|
20
|
+
"end_text": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "片尾结束字(模板写“完”);scenes.py 用来画收尾大字,可留空"
|
|
23
|
+
},
|
|
24
|
+
"style": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": [
|
|
27
|
+
"auto",
|
|
28
|
+
"tech-deep",
|
|
29
|
+
"magazine",
|
|
30
|
+
"paper",
|
|
31
|
+
"vivid",
|
|
32
|
+
"mono",
|
|
33
|
+
"cinema",
|
|
34
|
+
"lo-fi",
|
|
35
|
+
"epic"
|
|
36
|
+
],
|
|
37
|
+
"description": "风格包 id:一套决定画风+配乐+旁白+节奏。“auto”= 按内容自动选;不写这个键 = v0.4 legacy 行为(逐样本兼容)。枚举真值来自 stylekit.STYLES,新增风格时先改那边再改这里"
|
|
38
|
+
},
|
|
39
|
+
"engine": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"enum": [
|
|
42
|
+
"pil",
|
|
43
|
+
"web"
|
|
44
|
+
],
|
|
45
|
+
"description": "渲染引擎:pil = Pillow 逐帧(默认,40–80 fps);web = 无头浏览器逐帧(80–130 ms/帧,需要 playwright + assets/web/)"
|
|
46
|
+
},
|
|
47
|
+
"voice": {
|
|
48
|
+
"type": [
|
|
49
|
+
"string",
|
|
50
|
+
"object"
|
|
51
|
+
],
|
|
52
|
+
"description": "字符串 = edge-tts voice id(如 zh-CN-YunxiNeural,legacy 单声线路径);对象 = v0.5 声线策略(map 按 kind 映射 persona、auto、jitter、max_distinct、rate_range、cps_band),此时忽略 rate/pitch 的单值覆盖语义"
|
|
53
|
+
},
|
|
54
|
+
"rate": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"pattern": "^\\s*[+-]?\\d+\\s*%\\s*$",
|
|
57
|
+
"description": "语速,如 \"+6%\" / \"-2%\"(edge-tts 只接受整数);超过 +15% 会有机械感"
|
|
58
|
+
},
|
|
59
|
+
"pitch": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"pattern": "^\\s*[+-]?\\d+\\s*Hz\\s*$",
|
|
62
|
+
"description": "音高,如 \"+0Hz\" / \"-2Hz\""
|
|
63
|
+
},
|
|
64
|
+
"bpm": {
|
|
65
|
+
"type": [
|
|
66
|
+
"number",
|
|
67
|
+
"string"
|
|
68
|
+
],
|
|
69
|
+
"minimum": 0,
|
|
70
|
+
"description": "配乐 BPM:数字必须 > 0(这里是 ≥0 的宽松下限,0 与负数由 filmcheck 报 error);\"auto\" = 按风格 BPM 梯度 + 内容指纹决定。music.bpm 优先级更高"
|
|
71
|
+
},
|
|
72
|
+
"seed": {
|
|
73
|
+
"type": "integer",
|
|
74
|
+
"minimum": 0,
|
|
75
|
+
"description": "配乐/纹理种子(缺省 7);music.seed 优先"
|
|
76
|
+
},
|
|
77
|
+
"crf": {
|
|
78
|
+
"type": "integer",
|
|
79
|
+
"minimum": 1,
|
|
80
|
+
"maximum": 51,
|
|
81
|
+
"description": "x264 CRF:17 更锐利(体积约 +30%),18 是 filmkit 默认;范围 1–51"
|
|
82
|
+
},
|
|
83
|
+
"preset": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"enum": [
|
|
86
|
+
"ultrafast",
|
|
87
|
+
"superfast",
|
|
88
|
+
"veryfast",
|
|
89
|
+
"faster",
|
|
90
|
+
"fast",
|
|
91
|
+
"medium",
|
|
92
|
+
"slow",
|
|
93
|
+
"slower",
|
|
94
|
+
"veryslow"
|
|
95
|
+
],
|
|
96
|
+
"description": "x264 preset:medium 是实测基准(141 fps @crf17);slow 更小更慢,veryfast 只适合预览"
|
|
97
|
+
},
|
|
98
|
+
"lines": {
|
|
99
|
+
"type": "array",
|
|
100
|
+
"description": "台词数组(必填且非空):一句一个对象,顺序即播放顺序。id 缺省时 render.py 自动生成 l01、l02…;sfx.cues 的 at 用同一个 id 定位",
|
|
101
|
+
"items": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"required": [
|
|
104
|
+
"text"
|
|
105
|
+
],
|
|
106
|
+
"additionalProperties": true,
|
|
107
|
+
"properties": {
|
|
108
|
+
"id": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"pattern": "^[A-Za-z0-9_.-]+$",
|
|
111
|
+
"description": "场景 id(TTS 文件与 cue 都靠它定位)。缺省 = l%02d;一旦写 sfx.cues 就显式给 id"
|
|
112
|
+
},
|
|
113
|
+
"kind": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"enum": [
|
|
116
|
+
"hook",
|
|
117
|
+
"body",
|
|
118
|
+
"quote",
|
|
119
|
+
"outro",
|
|
120
|
+
"emphasis",
|
|
121
|
+
"calm"
|
|
122
|
+
],
|
|
123
|
+
"description": "段落类型:hook 开场 / body 正文 / quote 引用 / outro 收尾 / emphasis 强调 / calm 沉静。决定声线、语气、版式与配乐能量"
|
|
124
|
+
},
|
|
125
|
+
"text": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"description": "朗读文本(必填,不能为空):自然口语,TTS 念这一句"
|
|
128
|
+
},
|
|
129
|
+
"sub": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"description": "上屏字幕:短、一行优先(约 ≤24 个中文字);缺省沿用 text"
|
|
132
|
+
},
|
|
133
|
+
"big": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"description": "画面大字(标题/金句)"
|
|
136
|
+
},
|
|
137
|
+
"subtitle": {
|
|
138
|
+
"type": "string",
|
|
139
|
+
"description": "副标题(版式可用的第二行小字,可选)"
|
|
140
|
+
},
|
|
141
|
+
"chapter": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"description": "章节标签,如 \"02 · 怎么做到的\";同一章节内轮换版式,不会每句都跳"
|
|
144
|
+
},
|
|
145
|
+
"kicker": {
|
|
146
|
+
"type": "string",
|
|
147
|
+
"description": "小标签(如 \"PIPELINE\"),版式里的英文眉标"
|
|
148
|
+
},
|
|
149
|
+
"items": {
|
|
150
|
+
"type": "array",
|
|
151
|
+
"description": "要点列表(版式画成勾选卡片);items.py 只读 text/ok",
|
|
152
|
+
"items": {
|
|
153
|
+
"type": "object",
|
|
154
|
+
"required": [
|
|
155
|
+
"text"
|
|
156
|
+
],
|
|
157
|
+
"additionalProperties": true,
|
|
158
|
+
"properties": {
|
|
159
|
+
"text": {
|
|
160
|
+
"type": "string",
|
|
161
|
+
"description": "要点文字"
|
|
162
|
+
},
|
|
163
|
+
"ok": {
|
|
164
|
+
"type": "boolean",
|
|
165
|
+
"description": "true = 勾(绿色),false = 叉(红色)"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"hold": {
|
|
171
|
+
"type": "number",
|
|
172
|
+
"minimum": 0,
|
|
173
|
+
"description": "语音结束后额外停留秒数(让观众看清);缺省用全局 hold / 风格 pacing"
|
|
174
|
+
},
|
|
175
|
+
"lead": {
|
|
176
|
+
"type": "number",
|
|
177
|
+
"minimum": 0,
|
|
178
|
+
"description": "句前留白秒数;覆盖全局 lead 与 voice_plan 的逐句 lead"
|
|
179
|
+
},
|
|
180
|
+
"tail": {
|
|
181
|
+
"type": "number",
|
|
182
|
+
"minimum": 0,
|
|
183
|
+
"description": "句后留白秒数(一般通过 tail_map / voice_plan 控制,这里少见)"
|
|
184
|
+
},
|
|
185
|
+
"persona": {
|
|
186
|
+
"type": "string",
|
|
187
|
+
"description": "显式声线 persona(voicekit.PERSONA_IDS:narrator_male / narrator_female / warm_female / bright_female / authority_male / young_male / teen_male / dialect_ne_female / dialect_sx_female)"
|
|
188
|
+
},
|
|
189
|
+
"tone": {
|
|
190
|
+
"type": "string",
|
|
191
|
+
"enum": [
|
|
192
|
+
"body",
|
|
193
|
+
"hook",
|
|
194
|
+
"quote",
|
|
195
|
+
"outro",
|
|
196
|
+
"emphasis",
|
|
197
|
+
"calm"
|
|
198
|
+
],
|
|
199
|
+
"description": "显式语气(voicekit.VOICE_TONES 的键):覆盖 kind 规则"
|
|
200
|
+
},
|
|
201
|
+
"voice": {
|
|
202
|
+
"type": "string",
|
|
203
|
+
"description": "显式 edge-tts voice id(覆盖 persona 底子)"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"lead": {
|
|
209
|
+
"type": "number",
|
|
210
|
+
"minimum": 0,
|
|
211
|
+
"description": "全局句前留白(秒)。缺省取风格 pacing(v0.5 body 基准 0.62)"
|
|
212
|
+
},
|
|
213
|
+
"tail": {
|
|
214
|
+
"type": "number",
|
|
215
|
+
"minimum": 0,
|
|
216
|
+
"description": "全局句后留白(秒)。缺省取风格 pacing(v0.5 body 基准 0.92)"
|
|
217
|
+
},
|
|
218
|
+
"min_dur": {
|
|
219
|
+
"type": "number",
|
|
220
|
+
"minimum": 0,
|
|
221
|
+
"description": "每段最短时长(秒):语音太短时把画面撑住,缺省 3.0–4.0(按风格)"
|
|
222
|
+
},
|
|
223
|
+
"hold": {
|
|
224
|
+
"type": "number",
|
|
225
|
+
"minimum": 0,
|
|
226
|
+
"description": "全局停留秒数(语音结束后的额外停留),逐句 hold 优先"
|
|
227
|
+
},
|
|
228
|
+
"max_dur": {
|
|
229
|
+
"type": "number",
|
|
230
|
+
"minimum": 0,
|
|
231
|
+
"description": "每段最长时长(秒):超过就截断(会截断旁白,慎用)"
|
|
232
|
+
},
|
|
233
|
+
"bar": {
|
|
234
|
+
"type": "number",
|
|
235
|
+
"minimum": 0,
|
|
236
|
+
"description": "按小节对齐(秒):>0 时每段时长向上取整到整数倍。注意 render.py 目前未传这个值给 build_timeline(保留字段)"
|
|
237
|
+
},
|
|
238
|
+
"sub_max_hold": {
|
|
239
|
+
"type": [
|
|
240
|
+
"number",
|
|
241
|
+
"null"
|
|
242
|
+
],
|
|
243
|
+
"description": "字幕最长停留秒数(null = 覆盖整句);拍的是“字幕跟读完”,不是“画面慢放”"
|
|
244
|
+
},
|
|
245
|
+
"trim_silence": {
|
|
246
|
+
"type": "boolean",
|
|
247
|
+
"description": "TTS 后是否裁掉首尾静音(默认 true;要保留 edge-tts 尾部 ~0.95 s 静音就设 false)"
|
|
248
|
+
},
|
|
249
|
+
"trim_db": {
|
|
250
|
+
"type": "number",
|
|
251
|
+
"description": "裁静音的门限 dBFS(默认 -42.0);太激进会把气声裁掉"
|
|
252
|
+
},
|
|
253
|
+
"tts_workers": {
|
|
254
|
+
"type": "integer",
|
|
255
|
+
"minimum": 1,
|
|
256
|
+
"description": "TTS 并发句数(默认 4;edge-tts 免费端点别开太大)"
|
|
257
|
+
},
|
|
258
|
+
"chunk_frames": {
|
|
259
|
+
"type": "integer",
|
|
260
|
+
"minimum": 0,
|
|
261
|
+
"description": "分块渲染的块大小(帧);0 = 按 frames/jobs/4 自动算。写死它会同时进分块计划指纹"
|
|
262
|
+
},
|
|
263
|
+
"reencode_video": {
|
|
264
|
+
"type": "boolean",
|
|
265
|
+
"description": "mux 时是否重编码视频(默认 false = -c:v copy,只改封装与音频)"
|
|
266
|
+
},
|
|
267
|
+
"voice_gain": {
|
|
268
|
+
"type": "number",
|
|
269
|
+
"description": "旁白总增益(混音侧线性倍数,默认 1.0)"
|
|
270
|
+
},
|
|
271
|
+
"whoosh": {
|
|
272
|
+
"type": "boolean",
|
|
273
|
+
"description": "v0.2 兼容:没有 cues.json 时每段开头一声 whoosh(默认 true)"
|
|
274
|
+
},
|
|
275
|
+
"whoosh_amp": {
|
|
276
|
+
"type": "number",
|
|
277
|
+
"minimum": 0,
|
|
278
|
+
"description": "旧版 whoosh 的幅度(默认 0.055–0.06)"
|
|
279
|
+
},
|
|
280
|
+
"tail_map": {
|
|
281
|
+
"type": "object",
|
|
282
|
+
"description": "按 lines id 覆盖句后留白:{\"l03\": 1.4}(逐句微调用)"
|
|
283
|
+
},
|
|
284
|
+
"pacing": {
|
|
285
|
+
"type": "object",
|
|
286
|
+
"additionalProperties": true,
|
|
287
|
+
"description": "节奏覆盖(优先于 lead/tail/min_dur/hold 字段,也优先于风格 pacing)",
|
|
288
|
+
"properties": {
|
|
289
|
+
"lead": {
|
|
290
|
+
"type": "number",
|
|
291
|
+
"minimum": 0,
|
|
292
|
+
"description": "句前留白"
|
|
293
|
+
},
|
|
294
|
+
"tail": {
|
|
295
|
+
"type": "number",
|
|
296
|
+
"minimum": 0,
|
|
297
|
+
"description": "句后留白"
|
|
298
|
+
},
|
|
299
|
+
"min_dur": {
|
|
300
|
+
"type": "number",
|
|
301
|
+
"minimum": 0,
|
|
302
|
+
"description": "最短段长"
|
|
303
|
+
},
|
|
304
|
+
"hold": {
|
|
305
|
+
"type": "number",
|
|
306
|
+
"minimum": 0,
|
|
307
|
+
"description": "全局停留"
|
|
308
|
+
},
|
|
309
|
+
"item_stagger": {
|
|
310
|
+
"type": "number",
|
|
311
|
+
"minimum": 0,
|
|
312
|
+
"description": "要点条目的入场步长(秒)"
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"visual": {
|
|
317
|
+
"type": "object",
|
|
318
|
+
"additionalProperties": true,
|
|
319
|
+
"description": "视觉覆盖(v0.5):一般不用写,风格包已经决定;要锁主题/版式时才用",
|
|
320
|
+
"properties": {
|
|
321
|
+
"theme": {
|
|
322
|
+
"type": "string",
|
|
323
|
+
"description": "锁主题 id(等价于锁 style,主题与风格 1:1)"
|
|
324
|
+
},
|
|
325
|
+
"layout": {
|
|
326
|
+
"type": "string",
|
|
327
|
+
"description": "锁版式名(stylekit.LAYOUTS 的键,如 left-stack / center-stack / split-right)"
|
|
328
|
+
},
|
|
329
|
+
"theme_overrides": {
|
|
330
|
+
"type": "object",
|
|
331
|
+
"description": "主题字段覆盖:{\"accent\": \"#ff8a3d\"}(只接受主题里已存在的键)"
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
"music": {
|
|
336
|
+
"type": "object",
|
|
337
|
+
"additionalProperties": true,
|
|
338
|
+
"description": "配乐:scorekit 程序化生成 / v0.2 和弦床 / 外部 wav / 关掉。不写 mode 时走 v0.2 兼容链(有 bpm 就生成,没有就沿用)",
|
|
339
|
+
"properties": {
|
|
340
|
+
"enabled": {
|
|
341
|
+
"type": "boolean",
|
|
342
|
+
"description": "false = 本片不要配乐(等价于 mode=off)"
|
|
343
|
+
},
|
|
344
|
+
"mode": {
|
|
345
|
+
"type": "string",
|
|
346
|
+
"enum": [
|
|
347
|
+
"score",
|
|
348
|
+
"bed",
|
|
349
|
+
"file",
|
|
350
|
+
"off"
|
|
351
|
+
],
|
|
352
|
+
"description": "score = scorekit 程序化配乐;bed = v0.2 和弦床;file = 用外部 work/music.wav;off = 不要配乐(不读也不删 music.wav)"
|
|
353
|
+
},
|
|
354
|
+
"style": {
|
|
355
|
+
"type": "string",
|
|
356
|
+
"description": "\"auto\" 或风格 id:配乐风格(缺省跟随全片 style)"
|
|
357
|
+
},
|
|
358
|
+
"mood": {
|
|
359
|
+
"type": "string",
|
|
360
|
+
"description": "\"auto\" 或情绪名(steady/reflective/hopeful/uplifting/calm/driving,按风格缺省)"
|
|
361
|
+
},
|
|
362
|
+
"bpm": {
|
|
363
|
+
"type": [
|
|
364
|
+
"number",
|
|
365
|
+
"string"
|
|
366
|
+
],
|
|
367
|
+
"minimum": 0,
|
|
368
|
+
"description": "配乐 BPM:数字必须 > 0;\"auto\" = 风格梯度 + 指纹。优先级高于顶层 bpm"
|
|
369
|
+
},
|
|
370
|
+
"key": {
|
|
371
|
+
"type": "string",
|
|
372
|
+
"description": "调性:\"auto\" 或 C/G/D/F/A/Bb/Dm/Am/Em/Cm;缺省按风格调池选"
|
|
373
|
+
},
|
|
374
|
+
"seed": {
|
|
375
|
+
"type": "integer",
|
|
376
|
+
"minimum": 0,
|
|
377
|
+
"description": "配乐种子(缺省 7);同一 seed 逐采样一致"
|
|
378
|
+
},
|
|
379
|
+
"seed_from_content": {
|
|
380
|
+
"type": "boolean",
|
|
381
|
+
"description": "种子是否掺入内容指纹(默认 true:改台词换 BPM/调性,不换细节音色)"
|
|
382
|
+
},
|
|
383
|
+
"gain_db": {
|
|
384
|
+
"type": "number",
|
|
385
|
+
"description": "配乐总线增益 dB(默认 -1.5,混音前)"
|
|
386
|
+
},
|
|
387
|
+
"duck_db": {
|
|
388
|
+
"type": "number",
|
|
389
|
+
"description": "音效响起时配乐让位深度 dB(默认按风格 2.0–4.5)"
|
|
390
|
+
},
|
|
391
|
+
"seg": {
|
|
392
|
+
"type": "number",
|
|
393
|
+
"minimum": 0,
|
|
394
|
+
"description": "v0.2 和弦床的段长秒数(默认 4.0)"
|
|
395
|
+
},
|
|
396
|
+
"amp": {
|
|
397
|
+
"type": "number",
|
|
398
|
+
"minimum": 0,
|
|
399
|
+
"description": "v0.2 和弦床幅度(默认 0.055)"
|
|
400
|
+
},
|
|
401
|
+
"gain": {
|
|
402
|
+
"type": "number",
|
|
403
|
+
"minimum": 0,
|
|
404
|
+
"description": "v0.2 和弦床增益(默认 0.9)"
|
|
405
|
+
},
|
|
406
|
+
"xfade": {
|
|
407
|
+
"type": "number",
|
|
408
|
+
"minimum": 0,
|
|
409
|
+
"description": "v0.2 和弦床交叉淡化秒数(默认 1.2)"
|
|
410
|
+
},
|
|
411
|
+
"chords": {
|
|
412
|
+
"type": "array",
|
|
413
|
+
"description": "v0.2 兼容:和弦频率表 [[220, 261.63, 329.63], ...];只有 mode=bed/兼容链用得到",
|
|
414
|
+
"items": {
|
|
415
|
+
"type": "array",
|
|
416
|
+
"items": {
|
|
417
|
+
"type": "number"
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
"sections": {
|
|
422
|
+
"type": "array",
|
|
423
|
+
"description": "手工分段:每项 {id, at 或 start, end, energy, chords, layers…};at 可写 \"l03\" 让分段跟着场景走",
|
|
424
|
+
"items": {
|
|
425
|
+
"type": "object",
|
|
426
|
+
"additionalProperties": true
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
"sfx": {
|
|
432
|
+
"type": "object",
|
|
433
|
+
"additionalProperties": true,
|
|
434
|
+
"description": "音效:按 cues 在绝对时刻落位(画面提示点驱动声音,不靠“对齐猜”)",
|
|
435
|
+
"properties": {
|
|
436
|
+
"enabled": {
|
|
437
|
+
"type": "boolean",
|
|
438
|
+
"description": "false = 不登记 film.json 的 cues(scenes.py 的 cues() 钩子仍会跑)"
|
|
439
|
+
},
|
|
440
|
+
"gain_db": {
|
|
441
|
+
"type": "number",
|
|
442
|
+
"description": "音效总线增益 dB(默认 0)"
|
|
443
|
+
},
|
|
444
|
+
"mix_gain_db": {
|
|
445
|
+
"type": "number",
|
|
446
|
+
"description": "混音时音效总线额外增益 dB(默认 0)"
|
|
447
|
+
},
|
|
448
|
+
"cues": {
|
|
449
|
+
"type": "array",
|
|
450
|
+
"description": "提示点数组:每条 {at, type, dur, gain, ...};未知参数原样透传给 sfxkit 配方(size/pan/seed/pitch…)",
|
|
451
|
+
"items": {
|
|
452
|
+
"type": "object",
|
|
453
|
+
"required": [
|
|
454
|
+
"at",
|
|
455
|
+
"type"
|
|
456
|
+
],
|
|
457
|
+
"additionalProperties": true,
|
|
458
|
+
"properties": {
|
|
459
|
+
"at": {
|
|
460
|
+
"type": [
|
|
461
|
+
"number",
|
|
462
|
+
"string"
|
|
463
|
+
],
|
|
464
|
+
"description": "时刻:数字 = 绝对秒;\"abs:12.5\" = 绝对秒;\"l03\" = 场景起点;\"l03+0.35\" / \"l03-0.2\" = 相对场景 start 的偏移。用 id 写法时该 id 必须存在于 lines"
|
|
465
|
+
},
|
|
466
|
+
"type": {
|
|
467
|
+
"type": "string",
|
|
468
|
+
"description": "sfxkit 配方名或别名:whoosh / riser / impact / ui_blip / ui_click / data_chirp / typing / wind / rain / glitch / reverse_swell …(别名 blip→ui_blip、click→ui_click、chirp→data_chirp、wind→wind 等)"
|
|
469
|
+
},
|
|
470
|
+
"dur": {
|
|
471
|
+
"type": "number",
|
|
472
|
+
"minimum": 0,
|
|
473
|
+
"description": "时长秒数(不写用配方默认)"
|
|
474
|
+
},
|
|
475
|
+
"gain": {
|
|
476
|
+
"type": "number",
|
|
477
|
+
"description": "该条增益 dB"
|
|
478
|
+
},
|
|
479
|
+
"size": {
|
|
480
|
+
"type": "number",
|
|
481
|
+
"description": "impact 的体量参数(1 = 默认)"
|
|
482
|
+
},
|
|
483
|
+
"pan": {
|
|
484
|
+
"type": "number",
|
|
485
|
+
"description": "声像 -1(左)~ +1(右)"
|
|
486
|
+
},
|
|
487
|
+
"seed": {
|
|
488
|
+
"type": "integer",
|
|
489
|
+
"description": "该条随机种子(同 seed 逐采样一致)"
|
|
490
|
+
},
|
|
491
|
+
"visual_at": {
|
|
492
|
+
"type": [
|
|
493
|
+
"number",
|
|
494
|
+
"string"
|
|
495
|
+
],
|
|
496
|
+
"description": "可选锚点:画面上那个事件真正发生的秒数(数字或 \"abs:12.42\");qa_frames 用它查音画同步"
|
|
497
|
+
},
|
|
498
|
+
"visual_t": {
|
|
499
|
+
"type": [
|
|
500
|
+
"number",
|
|
501
|
+
"string"
|
|
502
|
+
],
|
|
503
|
+
"description": "visual_at 的兼容写法(qa_frames 两个都认)"
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
"web": {
|
|
511
|
+
"type": "object",
|
|
512
|
+
"additionalProperties": true,
|
|
513
|
+
"description": "浏览器引擎(engine=web)专用配置;走 PIL 时整块可删",
|
|
514
|
+
"properties": {
|
|
515
|
+
"entry": {
|
|
516
|
+
"type": "string",
|
|
517
|
+
"description": "入口 HTML 路径(相对 film.json 或绝对路径);缺省 = <项目>/web/index.html"
|
|
518
|
+
},
|
|
519
|
+
"chunk_s": {
|
|
520
|
+
"type": "number",
|
|
521
|
+
"minimum": 0,
|
|
522
|
+
"description": "页面分块秒数(webengine 切块用,默认 30)"
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
"additionalProperties": true
|
|
528
|
+
}
|