@dsh-gis/dsh-video-studio-skill 1.0.2 → 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.
- package/CHANGELOG.md +49 -0
- package/README.md +84 -108
- package/THIRD_PARTY_NOTICES.md +2 -2
- package/package.json +1 -1
- package/schemas/design.schema.json +5 -5
- package/schemas/film.schema.json +31 -31
- package/skills/video-studio/SKILL.md +168 -268
- package/skills/video-studio/assets/film.json +2 -3
- package/skills/video-studio/assets/golden_frames.json +11 -11
- package/skills/video-studio/assets/scenes.py +92 -49
- package/skills/video-studio/references/{style-packs.md → appearance.md} +17 -15
- package/skills/video-studio/references/audio-variation.md +73 -96
- package/skills/video-studio/references/audio.md +40 -44
- package/skills/video-studio/references/change-impact.md +2 -2
- package/skills/video-studio/references/{v08-quality.md → delivery-gates.md} +9 -11
- package/skills/video-studio/references/frame-qa.md +47 -15
- package/skills/video-studio/references/pipeline.md +4 -4
- package/skills/video-studio/references/pitfalls.md +22 -3
- package/skills/video-studio/references/proposal.md +19 -36
- package/skills/video-studio/references/quality-gates.md +11 -11
- package/skills/video-studio/references/scene-authoring.md +2 -2
- package/skills/video-studio/references/scene-grammar.md +17 -24
- package/skills/video-studio/references/sfx-design.md +7 -5
- package/skills/video-studio/references/web-engine.md +7 -7
- package/skills/video-studio/references/word-timeline.md +7 -7
- package/skills/video-studio/requirements.txt +9 -13
- package/skills/video-studio/scripts/designkit.py +84 -89
- package/skills/video-studio/scripts/filmcheck.py +19 -19
- package/skills/video-studio/scripts/filmkit.py +2949 -2948
- package/skills/video-studio/scripts/gates.py +4 -4
- package/skills/video-studio/scripts/grammar.py +10 -10
- package/skills/video-studio/scripts/musicgen.py +3 -4
- package/skills/video-studio/scripts/preflight.py +5 -5
- package/skills/video-studio/scripts/previewkit.py +11 -12
- package/skills/video-studio/scripts/propose.py +11 -11
- package/skills/video-studio/scripts/qa_frames.py +34 -35
- package/skills/video-studio/scripts/qaasr.py +26 -7
- package/skills/video-studio/scripts/qavmaf.py +19 -19
- package/skills/video-studio/scripts/render.py +137 -141
- package/skills/video-studio/scripts/scorekit.py +21 -23
- package/skills/video-studio/scripts/selfcheck.py +208 -135
- package/skills/video-studio/scripts/sfxkit.py +27 -26
- package/skills/video-studio/scripts/stagewatch.py +4 -4
- package/skills/video-studio/scripts/stylekit.py +77 -282
- package/skills/video-studio/scripts/voicekit.py +43 -44
- package/skills/video-studio/scripts/webengine.py +62 -64
- package/tools/audio_similarity.py +12 -12
- package/tools/ci_check.py +16 -16
- package/tools/estimate.py +24 -25
- package/tools/golden_frames.py +17 -18
- package/tools/silhouette_qa.py +13 -14
|
@@ -43,7 +43,7 @@ HERE = Path(__file__).resolve().parent
|
|
|
43
43
|
|
|
44
44
|
KINDS = ("hook", "body", "quote", "outro", "emphasis", "calm") # 也是 voicekit 的语气 id
|
|
45
45
|
|
|
46
|
-
#
|
|
46
|
+
# 视觉场景类型:决定"这段画面长成什么构图",与叙事 kind **正交**——
|
|
47
47
|
# kind 管声线/语气/配乐能量(voicekit / scorekit 读它);
|
|
48
48
|
# type 只管构图(assets/scenes.py 的 _DRAWERS 读它)。
|
|
49
49
|
# 所以**不新增 kind 值**:hero/stat/... 不是语气,硬塞进 KINDS 会撞 voicekit 的 tone id
|
|
@@ -65,8 +65,8 @@ ID_RE = re.compile(r"^[A-Za-z0-9_.\-]+$")
|
|
|
65
65
|
CPS = 4.2 # 每秒约 4.2 字(voicekit 实测中位口径)
|
|
66
66
|
# 语速区间而不是单一 4.2:voicekit 校准实测 3.84–4.61 cps(9 个 persona,固定校准句),
|
|
67
67
|
# 而 stylekit 的声线策略允许的 cps_band 是 3.6–5.6(rate 覆盖 ±15% 后)。
|
|
68
|
-
#
|
|
69
|
-
# "剧本与 timeline 差 5.23 s"的假 WARN
|
|
68
|
+
# 只用中位数会误报:夹具片实测 5.2 字/秒的句子被按 4.2 估 -> 全片多算 5.2 s ->
|
|
69
|
+
# "剧本与 timeline 差 5.23 s"的假 WARN(改按声线带宽判,夹具片可复现)。
|
|
70
70
|
CPS_LO, CPS_HI = 3.6, 5.6
|
|
71
71
|
DEFAULT_LEAD, DEFAULT_TAIL, DEFAULT_MIN_DUR = 0.62, 0.92, 3.0
|
|
72
72
|
TIMELINE_TOL = 0.5 # 估算与 timeline 差超过这个秒数就 WARN
|
|
@@ -211,7 +211,7 @@ LINE_ITEM_SPEC = {
|
|
|
211
211
|
},
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
# ----
|
|
214
|
+
# ---- 视觉场景字段的嵌套结构(写法照抄 LINE_ITEM_SPEC)----
|
|
215
215
|
# 这些对象的键由 scenes.py 的 10 个绘制器读:拼错就是"写了不生效",所以**不**用
|
|
216
216
|
# open=True(那是留给 sfx 配方参数那种真·透传的)。每层列全 props,才能把拼错报成
|
|
217
217
|
# unknown_key(WARN + "是不是想写 X"),把类型写错报成 ERROR。
|
|
@@ -282,7 +282,7 @@ LINE_SPEC = {
|
|
|
282
282
|
"persona": {"t": "str"},
|
|
283
283
|
"tone": {"t": "str", "enum": KINDS},
|
|
284
284
|
"voice": {"t": "str"},
|
|
285
|
-
# ----
|
|
285
|
+
# ---- 视觉场景字段(7 个全可选)----
|
|
286
286
|
# type 缺省由 grammar.py 按内容推导;其余字段是给绘制器的原料,不写就不画。
|
|
287
287
|
# 注意这些字段与 kind **正交**,不是新 kind:kind 仍只有上面 6 个(voicekit 的语气 id)。
|
|
288
288
|
"type": {"t": "str", "enum": SCENE_TYPES},
|
|
@@ -322,11 +322,11 @@ SCRIPT_SPEC = {
|
|
|
322
322
|
"props": {
|
|
323
323
|
"title": {"t": "str", "nonempty_warn": True},
|
|
324
324
|
"end_text": {"t": "str"},
|
|
325
|
-
#
|
|
326
|
-
# It used to use enum_dynamic -> _load_styles(); STYLE_IDS is
|
|
327
|
-
#
|
|
325
|
+
# style is deprecated: appearance comes from work/design.json.
|
|
326
|
+
# It used to use enum_dynamic -> _load_styles(); STYLE_IDS is empty, so it emitted
|
|
327
|
+
# a misleading WARN saying stylekit.py was missing (the file was there).
|
|
328
328
|
# Now it is an inert key: accepted (old scripts must not hard-fail) but reported.
|
|
329
|
-
"style": {"t": "str", "inert": "
|
|
329
|
+
"style": {"t": "str", "inert": "已废弃:外观由 work/design.json 决定(python propose.py --brief ... 再 --confirm),这里写任何值都不生效"},
|
|
330
330
|
"engine": {"t": "str", "enum": ENGINES},
|
|
331
331
|
"voice": {"t": ("str", "dict"), "open": "dict"},
|
|
332
332
|
"rate": {"t": "str", "pattern": RATE_RE, "example": "+6%"},
|
|
@@ -369,10 +369,10 @@ SCRIPT_SPEC = {
|
|
|
369
369
|
"seed": {"t": "int", "min": 0},
|
|
370
370
|
"seed_from_content": {"t": "bool"},
|
|
371
371
|
"gain_db": {"t": "num"}, "duck_db": {"t": "num"},
|
|
372
|
-
#
|
|
372
|
+
# 旁白优先:mix_film 读这四个(背景在人声处额外让位多少 / 阈值)
|
|
373
373
|
"voice_duck_db": {"t": "num"}, "voice_duck_sfx_db": {"t": "num"},
|
|
374
374
|
"voice_thresh_db": {"t": "num"}, "voice_floor_db": {"t": "num"},
|
|
375
|
-
#
|
|
375
|
+
# SNR 兜底:混音后实测人声/背景差,不足就整体压背景
|
|
376
376
|
"guard_snr_db": {"t": "num"}, "guard_cap_db": {"t": "num"},
|
|
377
377
|
"seg": {"t": "num", "min": 0.0}, "amp": {"t": "num", "min": 0.0},
|
|
378
378
|
"gain": {"t": "num", "min": 0.0}, "xfade": {"t": "num", "min": 0.0},
|
|
@@ -385,7 +385,7 @@ SCRIPT_SPEC = {
|
|
|
385
385
|
# render.py 的 st_sfx 把它透传给 CueBus.build_audio():按配方名覆盖基础电平。
|
|
386
386
|
# 以前 schema/filmcheck 都没写,用户写了会被当未知键警告(其实真的会生效)。
|
|
387
387
|
"base_db": {"t": "dict", "open": True},
|
|
388
|
-
#
|
|
388
|
+
# 音频差异化:content_seed 由 CueBus 读(位置派生 vs 内容派生);
|
|
389
389
|
# duck_transitions 由 render.st_sfx 读(段落边界前的转场音效自动让位)。
|
|
390
390
|
"content_seed": {"t": "bool"},
|
|
391
391
|
"duck_transitions": {"t": "bool"},
|
|
@@ -393,10 +393,10 @@ SCRIPT_SPEC = {
|
|
|
393
393
|
"web": {"t": "dict", "props": {
|
|
394
394
|
"entry": {"t": "str"},
|
|
395
395
|
"chunk_s": {"t": "num", "min": 0.0}}},
|
|
396
|
-
# ----
|
|
396
|
+
# ---- 词级时间戳 / TTS 后端 ----
|
|
397
397
|
# 词级时间戳开关(字幕按词折行 / cue 词锚点 / G10 门禁都依赖它)
|
|
398
398
|
"words": {"t": "bool"},
|
|
399
|
-
# TTS
|
|
399
|
+
# TTS 后端选择(接口化;默认 edge,其它后端需先 register_tts_backend)
|
|
400
400
|
"tts": {"t": "dict", "props": {
|
|
401
401
|
"backend": {"t": "str"},
|
|
402
402
|
"voice": {"t": ("str", "dict")}}},
|
|
@@ -410,7 +410,7 @@ SCRIPT_SPEC = {
|
|
|
410
410
|
# 质检门禁参数(全片 VMAF/SSIM 阻断 + ASR 回读)
|
|
411
411
|
"qa": {"t": "dict", "props": {
|
|
412
412
|
"vmaf": {"t": "dict", "props": {
|
|
413
|
-
# enabled / require_vmaf
|
|
413
|
+
# enabled / require_vmaf 是起草时留下的**惰性键**:schema 与这里都认,
|
|
414
414
|
# 但 render.py / qavmaf.py 全仓没有读取点——写了它门禁照跑,用户以为自己关掉了。
|
|
415
415
|
# 真正生效的是 mode=off(或命令行 --vmaf off)。这里标 inert 让 filmcheck 报 WARN,
|
|
416
416
|
# 因为本项目的立场是"写对了却不生效"比"报未知键"更坏。
|
|
@@ -418,7 +418,7 @@ SCRIPT_SPEC = {
|
|
|
418
418
|
"mode": {"t": "str", "enum": ("full", "sample", "off")},
|
|
419
419
|
"pass": {"t": "num", "min": 0.0},
|
|
420
420
|
"warn": {"t": "num", "min": 0.0},
|
|
421
|
-
#
|
|
421
|
+
# 键名对齐 schemas/film.schema.json 与 qavmaf.report(sample_step=...)。
|
|
422
422
|
# 这里以前写的是 sample_s —— 全仓没有任何消费者(render 不读、qavmaf 只认
|
|
423
423
|
# sample_step),于是"写对了却完全没生效",而 schema 里合法写完还会被本脚本
|
|
424
424
|
# 报成未知键。别再兼容 sample_s:它从来没生效过,留着只会让人以为能用。
|
|
@@ -561,7 +561,7 @@ def _cue_ref(at):
|
|
|
561
561
|
float(off)
|
|
562
562
|
except ValueError:
|
|
563
563
|
return "bad", "偏移 %r 不是数字(写 l03+0.35 或 l03-0.2)" % off
|
|
564
|
-
#
|
|
564
|
+
# 词锚点:<id>:w<N>[+/-秒]。把 ":wN" 剥掉再做 id 存在性检查,
|
|
565
565
|
# 否则合法写法会被报成"场景 id 不存在"(假失败比不校验更糟)。
|
|
566
566
|
if ":w" in sid:
|
|
567
567
|
head, _sep, tail = sid.partition(":w")
|
|
@@ -633,7 +633,7 @@ def check_cross(script, script_path, rep, ctx):
|
|
|
633
633
|
"tail_map)。例如 %s: 1.4" % lid),
|
|
634
634
|
"inert_line_tail")
|
|
635
635
|
|
|
636
|
-
# ----
|
|
636
|
+
# ---- 场景语法:绘制器的容量上限(超了会被静默截断) ----
|
|
637
637
|
# 这是本项目最忌讳的一类坑:作者写对了、跑得通、但画面上少了几条,而没有任何提示。
|
|
638
638
|
# 容量由 assets/scenes.py 的实现决定(stats 取前 3 条、series 前 6 条、steps 前 5 条、
|
|
639
639
|
# sides 每侧前 3 条),改那边要同步改这里。
|
|
@@ -656,7 +656,7 @@ def check_cross(script, script_path, rep, ctx):
|
|
|
656
656
|
"sides.%s 有 %d 条,但左右对比构图每侧只画前 3 条"
|
|
657
657
|
% (side, len(its)), "scene_capacity")
|
|
658
658
|
|
|
659
|
-
# ----
|
|
659
|
+
# ---- video 块:只支持 16:9 横屏 + 下采样输出 ----
|
|
660
660
|
# **不要在这里重写一遍规则**:允许列表 / 宽高比 / 上采样拒绝的权威实现在
|
|
661
661
|
# filmkit.video_plan()。以前这里是第二套手写判据,于是"1600x900"能过 filmcheck
|
|
662
662
|
# (0 error 0 warning)却在 render 的 st_layout 被 video_plan 拒片——校验器放行、
|