@dsh-gis/dsh-video-studio-skill 0.9.1 → 1.0.4

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 (63) hide show
  1. package/CHANGELOG.md +473 -0
  2. package/README.md +263 -327
  3. package/THIRD_PARTY_NOTICES.md +2 -2
  4. package/package.json +9 -10
  5. package/schemas/design.schema.json +722 -0
  6. package/schemas/film.schema.json +31 -42
  7. package/schemas/proposal.schema.json +133 -0
  8. package/skills/video-studio/SKILL.md +1216 -1123
  9. package/skills/video-studio/assets/design_fixture.json +141 -0
  10. package/skills/video-studio/assets/film.json +2 -4
  11. package/skills/video-studio/assets/golden_frames.json +13 -10
  12. package/skills/video-studio/assets/scenes.py +153 -65
  13. package/skills/video-studio/assets/voice_loudness.json +16 -0
  14. package/skills/video-studio/references/appearance.md +123 -0
  15. package/skills/video-studio/references/audio-variation.md +74 -93
  16. package/skills/video-studio/references/audio.md +64 -66
  17. package/skills/video-studio/references/change-impact.md +5 -5
  18. package/skills/video-studio/references/{v08-quality.md → delivery-gates.md} +16 -18
  19. package/skills/video-studio/references/frame-qa.md +48 -16
  20. package/skills/video-studio/references/pipeline.md +4 -4
  21. package/skills/video-studio/references/pitfalls.md +22 -3
  22. package/skills/video-studio/references/proposal.md +160 -0
  23. package/skills/video-studio/references/quality-gates.md +11 -11
  24. package/skills/video-studio/references/scene-authoring.md +2 -2
  25. package/skills/video-studio/references/scene-grammar.md +40 -42
  26. package/skills/video-studio/references/sfx-design.md +8 -6
  27. package/skills/video-studio/references/web-engine.md +8 -8
  28. package/skills/video-studio/references/word-timeline.md +9 -9
  29. package/skills/video-studio/requirements.txt +9 -13
  30. package/skills/video-studio/scripts/designkit.py +2115 -0
  31. package/skills/video-studio/scripts/filmcheck.py +22 -48
  32. package/skills/video-studio/scripts/filmkit.py +2980 -2904
  33. package/skills/video-studio/scripts/gates.py +4 -4
  34. package/skills/video-studio/scripts/grammar.py +73 -13
  35. package/skills/video-studio/scripts/musicgen.py +2042 -0
  36. package/skills/video-studio/scripts/preflight.py +14 -7
  37. package/skills/video-studio/scripts/previewkit.py +848 -0
  38. package/skills/video-studio/scripts/propose.py +825 -0
  39. package/skills/video-studio/scripts/qa_frames.py +73 -39
  40. package/skills/video-studio/scripts/qaasr.py +26 -7
  41. package/skills/video-studio/scripts/qavmaf.py +89 -23
  42. package/skills/video-studio/scripts/render.py +545 -231
  43. package/skills/video-studio/scripts/scorekit.py +55 -1755
  44. package/skills/video-studio/scripts/selfcheck.py +815 -215
  45. package/skills/video-studio/scripts/sfxkit.py +27 -26
  46. package/skills/video-studio/scripts/stagewatch.py +24 -8
  47. package/skills/video-studio/scripts/stylekit.py +207 -888
  48. package/skills/video-studio/scripts/voicekit.py +508 -387
  49. package/skills/video-studio/scripts/webengine.py +71 -72
  50. package/tools/audio_similarity.py +64 -37
  51. package/tools/ci_check.py +20 -14
  52. package/tools/estimate.py +34 -29
  53. package/tools/golden_frames.py +72 -28
  54. package/tools/silhouette_qa.py +520 -168
  55. package/docs/demo-pil-sheet.png +0 -0
  56. package/docs/styles/demo-results.json +0 -76
  57. package/docs/styles/sheet-8-styles.png +0 -0
  58. package/docs/styles/sheet-ai.png +0 -0
  59. package/docs/styles/sheet-before-after.png +0 -0
  60. package/docs/styles/sheet-craft.png +0 -0
  61. package/docs/styles/sheet-night.png +0 -0
  62. package/skills/video-studio/assets/score_demo.json +0 -307
  63. package/skills/video-studio/references/style-packs.md +0 -283
@@ -0,0 +1,722 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://github.com/znlgis/dsh-video-studio-skill/schemas/design.schema.json",
4
+ "title": "video-studio design(v1.0 设计 DSL)",
5
+ "description": "一份 design.json 描述'这一版长什么样':结构、视觉、声音、节奏。由 propose.py --confirm 冻结,render 阶段作为唯一画面/声音依据。",
6
+ "type": "object",
7
+ "required": [
8
+ "schema",
9
+ "id",
10
+ "structure",
11
+ "visual",
12
+ "audio",
13
+ "pacing"
14
+ ],
15
+ "additionalProperties": false,
16
+ "properties": {
17
+ "schema": {
18
+ "type": "integer",
19
+ "const": 1
20
+ },
21
+ "id": {
22
+ "type": "string",
23
+ "pattern": "^[a-z0-9][a-z0-9._-]{1,63}$"
24
+ },
25
+ "label": {
26
+ "type": "string",
27
+ "maxLength": 40
28
+ },
29
+ "pitch": {
30
+ "type": "string",
31
+ "maxLength": 120,
32
+ "description": "一句话立意(给用户看)"
33
+ },
34
+ "_unmatched_constraints": {
35
+ "type": "array",
36
+ "items": {
37
+ "type": "string"
38
+ },
39
+ "description": "采样期附加信息:brief 里没能识别的约束(例如用户写了「要有科幻感」)。不参与指纹、不影响渲染,但它必须被契约接纳,否则采样器吐出的设计自己就过不了校验。"
40
+ },
41
+ "structure": {
42
+ "type": "object",
43
+ "required": [
44
+ "segments"
45
+ ],
46
+ "additionalProperties": false,
47
+ "properties": {
48
+ "segments": {
49
+ "type": "integer",
50
+ "minimum": 1,
51
+ "maximum": 40
52
+ },
53
+ "beats": {
54
+ "type": "array",
55
+ "items": {
56
+ "type": "string"
57
+ },
58
+ "description": "每段叙事用途,如 hook/stat/compare/outro"
59
+ },
60
+ "hold_policy": {
61
+ "type": "string",
62
+ "enum": [
63
+ "none",
64
+ "readable",
65
+ "long"
66
+ ]
67
+ },
68
+ "target_sec": {
69
+ "type": [
70
+ "number",
71
+ "null"
72
+ ],
73
+ "minimum": 3,
74
+ "maximum": 1800
75
+ }
76
+ }
77
+ },
78
+ "visual": {
79
+ "type": "object",
80
+ "required": [
81
+ "palette",
82
+ "typography",
83
+ "motif",
84
+ "transition",
85
+ "motion",
86
+ "bias",
87
+ "layout",
88
+ "hud"
89
+ ],
90
+ "additionalProperties": false,
91
+ "properties": {
92
+ "palette": {
93
+ "type": "object",
94
+ "required": [
95
+ "bg",
96
+ "bg2",
97
+ "surface",
98
+ "ink",
99
+ "muted",
100
+ "dim",
101
+ "accent",
102
+ "accent2",
103
+ "good",
104
+ "bad",
105
+ "rule"
106
+ ],
107
+ "additionalProperties": false,
108
+ "properties": {
109
+ "bg": {
110
+ "type": "array",
111
+ "items": {
112
+ "type": "integer",
113
+ "minimum": 0,
114
+ "maximum": 255
115
+ },
116
+ "minItems": 3,
117
+ "maxItems": 3
118
+ },
119
+ "bg2": {
120
+ "type": "array",
121
+ "items": {
122
+ "type": "integer",
123
+ "minimum": 0,
124
+ "maximum": 255
125
+ },
126
+ "minItems": 3,
127
+ "maxItems": 3
128
+ },
129
+ "surface": {
130
+ "type": "array",
131
+ "items": {
132
+ "type": "integer",
133
+ "minimum": 0,
134
+ "maximum": 255
135
+ },
136
+ "minItems": 3,
137
+ "maxItems": 3
138
+ },
139
+ "ink": {
140
+ "type": "array",
141
+ "items": {
142
+ "type": "integer",
143
+ "minimum": 0,
144
+ "maximum": 255
145
+ },
146
+ "minItems": 3,
147
+ "maxItems": 3
148
+ },
149
+ "muted": {
150
+ "type": "array",
151
+ "items": {
152
+ "type": "integer",
153
+ "minimum": 0,
154
+ "maximum": 255
155
+ },
156
+ "minItems": 3,
157
+ "maxItems": 3
158
+ },
159
+ "dim": {
160
+ "type": "array",
161
+ "items": {
162
+ "type": "integer",
163
+ "minimum": 0,
164
+ "maximum": 255
165
+ },
166
+ "minItems": 3,
167
+ "maxItems": 3
168
+ },
169
+ "accent": {
170
+ "type": "array",
171
+ "items": {
172
+ "type": "integer",
173
+ "minimum": 0,
174
+ "maximum": 255
175
+ },
176
+ "minItems": 3,
177
+ "maxItems": 3
178
+ },
179
+ "accent2": {
180
+ "type": "array",
181
+ "items": {
182
+ "type": "integer",
183
+ "minimum": 0,
184
+ "maximum": 255
185
+ },
186
+ "minItems": 3,
187
+ "maxItems": 3
188
+ },
189
+ "good": {
190
+ "type": "array",
191
+ "items": {
192
+ "type": "integer",
193
+ "minimum": 0,
194
+ "maximum": 255
195
+ },
196
+ "minItems": 3,
197
+ "maxItems": 3
198
+ },
199
+ "bad": {
200
+ "type": "array",
201
+ "items": {
202
+ "type": "integer",
203
+ "minimum": 0,
204
+ "maximum": 255
205
+ },
206
+ "minItems": 3,
207
+ "maxItems": 3
208
+ },
209
+ "rule": {
210
+ "type": "array",
211
+ "items": {
212
+ "type": "integer",
213
+ "minimum": 0,
214
+ "maximum": 255
215
+ },
216
+ "minItems": 3,
217
+ "maxItems": 3
218
+ }
219
+ }
220
+ },
221
+ "family": {
222
+ "type": "string",
223
+ "enum": [
224
+ "sans",
225
+ "serif",
226
+ "kai",
227
+ "round"
228
+ ]
229
+ },
230
+ "typography": {
231
+ "type": "object",
232
+ "required": [
233
+ "tracking",
234
+ "line_gap",
235
+ "number",
236
+ "ratio"
237
+ ],
238
+ "additionalProperties": false,
239
+ "properties": {
240
+ "tracking": {
241
+ "type": "number",
242
+ "minimum": 0,
243
+ "maximum": 8
244
+ },
245
+ "line_gap": {
246
+ "type": "number",
247
+ "minimum": 1.15,
248
+ "maximum": 1.55
249
+ },
250
+ "number": {
251
+ "type": "string",
252
+ "enum": [
253
+ "dim",
254
+ "serif",
255
+ "cn",
256
+ "block",
257
+ "roman",
258
+ "timecode",
259
+ "dot",
260
+ "gilt"
261
+ ]
262
+ },
263
+ "ratio": {
264
+ "type": "number",
265
+ "minimum": 1,
266
+ "maximum": 3.6
267
+ },
268
+ "align": {
269
+ "type": "string",
270
+ "enum": [
271
+ "left",
272
+ "center",
273
+ "right"
274
+ ]
275
+ }
276
+ }
277
+ },
278
+ "motif": {
279
+ "type": "object",
280
+ "required": [
281
+ "kind",
282
+ "density"
283
+ ],
284
+ "additionalProperties": false,
285
+ "properties": {
286
+ "kind": {
287
+ "type": "string",
288
+ "enum": [
289
+ "brackets",
290
+ "hairlines",
291
+ "handdrawn",
292
+ "slabs",
293
+ "minimal",
294
+ "letterbox",
295
+ "signal",
296
+ "rays"
297
+ ]
298
+ },
299
+ "density": {
300
+ "type": "number",
301
+ "minimum": 0,
302
+ "maximum": 1
303
+ },
304
+ "detail": {
305
+ "type": "object"
306
+ }
307
+ }
308
+ },
309
+ "transition": {
310
+ "type": "object",
311
+ "required": [
312
+ "kind",
313
+ "dur"
314
+ ],
315
+ "additionalProperties": false,
316
+ "properties": {
317
+ "kind": {
318
+ "type": "string",
319
+ "enum": [
320
+ "dip",
321
+ "wash",
322
+ "paper",
323
+ "wipe",
324
+ "cut",
325
+ "iris"
326
+ ]
327
+ },
328
+ "dur": {
329
+ "type": "number",
330
+ "minimum": 0,
331
+ "maximum": 0.6
332
+ }
333
+ }
334
+ },
335
+ "motion": {
336
+ "type": "object",
337
+ "required": [
338
+ "ease",
339
+ "push",
340
+ "breathe_hz"
341
+ ],
342
+ "additionalProperties": false,
343
+ "properties": {
344
+ "ease": {
345
+ "type": "string",
346
+ "enum": [
347
+ "out3",
348
+ "out5",
349
+ "inOut3",
350
+ "outBack"
351
+ ]
352
+ },
353
+ "push": {
354
+ "type": "number",
355
+ "minimum": 0,
356
+ "maximum": 0.16
357
+ },
358
+ "breathe_hz": {
359
+ "type": "number",
360
+ "minimum": 0.2,
361
+ "maximum": 1.2
362
+ },
363
+ "enter": {
364
+ "type": "array",
365
+ "items": {
366
+ "type": "number"
367
+ },
368
+ "minItems": 2,
369
+ "maxItems": 2
370
+ }
371
+ }
372
+ },
373
+ "bias": {
374
+ "type": "object",
375
+ "required": [
376
+ "x",
377
+ "y"
378
+ ],
379
+ "additionalProperties": false,
380
+ "properties": {
381
+ "x": {
382
+ "type": "integer",
383
+ "minimum": -240,
384
+ "maximum": 240
385
+ },
386
+ "y": {
387
+ "type": "integer",
388
+ "minimum": -240,
389
+ "maximum": 240
390
+ },
391
+ "inset": {
392
+ "type": "integer",
393
+ "minimum": 0,
394
+ "maximum": 120
395
+ }
396
+ }
397
+ },
398
+ "layout": {
399
+ "type": "string",
400
+ "enum": [
401
+ "left-stack",
402
+ "center-stack",
403
+ "split-right"
404
+ ]
405
+ },
406
+ "hud": {
407
+ "type": "string",
408
+ "enum": [
409
+ "chip-left",
410
+ "corner-line",
411
+ "none"
412
+ ]
413
+ },
414
+ "layout_cycle": {
415
+ "type": "array",
416
+ "minItems": 2,
417
+ "uniqueItems": true,
418
+ "items": {
419
+ "type": "string",
420
+ "enum": [
421
+ "left-stack",
422
+ "center-stack",
423
+ "split-right"
424
+ ]
425
+ },
426
+ "description": "片内版式轮换顺序(可选)。grammar.plan_scenes 在 plan 没有显式 chapter_layout 时,按「章节首次出现的顺序」依次取 cycle[0]、cycle[1]… 循环;同一章内版式固定(观众视角一章是一段整体),换章才换版式——这正是「同一视频内部不要大面积重复」的实现。至少 2 种不同版式(只写一种等于不轮换,designkit.validate_design 报错)。不写 = design_to_plan 按设计指纹自动派生 2–3 种;没有这个键时 grammar 走 layout_default。"
427
+ },
428
+ "subtitle": {
429
+ "type": "object",
430
+ "additionalProperties": false,
431
+ "description": "字幕样式(可选)。字号 / 位置 / 背板透明度 / 圆角 / 字族 / 颜色 / 折行数全部可写:不写就是 filmkit.py 的默认值(不写时任何两条片子确实会得到同样的字幕带,所以要不同就该改这里)。默认值:size=46、y=null、align=center、plate_alpha=170、radius=10、family=null、color=null、max_lines=2。",
432
+ "properties": {
433
+ "size": {
434
+ "type": "integer",
435
+ "minimum": 20,
436
+ "maximum": 96,
437
+ "default": 46,
438
+ "description": "字幕字号(像素,默认 46)。范围 20–96 与 designkit.validate_design 同源;采样器只在 40–56 之间取「好看」的值,手写可越过但别越界。"
439
+ },
440
+ "y": {
441
+ "type": [
442
+ "integer",
443
+ "null"
444
+ ],
445
+ "minimum": 0,
446
+ "maximum": 1030,
447
+ "default": null,
448
+ "description": "字幕基线 y(像素;默认 null = 底部安全区,由 filmkit 按画布高度算)。范围 0–1030 与 designkit.validate_design 同源。"
449
+ },
450
+ "align": {
451
+ "type": "string",
452
+ "enum": [
453
+ "center",
454
+ "left"
455
+ ],
456
+ "default": "center",
457
+ "description": "字幕对齐方式(默认 center;left = 左对齐,适合左侧长文版式)。"
458
+ },
459
+ "plate_alpha": {
460
+ "type": "integer",
461
+ "minimum": 0,
462
+ "maximum": 255,
463
+ "default": 170,
464
+ "description": "字幕背板不透明度 0–255(默认 170;0 = 完全透明 = 不画背板)。"
465
+ },
466
+ "radius": {
467
+ "type": "integer",
468
+ "minimum": 0,
469
+ "maximum": 48,
470
+ "default": 10,
471
+ "description": "背板圆角半径(像素,默认 10;0 = 直角)。范围 0–48 与 designkit.validate_design 同源。"
472
+ },
473
+ "family": {
474
+ "type": [
475
+ "string",
476
+ "null"
477
+ ],
478
+ "enum": [
479
+ "sans",
480
+ "serif",
481
+ "kai",
482
+ "round",
483
+ null
484
+ ],
485
+ "default": null,
486
+ "description": "字幕字体族(默认 null = 随主题字体族;sans 可读性最好)。取值同 visual.family 的四族。"
487
+ },
488
+ "color": {
489
+ "type": [
490
+ "array",
491
+ "string",
492
+ "null"
493
+ ],
494
+ "default": null,
495
+ "description": "字幕颜色(默认 null = 随主题墨色低一档)。两种写法都认:[r,g,b] 整数三元素,或 \"#rrggbb\"(与 visual.palette 同口径)。"
496
+ },
497
+ "max_lines": {
498
+ "type": "integer",
499
+ "enum": [
500
+ 1,
501
+ 2,
502
+ 3
503
+ ],
504
+ "default": 2,
505
+ "description": "字幕最多折几行(默认 2;1 = 强单行,超长会被省略/缩字)。范围 1–3 与 designkit.validate_design 同源。"
506
+ }
507
+ }
508
+ },
509
+ "size": {
510
+ "type": "string",
511
+ "enum": [
512
+ "1920x1080",
513
+ "1280x720",
514
+ "960x540"
515
+ ],
516
+ "description": "画幅。本版**仅支持 16:9 横屏**(1920x1080 内部构图,可 lanczos 下采样到 1280x720 / 960x540);竖屏、非 16:9 或上采样一律拒绝。与 film.json 的 video 块(width/height/fps)冲突时报错(fail-closed,绝不静默取其一)。"
517
+ },
518
+ "fps": {
519
+ "type": "integer",
520
+ "enum": [
521
+ 24,
522
+ 25,
523
+ 30,
524
+ 50,
525
+ 60
526
+ ],
527
+ "description": "帧率。与 film.json 的 video.fps 冲突时报错(fail-closed)。缺省 30。"
528
+ }
529
+ }
530
+ },
531
+ "audio": {
532
+ "type": "object",
533
+ "required": [
534
+ "voice",
535
+ "music"
536
+ ],
537
+ "additionalProperties": false,
538
+ "properties": {
539
+ "voice": {
540
+ "description": "两种形态都接受:裸 edge voice id 字符串(如 zh-CN-YunxiNeural),或对象 {mode,id,map,jitter,max_distinct}",
541
+ "type": [
542
+ "object",
543
+ "string"
544
+ ],
545
+ "required": [
546
+ "mode"
547
+ ],
548
+ "additionalProperties": false,
549
+ "properties": {
550
+ "mode": {
551
+ "type": "string",
552
+ "enum": [
553
+ "edge_id",
554
+ "wav"
555
+ ]
556
+ },
557
+ "id": {
558
+ "type": "string",
559
+ "description": "edge voice id,如 zh-CN-YunxiNeural"
560
+ },
561
+ "rate": {
562
+ "type": "string",
563
+ "default": "+0%"
564
+ },
565
+ "pitch": {
566
+ "type": "string",
567
+ "default": "+0Hz"
568
+ },
569
+ "map": {
570
+ "type": "object",
571
+ "description": "kind -> voice id 或 {mode,id}"
572
+ },
573
+ "jitter": {
574
+ "type": "number",
575
+ "minimum": 0,
576
+ "maximum": 1
577
+ },
578
+ "max_distinct": {
579
+ "type": "integer",
580
+ "minimum": 1,
581
+ "maximum": 5
582
+ }
583
+ }
584
+ },
585
+ "music": {
586
+ "type": "object",
587
+ "required": [
588
+ "mode"
589
+ ],
590
+ "additionalProperties": false,
591
+ "properties": {
592
+ "mode": {
593
+ "type": "string",
594
+ "enum": [
595
+ "params",
596
+ "file",
597
+ "off"
598
+ ]
599
+ },
600
+ "arranger": {
601
+ "type": "string",
602
+ "description": "参数化编排器的配置 id(P2 实现)"
603
+ },
604
+ "style": {
605
+ "type": "string",
606
+ "description": "已废弃:配乐没有风格表,这个键不决定任何东西(保留只为老 design.json / 既有 fixture 能继续通过契约校验;designkit.validate_design 也接受它)"
607
+ },
608
+ "bpm": {
609
+ "type": [
610
+ "number",
611
+ "string"
612
+ ]
613
+ },
614
+ "key": {
615
+ "type": "string"
616
+ },
617
+ "scale": {
618
+ "type": "string",
619
+ "enum": [
620
+ "minor",
621
+ "major"
622
+ ],
623
+ "description": "调式(designkit 会校验;audio.music.scale 决定大调/小调)"
624
+ },
625
+ "mood": {
626
+ "type": "string"
627
+ },
628
+ "seed": {
629
+ "type": "integer"
630
+ },
631
+ "gain_db": {
632
+ "type": "number",
633
+ "minimum": -60,
634
+ "maximum": 12
635
+ },
636
+ "duck_db": {
637
+ "type": "number",
638
+ "minimum": 0,
639
+ "maximum": 24
640
+ },
641
+ "sections": {
642
+ "type": "array",
643
+ "items": {
644
+ "type": "object"
645
+ }
646
+ },
647
+ "file": {
648
+ "type": "string",
649
+ "description": "mode=file 时的音频路径"
650
+ }
651
+ }
652
+ },
653
+ "sfx": {
654
+ "type": "object",
655
+ "additionalProperties": false,
656
+ "properties": {
657
+ "enabled": {
658
+ "type": "boolean"
659
+ },
660
+ "density": {
661
+ "type": "string",
662
+ "enum": [
663
+ "none",
664
+ "sparse",
665
+ "normal",
666
+ "rich"
667
+ ]
668
+ },
669
+ "gain_db": {
670
+ "type": "number",
671
+ "minimum": -40,
672
+ "maximum": 12
673
+ },
674
+ "cues": {
675
+ "type": "array",
676
+ "items": {
677
+ "type": "object"
678
+ }
679
+ }
680
+ }
681
+ }
682
+ }
683
+ },
684
+ "pacing": {
685
+ "type": "object",
686
+ "required": [
687
+ "lead",
688
+ "tail",
689
+ "min_dur",
690
+ "hold"
691
+ ],
692
+ "additionalProperties": false,
693
+ "properties": {
694
+ "lead": {
695
+ "type": "number",
696
+ "minimum": 0,
697
+ "maximum": 3
698
+ },
699
+ "tail": {
700
+ "type": "number",
701
+ "minimum": 0,
702
+ "maximum": 3
703
+ },
704
+ "min_dur": {
705
+ "type": "number",
706
+ "minimum": 1,
707
+ "maximum": 12
708
+ },
709
+ "hold": {
710
+ "type": "number",
711
+ "minimum": 0,
712
+ "maximum": 5
713
+ },
714
+ "item_stagger": {
715
+ "type": "number",
716
+ "minimum": 0.05,
717
+ "maximum": 1.2
718
+ }
719
+ }
720
+ }
721
+ }
722
+ }