@oh-story/dsh 0.1.12 → 0.1.13

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 (264) hide show
  1. package/README.md +17 -11
  2. package/lib/client.js +85 -35
  3. package/lib/client.js.map +3 -3
  4. package/lib/drama/manifest.json +41 -36
  5. package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +340 -13
  6. package/lib/drama/skills/short-drama-assets/references/voice-direction.md +4 -2
  7. package/lib/drama/skills/short-drama-edit/SKILL.md +32 -12
  8. package/lib/drama/skills/short-drama-edit/references/still-cuts.md +90 -0
  9. package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1035 -145
  10. package/lib/drama/skills/short-drama-edit/scripts/selftest.py +48 -0
  11. package/lib/drama/skills/short-drama-produce/SKILL.md +6 -1
  12. package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +12 -0
  13. package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +138 -9
  14. package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +6 -0
  15. package/lib/drama/skills/short-drama-storyboard/SKILL.md +2 -0
  16. package/lib/drama/skills/short-drama-storyboard/references/production-shot-grammar.md +3 -1
  17. package/lib/drama/skills/short-drama-video-prompts/SKILL.md +7 -0
  18. package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +14 -0
  19. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +19 -6
  20. package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +1 -0
  21. package/lib/drama/skills/short-drama-video-prompts/references/target-model-profile.md +5 -0
  22. package/lib/drama/skills/short-drama-video-prompts/references/wan-3.0.md +4 -1
  23. package/lib/index.js +16 -7
  24. package/lib/index.js.map +2 -2
  25. package/lib/novel-to-game/README.md +98 -44
  26. package/lib/novel-to-game/README_ZH.md +100 -46
  27. package/lib/novel-to-game/VERSION +1 -1
  28. package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +27 -202
  29. package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +23 -115
  30. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/chamber.webp +0 -0
  31. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/court_night.webp +0 -0
  32. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/court_rain.webp +0 -0
  33. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/garden.webp +0 -0
  34. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/hall.webp +0 -0
  35. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/kitchen.webp +0 -0
  36. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/street.webp +0 -0
  37. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/street_dawn.webp +0 -0
  38. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/temple.webp +0 -0
  39. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/yue/moon.webp +0 -0
  40. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/meng/angry.webp +0 -0
  41. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/meng/blush.webp +0 -0
  42. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/meng/neutral.webp +0 -0
  43. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/meng/sad.webp +0 -0
  44. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/meng/smile.webp +0 -0
  45. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/meng/surprised.webp +0 -0
  46. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pan/angry.webp +0 -0
  47. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pan/blush.webp +0 -0
  48. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pan/neutral.webp +0 -0
  49. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pan/sad.webp +0 -0
  50. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pan/smile.webp +0 -0
  51. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pan/surprised.webp +0 -0
  52. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pinger/angry.webp +0 -0
  53. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pinger/blush.webp +0 -0
  54. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pinger/neutral.webp +0 -0
  55. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pinger/sad.webp +0 -0
  56. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pinger/smile.webp +0 -0
  57. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/pinger/surprised.webp +0 -0
  58. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/xuee/angry.webp +0 -0
  59. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/xuee/blush.webp +0 -0
  60. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/xuee/neutral.webp +0 -0
  61. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/xuee/sad.webp +0 -0
  62. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/xuee/smile.webp +0 -0
  63. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/xuee/surprised.webp +0 -0
  64. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/yue/angry.webp +0 -0
  65. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/yue/blush.webp +0 -0
  66. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/yue/neutral.webp +0 -0
  67. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/yue/sad.webp +0 -0
  68. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/yue/smile.webp +0 -0
  69. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/sprite/yue/surprised.webp +0 -0
  70. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +326 -2503
  71. package/lib/novel-to-game/examples/jin-ping-mei/build/app/index.html +71 -4
  72. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/adv.js +221 -0
  73. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/audio.js +113 -257
  74. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +511 -3026
  75. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/menus.js +277 -0
  76. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/petals.js +67 -0
  77. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/stage.js +180 -0
  78. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/store.js +70 -0
  79. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/common.js +198 -0
  80. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/common2.js +204 -0
  81. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/common3.js +198 -0
  82. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/dates.js +186 -0
  83. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/index.js +122 -0
  84. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/meng.js +190 -0
  85. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/pan.js +212 -0
  86. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/pinger.js +198 -0
  87. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/xuee.js +199 -0
  88. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/story/yue.js +214 -0
  89. package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +2 -2
  90. package/lib/novel-to-game/examples/jin-ping-mei/build/art/generated-art.json +182 -45
  91. package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +7 -17
  92. package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +9 -9
  93. package/lib/novel-to-game/manifest.json +303 -78
  94. package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +7 -2
  95. package/lib/novel-to-game/skills/game-concept/references/concept-method.md +2 -0
  96. package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +2 -0
  97. package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +9 -0
  98. package/lib/types/client/drama-production-view.d.ts +11 -0
  99. package/lib/types/client/drama-production-view.d.ts.map +1 -1
  100. package/lib/types/client/file-activity.d.ts +1 -1
  101. package/lib/types/client/file-activity.d.ts.map +1 -1
  102. package/lib/types/client/production-prompts.d.ts +7 -1
  103. package/lib/types/client/production-prompts.d.ts.map +1 -1
  104. package/lib/types/client/production-runtime.d.ts +7 -2
  105. package/lib/types/client/production-runtime.d.ts.map +1 -1
  106. package/lib/types/drama-adapters.d.ts.map +1 -1
  107. package/lib/types/skill-provider.d.ts.map +1 -1
  108. package/lib/types/video-project.d.ts.map +1 -1
  109. package/lib/video-recap/CHANGELOG.md +108 -1
  110. package/lib/video-recap/README.en.md +18 -14
  111. package/lib/video-recap/README.md +18 -14
  112. package/lib/video-recap/manifest.json +297 -321
  113. package/lib/video-recap/skills/video-assemble/SKILL.md +18 -16
  114. package/lib/video-recap/skills/video-assemble/references/explicit-audio-mix.md +3 -1
  115. package/lib/video-recap/skills/video-assemble/references/jianying/SOURCE.md +5 -5
  116. package/lib/video-recap/skills/video-assemble/references/packaging.md +4 -4
  117. package/lib/video-recap/skills/video-assemble/references/subtitle-track.md +10 -10
  118. package/lib/video-recap/skills/video-assemble/scripts/adoption/audio_mix_binding.py +13 -2
  119. package/lib/video-recap/skills/video-assemble/scripts/adoption/av_clock.py +109 -0
  120. package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_publish.py +4 -1
  121. package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +2 -9
  122. package/lib/video-recap/skills/video-assemble/scripts/assemble.py +188 -51
  123. package/lib/video-recap/skills/video-assemble/scripts/assemble_constants.py +0 -1
  124. package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +32 -75
  125. package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +8 -15
  126. package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +202 -161
  127. package/lib/video-recap/skills/video-assemble/scripts/codec_peak.py +112 -0
  128. package/lib/video-recap/skills/video-assemble/scripts/export_jianying.py +10 -101
  129. package/lib/video-recap/skills/video-assemble/scripts/jianying/builders.py +44 -475
  130. package/lib/video-recap/skills/video-assemble/scripts/jianying/model.py +1 -22
  131. package/lib/video-recap/skills/video-assemble/scripts/jianying/templates.py +0 -3
  132. package/lib/video-recap/skills/video-assemble/scripts/jianying/timeline_contract.py +36 -103
  133. package/lib/video-recap/skills/video-assemble/scripts/jianying/tracks.py +0 -8
  134. package/lib/video-recap/skills/video-assemble/scripts/jianying/writer.py +28 -203
  135. package/lib/video-recap/skills/video-assemble/scripts/lib.py +20 -34
  136. package/lib/video-recap/skills/video-assemble/scripts/loudness.py +332 -0
  137. package/lib/video-recap/skills/video-assemble/scripts/media.py +158 -38
  138. package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +30 -16
  139. package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +49 -8
  140. package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +17 -6
  141. package/lib/video-recap/skills/video-assemble/scripts/subtitles/core.py +24 -2
  142. package/lib/video-recap/skills/video-assemble/scripts/subtitles/track.py +2 -5
  143. package/lib/video-recap/skills/video-assemble/scripts/subtitles/track_binding.py +2 -9
  144. package/lib/video-recap/skills/video-assemble/scripts/timeline.py +12 -34
  145. package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +3 -4
  146. package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +28 -2
  147. package/lib/video-recap/skills/video-cut/SKILL.md +37 -11
  148. package/lib/video-recap/skills/video-cut/references/shot-review.md +1 -1
  149. package/lib/video-recap/skills/video-cut/scripts/cut.py +2 -34
  150. package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +96 -124
  151. package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +97 -182
  152. package/lib/video-recap/skills/video-cut/scripts/cut_render.py +177 -166
  153. package/lib/video-recap/skills/video-cut/scripts/frame_grid.py +249 -0
  154. package/lib/video-recap/skills/video-cut/scripts/lib.py +0 -3
  155. package/lib/video-recap/skills/video-cut/scripts/media_geometry.py +173 -7
  156. package/lib/video-recap/skills/video-cut/scripts/sentence_boundaries.py +234 -151
  157. package/lib/video-recap/skills/video-cut/scripts/sentence_gate.py +189 -0
  158. package/lib/video-recap/skills/video-cut/scripts/shot_review.py +2 -6
  159. package/lib/video-recap/skills/video-recap/SKILL.md +24 -27
  160. package/lib/video-recap/skills/video-recap/references/audio-routing.md +8 -6
  161. package/lib/video-recap/skills/video-recap/references/config-playbook.md +8 -11
  162. package/lib/video-recap/skills/video-recap/references/data-schema.md +131 -74
  163. package/lib/video-recap/skills/video-recap/references/resource-library.md +17 -1
  164. package/lib/video-recap/skills/video-recap/scripts/doctor.py +51 -268
  165. package/lib/video-recap/skills/video-recap/scripts/final_qc.py +89 -254
  166. package/lib/video-recap/skills/video-recap/scripts/lib.py +81 -70
  167. package/lib/video-recap/skills/video-recap/scripts/library.py +40 -4
  168. package/lib/video-recap/skills/video-recap/scripts/materials.py +13 -80
  169. package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +49 -17
  170. package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +1 -3
  171. package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +86 -116
  172. package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +87 -23
  173. package/lib/video-recap/skills/video-recap/scripts/recap_source.py +0 -39
  174. package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +37 -135
  175. package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +118 -127
  176. package/lib/video-recap/skills/video-recap/scripts/resources/__init__.py +4 -0
  177. package/lib/video-recap/skills/video-recap/scripts/{resource_lock.py → resources/lock.py} +1 -1
  178. package/lib/video-recap/skills/video-recap/scripts/{project_binding.py → resources/project_binding.py} +78 -17
  179. package/lib/video-recap/skills/video-reference/SKILL.md +108 -0
  180. package/lib/video-recap/skills/video-reference/references/reference-schema.md +139 -0
  181. package/lib/video-recap/skills/video-reference/scripts/lib.py +85 -0
  182. package/lib/video-recap/skills/video-reference/scripts/reference.py +96 -0
  183. package/lib/video-recap/skills/video-reference/scripts/reference_check.py +553 -0
  184. package/lib/video-recap/skills/video-reference/scripts/reference_frames.py +122 -0
  185. package/lib/video-recap/skills/video-reference/scripts/reference_measure.py +253 -0
  186. package/lib/video-recap/skills/video-reference/scripts/reference_profile.py +271 -0
  187. package/lib/video-recap/skills/video-script/SKILL.md +9 -7
  188. package/lib/video-recap/skills/video-script/scripts/agent_text.py +18 -267
  189. package/lib/video-recap/skills/video-script/scripts/deslop_qc.py +12 -30
  190. package/lib/video-recap/skills/video-script/scripts/entry_suggestion.py +125 -0
  191. package/lib/video-recap/skills/video-script/scripts/evidence_bundle.py +2 -26
  192. package/lib/video-recap/skills/video-script/scripts/lib.py +5 -15
  193. package/lib/video-recap/skills/video-script/scripts/lint_summary.py +184 -0
  194. package/lib/video-recap/skills/video-script/scripts/narration_lint.py +120 -100
  195. package/lib/video-recap/skills/video-script/scripts/review.py +3 -34
  196. package/lib/video-recap/skills/video-script/scripts/review_grounding.py +20 -46
  197. package/lib/video-recap/skills/video-script/scripts/review_response.py +120 -258
  198. package/lib/video-recap/skills/video-script/scripts/review_runner.py +2 -10
  199. package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +89 -5
  200. package/lib/video-recap/skills/video-script/scripts/validate.py +26 -34
  201. package/lib/video-recap/skills/video-understanding/SKILL.md +29 -4
  202. package/lib/video-recap/skills/video-understanding/references/data-schema.md +5 -22
  203. package/lib/video-recap/skills/video-understanding/scripts/agent_text.py +24 -121
  204. package/lib/video-recap/skills/video-understanding/scripts/asr.py +11 -5
  205. package/lib/video-recap/skills/video-understanding/scripts/asr_timing_evidence.py +15 -24
  206. package/lib/video-recap/skills/video-understanding/scripts/briefing/builder.py +59 -25
  207. package/lib/video-recap/skills/video-understanding/scripts/briefing/context.py +39 -3
  208. package/lib/video-recap/skills/video-understanding/scripts/briefing/inputs.py +15 -27
  209. package/lib/video-recap/skills/video-understanding/scripts/briefing/timeline.py +136 -37
  210. package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +121 -37
  211. package/lib/video-recap/skills/video-understanding/scripts/detect.py +118 -16
  212. package/lib/video-recap/skills/video-understanding/scripts/index_normalize.py +359 -0
  213. package/lib/video-recap/skills/video-understanding/scripts/lib.py +62 -21
  214. package/lib/video-recap/skills/video-understanding/scripts/storyboard.py +181 -51
  215. package/lib/video-recap/skills/video-understanding/scripts/timeline_fusion.py +0 -26
  216. package/lib/video-recap/skills/video-understanding/scripts/understanding_brief.py +37 -14
  217. package/lib/video-recap/skills/video-understanding/scripts/understanding_cache.py +40 -32
  218. package/lib/video-recap/skills/video-understanding/scripts/understanding_runner.py +100 -127
  219. package/lib/video-recap/skills/video-understanding/scripts/understanding_storyboard.py +182 -30
  220. package/lib/video-recap/skills/video-understanding/scripts/vlm.py +30 -27
  221. package/lib/video-recap/skills/video-voiceover/SKILL.md +19 -12
  222. package/lib/video-recap/skills/video-voiceover/references/index-tts.md +3 -3
  223. package/lib/video-recap/skills/video-voiceover/scripts/approved_text_policy.py +3 -1
  224. package/lib/video-recap/skills/video-voiceover/scripts/dub.py +60 -135
  225. package/lib/video-recap/skills/video-voiceover/scripts/lib.py +9 -34
  226. package/lib/video-recap/skills/video-voiceover/scripts/providers/fish_audio.py +6 -1
  227. package/lib/video-recap/skills/video-voiceover/scripts/tts_audio.py +64 -1
  228. package/lib/video-recap/skills/video-voiceover/scripts/tts_cache.py +99 -0
  229. package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +177 -200
  230. package/package.json +45 -45
  231. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_accord_five.webp +0 -0
  232. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/public_day15.webp +0 -0
  233. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/household/li_jiaoer.webp +0 -0
  234. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +0 -1494
  235. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/assets.js +0 -147
  236. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +0 -7470
  237. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +0 -13066
  238. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +0 -32
  239. package/lib/novel-to-game/examples/jin-ping-mei/qa/playable-model.json +0 -99
  240. package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +0 -152
  241. package/lib/video-recap/skills/video-assemble/references/foreground-compose.md +0 -118
  242. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_combination_segment.json +0 -84
  243. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_combination_video_material.json +0 -98
  244. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_draft.json +0 -204
  245. package/lib/video-recap/skills/video-assemble/references/pair-media.md +0 -74
  246. package/lib/video-recap/skills/video-assemble/scripts/compose_foreground.py +0 -293
  247. package/lib/video-recap/skills/video-assemble/scripts/pair_media.py +0 -216
  248. package/lib/video-recap/skills/video-recap/references/shift-left-qc-schema.md +0 -23
  249. package/lib/video-recap/skills/video-recap/scripts/mimo_qc.py +0 -33
  250. package/lib/video-recap/skills/video-recap/scripts/qc/__init__.py +0 -1
  251. package/lib/video-recap/skills/video-recap/scripts/qc/mimo_client.py +0 -13
  252. package/lib/video-recap/skills/video-recap/scripts/qc/mimo_contract.py +0 -9
  253. package/lib/video-recap/skills/video-recap/scripts/qc/mimo_evidence.py +0 -287
  254. package/lib/video-recap/skills/video-recap/scripts/qc/mimo_observations.py +0 -175
  255. package/lib/video-recap/skills/video-recap/scripts/qc/mimo_payload.py +0 -206
  256. package/lib/video-recap/skills/video-recap/scripts/qc/mimo_report.py +0 -318
  257. package/lib/video-recap/skills/video-recap/scripts/qc/mimo_runner.py +0 -130
  258. package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +0 -320
  259. package/lib/video-recap/skills/video-script/scripts/timeline_fusion.py +0 -108
  260. package/lib/video-recap/skills/video-understanding/scripts/brief.py +0 -9
  261. package/lib/video-recap/skills/video-understanding/scripts/deslop_qc.py +0 -211
  262. package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +0 -707
  263. package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +0 -143
  264. /package/lib/video-recap/skills/video-cut/scripts/{narration_mapping.py → cut_qc.py} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"production-prompts.d.ts","sourceRoot":"","sources":["../../../src/client/production-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAqBrF,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,sBAAsB,EAClC,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,SAAS,sBAAsB,EAAE,GAC5C,MAAM,CAuBR;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,sBAAsB,EAClC,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,GACtE,MAAM,CAgBR;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,sBAAsB,EAClC,GAAG,EAAE,aAAa,EAClB,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,MAAM,CAoBR"}
1
+ {"version":3,"file":"production-prompts.d.ts","sourceRoot":"","sources":["../../../src/client/production-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAqBrF,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,sBAAsB,EAClC,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,SAAS,sBAAsB,EAAE,GAC5C,MAAM,CAuBR;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,sBAAsB,EAClC,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,GACtE,MAAM,CAgBR;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,sBAAsB,EAClC,GAAG,EAAE,aAAa,EAClB,cAAc,EAAE,SAAS;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C,EAAE,GACF,MAAM,CAoBR"}
@@ -29,6 +29,9 @@ export interface ProductionJob {
29
29
  }
30
30
  export interface ProductionSequenceItem {
31
31
  readonly shotId: string;
32
+ /** Creator-chosen source for this cut; absent keeps automatic video-first resolution. */
33
+ readonly sourceVersionId?: string | undefined;
34
+ /** Resolved source used for preview and composition; recomputed as media changes. */
32
35
  readonly versionId?: string | undefined;
33
36
  }
34
37
  export interface CanvasPoint {
@@ -81,11 +84,13 @@ export declare function referencesForTarget(targetId: string, production: {
81
84
  readonly references: readonly string[];
82
85
  }[];
83
86
  }, versions: readonly ProductionMediaVersion[], selections: Readonly<Record<string, string>>, libraryVersions?: readonly ProductionMediaVersion[], manualReferences?: Readonly<Record<string, readonly string[]>>): ProductionMediaVersion[];
87
+ export declare function mediaBelongsToEpisode(path: string | undefined, episodeDirectory: string): boolean;
88
+ export declare function sequenceSourceEligible(shotId: string, version: ProductionMediaVersion): boolean;
84
89
  export declare function queuedItemForJob(jobId: string, queue: readonly ProductionQueueEntry[]): ProductionQueueEntry | undefined;
85
90
  export declare function activeProductionJobId(jobs: readonly ProductionJob[], queue: readonly ProductionQueueEntry[], sessionRunning: boolean): string | undefined;
86
91
  /** Reconcile the lightweight Session projection against DSH Queue/Turn state and real workspace outputs. */
87
92
  export declare function reconcileProductionJobs(jobs: readonly ProductionJob[], queue: readonly ProductionQueueEntry[], sessionRunning: boolean, versions: readonly ProductionMediaVersion[]): ProductionJob[];
88
- export declare function reconcileSequence(shotIds: readonly string[], current: readonly ProductionSequenceItem[], versions: readonly ProductionMediaVersion[], selections: Readonly<Record<string, string>>): ProductionSequenceItem[];
89
- export declare function sequenceIssues(sequence: readonly ProductionSequenceItem[], versions: readonly ProductionMediaVersion[]): string[];
93
+ export declare function reconcileSequence(shotIds: readonly string[], current: readonly ProductionSequenceItem[], versions: readonly ProductionMediaVersion[], selections: Readonly<Record<string, string>>, episodeDirectory?: string): ProductionSequenceItem[];
94
+ export declare function sequenceIssues(sequence: readonly ProductionSequenceItem[], versions: readonly ProductionMediaVersion[], episodeDirectory?: string): string[];
90
95
  export declare function reorderSequence(sequence: readonly ProductionSequenceItem[], source: number, target: number): ProductionSequenceItem[];
91
96
  //# sourceMappingURL=production-runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"production-runtime.d.ts","sourceRoot":"","sources":["../../../src/client/production-runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"production-runtime.d.ts","sourceRoot":"","sources":["../../../src/client/production-runtime.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"drama-adapters.d.ts","sourceRoot":"","sources":["../../src/drama-adapters.ts"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,iGAAiG;AACjG,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wFAAwF;IACxF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,4EAA4E;AAC5E,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AAIxE,eAAO,MAAM,cAAc,EAAE,SAAS,gBAAgB,EA+CrD,CAAC;AAQF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,aAAa,SAAW,GAAG,0BAA0B,CAKpJ;AAeD,gGAAgG;AAChG,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAY,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAOlM;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5G,OAAO,CAAC,0BAA0B,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAAC,CAiBhE;AAED,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,kBAAkB,EAAE,CAK/F;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
1
+ {"version":3,"file":"drama-adapters.d.ts","sourceRoot":"","sources":["../../src/drama-adapters.ts"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,iGAAiG;AACjG,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wFAAwF;IACxF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,4EAA4E;AAC5E,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AAIxE,eAAO,MAAM,cAAc,EAAE,SAAS,gBAAgB,EA+CrD,CAAC;AAQF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,aAAa,SAAW,GAAG,0BAA0B,CAKpJ;AAeD,gGAAgG;AAChG,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAY,GAAG;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9G,CAOA;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5G,OAAO,CAAC,0BAA0B,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAAC,CAiBhE;AAED,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,kBAAkB,EAAE,CAK/F;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"skill-provider.d.ts","sourceRoot":"","sources":["../../src/skill-provider.ts"],"names":[],"mappings":"AAIA,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAuNhC,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAuBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAa7D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIrE;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAKhD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAK9C;AAED,wBAAgB,2BAA2B,IAAI,MAAM,CAKpD;AAuDD,wBAAgB,0BAA0B,CAAC,SAAS,SAA4B,GAAG,aAAa,CAE/F;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,SAA0B,GAAG,MAAM,CAM/G;AAED,wBAAgB,wBAAwB,CAAC,SAAS,SAA0B,GAAG,aAAa,CAE3F;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjF;AAED,wBAAgB,8BAA8B,CAAC,SAAS,SAAgC,GAAG,aAAa,CAEvG;AAED,wBAAgB,0BAA0B,IAAI,MAAM,CAKnD;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,6BAA6B,CAAC,SAAS,SAA+B,GAAG,aAAa,CAErG"}
1
+ {"version":3,"file":"skill-provider.d.ts","sourceRoot":"","sources":["../../src/skill-provider.ts"],"names":[],"mappings":"AAIA,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAwNhC,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAuBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAa7D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIrE;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAKhD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAK9C;AAED,wBAAgB,2BAA2B,IAAI,MAAM,CAKpD;AAuDD,wBAAgB,0BAA0B,CAAC,SAAS,SAA4B,GAAG,aAAa,CAE/F;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,SAA0B,GAAG,MAAM,CAM/G;AAED,wBAAgB,wBAAwB,CAAC,SAAS,SAA0B,GAAG,aAAa,CAE3F;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjF;AAED,wBAAgB,8BAA8B,CAAC,SAAS,SAAgC,GAAG,aAAa,CAEvG;AAED,wBAAgB,0BAA0B,IAAI,MAAM,CAKnD;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,wBAAgB,6BAA6B,CAAC,SAAS,SAA+B,GAAG,aAAa,CAErG"}
@@ -1 +1 @@
1
- {"version":3,"file":"video-project.d.ts","sourceRoot":"","sources":["../../src/video-project.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAE9C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;CACxE;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAChE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACrD;AAoDD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKjE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWtD;AA0BD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,kBAAkB,EAAE,EACpC,QAAQ,GAAE;IACR,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACxB,GACL,mBAAmB,CA6DrB"}
1
+ {"version":3,"file":"video-project.d.ts","sourceRoot":"","sources":["../../src/video-project.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAE9C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;CACxE;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAChE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACrD;AA0DD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKjE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWtD;AA0BD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,kBAAkB,EAAE,EACpC,QAAQ,GAAE;IACR,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACxB,GACL,mBAAmB,CA6DrB"}
@@ -10,6 +10,112 @@ All notable changes to this project are documented here.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.6.1] - 2026-10-03
14
+
15
+ 升级前先从脚本与环境里删掉本版移除的参数和环境变量(见 Removed,如 `--mimo-qc`、`validate.py --preserve-approved-text`、`cut.py --clip-padding`、`dashboard_server.py --host` 和 19 个调参变量),读 `golden_eval.json`、`mimo_qc.json`、`preflight_qc.json` 的脚本按 Removed 改读 `final_qc.json` 或对应产物。
16
+ full 模式下超预算的解说稿和任何模式下未按 `start` 排序的解说稿现在 lint 失败,要改稿后重跑;默认开启的 `TTS_MIN_SPEECH_RATE` 会让语速过慢的段失败,可调低或设为 `0`。
17
+ 旧 work_dir 续跑会重剪 `edited_source.mp4`、重新合成 TTS、重建故事索引各一次,缺 ASR 时间证据的还会重跑 ASR。
18
+ 虽是补丁号,本版改了契约:校验、导出与清单读取不再静默改写或兼容旧形状,而是报错并写明改法(见 Changed),没有读取方的产物与开关一并删除。
19
+
20
+ ### Added
21
+
22
+ - **缺 drawtext 时,带画面文字叠加的运行在配音前停下。** 旁白 `visual_overlays`(`top_title` / `inline_label_or_callout`)用 ffmpeg `drawtext` 渲染,Homebrew 自带的 ffmpeg 没有它,以前要跑完理解、写稿和 TTS 才在最后渲染失败。现在 recap 在评审与 TTS 之前检查(source 模式检查已有的 `visual_overlays.json`),`assemble.py` 在渲染前再查一次,报错写明删掉叠加或换带 drawtext 的 ffmpeg;叠加是写稿时明确加的内容,所以不做静默跳过。`--doctor` 新增 `ffmpeg_drawtext_filter` / `visual_overlays_ready` 和对应 warning。
23
+ - **新增按需技能 video-reference:把成片拆成可复用的制作参考。** `reference.py measure` 用一次 ffmpeg(`scdet` 逐帧分数 + `ebur128`)测镜头切点、镜长分布与响度,按成片 `{size, mtime_ns}` 缓存;切点只认孤立峰(固定阈值会在暗场漏掉硬切、在运动镜头里误报),被压下的候选由 `reference.py frames --review` 逐帧拼图给 Agent 复核,复核结果写进 `labels.cut_fixes`,导出物用 `cut_detection` 记录检测参数与增删数;Agent 在 `reference_breakdown.json` 标注音轨归属与叙事段落,并分开写原片事实与可迁移方法;`check` 用 R1–R8 机械分离两者(封闭 schema、事实锚点、方法证据、target 只写测量路径、实体名/台词引文/绝对时间/路径泄漏扫描、五维覆盖),`export` 零 error 时才写不含原片事实的 `production_reference.json`。写稿 Agent 只在 work_dir 有这个文件时阅读,并可在 `recap_story_plan.json` 写可选的 `reference_methods`。不调用 MiMo,不进默认生产路径,recap 不加参数,不新增 QC。
24
+ - **制作参考可以登记进资源库并经 `--project` 绑定。** 资源库新增模板 kind `production_reference`:版本目录里放导出的 `production_reference.json`,`template.json` 的 `params` 恰好是 `{"reference": {"path": "production_reference.json"}}`;`library.py check` 核对导出物 schema、methods 与五维枚举,任何层级出现 `source_facts`/`labels`/`evidence`/`entities`/`statement`/`from`/`path` 键都报错(与导出复扫同一组键)。项目 `bindings.production_reference` 只接受 adopted 版本,recap 在第一次暂停前把带 `written_by` 与 `template {id, version}` 的副本写进 `work_dir`,暂停提示多一行说明,`resource_lock.json` 记下 `id@vN`;只绑定参考时不探测成片画布,不加门禁,没有脚本读它。`work_dir` 已有不是 `--project` 写的同名文件时,内容与导出物相同就原样保留,不同则运行停止;解除绑定后只删自己写的副本。示例库加一份合成的 `demo-pacing@v1`。
25
+ - **新增 `TTS_MIN_SPEECH_RATE`(默认 2.5 字/秒,`0` 关闭)。** 段音频超过按这个语速读完全文再加停顿与首尾静音的上限时视为 TTS 幻读,按失败重试、不写缓存(见 Fixed);默认开启的影响见 Changed。
26
+ - **新增 `LOUDNESS_LIMITER_MAX_DB`(默认 6 dB,`0` 关闭限幅)。** 成片响度的真峰值限幅器最多削这么多,超出部分改为下调目标响度(见 Changed)。
27
+ - **新增 `understand.py --edited-storyboard-only`。** 只按 `clip_plan_validated.json` 生成剪后故事板,与 `--brief-only` 互斥;recap 多视频第二阶段会调用它(见 Fixed)。
28
+ - **guohuo-60s 样例新增 `remotion/sync_overlay.py` 与 `npm run typecheck`。** 前者从运行的 `subtitles.srt` 重建 Remotion 透明层数据并列出越过母版结尾的元素(见 Fixed)。
29
+ - **cut 被阻断的边界会给出最近的安全边界。** `unsafe_clip_sentence_boundary` 的边界在 `qc.boundary_status.sentence_checks`(和 `qc.blocking`)里多一个 `nearest_safe: {"before", "after"}`:前后 5 秒内用同一门禁复核过的最近时间,报的是帧对齐后的落点、已在原片帧网格上,对齐后仍安全才报(原片秒,带 `reason` 与 `delta`),没有就是 `null`;Agent 按它改 `clip_plan.json` 的入/出点,不必再猜。重跑时切镜头避让(`SCENE_CUT_SNAP`,默认开)也不会再把建议的边界拉回讲话内,见 Fixed。
30
+
31
+ ### Changed
32
+
33
+ - **ffmpeg 缺 libass 时,默认烧录字幕降级为外挂 `.srt`,不再在开跑前退出。** Homebrew 自带的 ffmpeg 已去掉 libass,以前默认运行一律停在预检。现在只有显式要求烧录(`--burn-subtitles`,或设置了取真值的 `BURN_SUBTITLES`)时才在开跑前报错;默认运行照常完成,成片不带字幕,`subtitles.srt` 复制到成片旁(`recap_<stem>.srt`,烧录运行会删掉旧的同名文件);显式 `--no-burn-subtitles` 的运行同样输出这个外挂字幕,没有任何字幕条目的运行(如 source-mix 不带用户字幕)既不写空 `.srt` 也不记警告,留白里的 `「」` 原声对白在 work_dir 有 `user_subtitles.*` 时照常写进 `.srt`、`timeline.json` 和剪映草稿;原本由遮罩触发的 `「」` 对白随遮罩一起关闭(原片硬字幕可见)。降级是机器可读的:`visual_qc.json` 与 `assembly_manifest.json` 的 `warnings` 各有一条 `subtitle_burn_degraded`(`assembly_manifest.json` 另有 `subtitle_sidecar` 路径,`assembly_settings.subtitle_burn_degraded` 记原因),`final_qc.json` 在 `metadata.warnings` 转载它(仅当 `assembly_manifest.json` 的 `final_output` 就是本次成片,dub 运行不会带上同一 work_dir 里旧运行的警告),`final_qc.py` 的摘要多出 `warnings` 列表,recap 完成时打印警告和 `.srt` 路径。降级不阻断、不改 `ok` / `blocker_count`。原字幕遮罩仍然只在烧录时生效,降级时 `mask.trigger` 记为 `burn_subtitles_degraded`;显式 `--no-burn-subtitles` 时记 `burn_subtitles_disabled`。`--doctor` 的 `system_tools.subtitle_delivery` 给出 `burned` / `sidecar_srt` / `fails_explicit_burn` / `unavailable`(找不到 ffmpeg)。
34
+ - **full 模式校验不再静默改写解说稿(破坏性变更)。** `validate.py --mode full` 不再截短超预算文本、丢弃过短段、合并相似相邻段、补句末标点或按时间重排,也不再丢掉白名单之外的字段;它和 cut_output 一样只做 lint,再用同一套声音归属算法(原声对白区间减去安静窗口)回写 `overlaps_speech`,因此 full 模式的 `overlaps_speech` 和随之的原声闪避可能与以前不同。字数超过该时间窗推荐字数(先扣约 0.45 秒 TTS 首尾静音:每块是一次 TTS 合成,自带这段静音,取 MiMo 实测中位数)1.25 倍的段现在是 `over_budget` error(以前会被静默截短或丢弃),`narration_lint.json` 写明段号、时间窗、`budget_chars`、`limit_chars`、`actual_chars`、`over_chars` 与 `tts_overhead_seconds`,Agent 改稿后重跑;cut_output 的超预算仍是 warning,估计朗读时长同样计入这段静音。扣掉静音后 `slot_too_short` warning 在默认配置下对约 1.9 秒以下的窗口出现(以前约 1.4 秒)。brief 里每个窗口标的字数还没扣这一项,2–3 秒的短窗口要比它少写一两个字。未按 `start` 排序的段在所有模式下都报 `out_of_order` error。`validate.py` 的 `--preserve-approved-text` 已删除(见 Removed);voiceover 默认也不再缩稿,见下方 Fixed 的“默认路径不再截短旁白”。
35
+ - **TTS 段时长超过 `TTS_MIN_SPEECH_RATE` 推出的上限时判为失败,默认开启。** 以前能通过的慢速旁白或慢速克隆声线现在会被重试,重试用尽则该段失败;旁白本来就慢时把 `TTS_MIN_SPEECH_RATE` 调低,或设为 `0` 关闭(判定细节见 Fixed)。
36
+ - **暂停时的续跑命令改为回显原命令。** 不再由 `recap_timeline` 按 flag 逐个重组,而是回显用户输入的参数:保留原写法(如 `--style=悬疑`、`--project` 写的是目录),视频与 `--work-dir` / `--output-dir` / `--voice-ref` / `--material-library-dir` / `--project` 等路径转为绝对路径,补上 `--work-dir` 与来自 `EDIT_MODE` / `TARGET_DURATION` / `TTS_PROVIDER` / `VOICE_REF` / `SUBTITLE_Y_*` 的设置。`recap_run_manifest.json` 新增 `argv`,记录这条续跑参数。续跑命令从任何目录都能用。
37
+ - **`final_qc.json` 改为最小报告形状(`schema_version: 2`),QC 只收敛到这一份报告。** 通用 QC 契约 `scripts/qc_contract.py` 与 `references/shift-left-qc-schema.md` 删除,字段说明并入 `data-schema.md` 的 `final_qc.json` 一节。报告去掉恒为 `post_render` 的 `stage`;每条 finding 只剩 `code`、`message`、`blocking`、`evidence`、`next_action`,去掉 `finding_id` / `severity` / `confidence` / `sample_policy` / `model_used` / `rule_id` / `decision_reason` / `location` / `category` / `source` 等恒定或重复字段。`ok`、`blocker_count`、`finding_count` 与 `--require-final-qc` 的判定不变。`metadata.probe` 只保留检查用到的流与容器字段,原片带来的容器标签(comment、purl 里的 URL 等)不再写进报告;`metadata.artifacts` 对 `assembly_qc.json` / `visual_qc.json` 改为记录它们的 `verdict` / `blocking` / `blocking_codes`。
38
+ - **`final_qc` 不再把 assembly / visual QC 的阻断码转写成自己的 blocker。** 这两份 QC 阻断时 video-assemble 已经非零退出,流水线走不到 final_qc;只有在失败的 work_dir 上手动跑 `final_qc.py` 时,结果才会不同(这时直接看 `assembly_qc.json` / `visual_qc.json`)。
39
+ - **cut 账本 `recap_phase.json` 只记 `clip_plan_identity`。** 写稿时剪辑计划的身份是它唯一被读取的字段;`edited_source_rendered`、`narration_written`、`multi_source`、`audio_mode`、`audio_stream_index` 不再写入,不带解说的 cut 运行也不再写账本。旧账本里多出的字段在下次写入时丢弃。
40
+ - **素材库按 `material_id` 直接恢复。** recap 把保存时用的 `material_id` 传给恢复,不再扫描 `materials/*/material.json` 按源路径查找;手工改过名的素材目录因此不会再被找到,需改回原名或重新沉淀。素材白名单去掉从未有生产者的 `reference_profile.json` / `reference_match_report.json`。
41
+ - **剪映导出只接受 `schema_version: 2` 的 `timeline.json`。** v0.4.0 起流水线就只写 v2;0.3 时代的 v1 时间线不再静默迁移,`export_jianying.py` 直接报 `unsupported timeline schema_version 1`,把版本号改成 2 即可导出。
42
+ - **`subtitle_track.json` 的 binding 不再容忍 `sha256` / `edit_sha256`。** 这两个摘要键按未知字段拒绝(`unknown field(s)`),删掉即可;没有任何已发布版本写过带这两个键的字幕轨。
43
+ - **assemble 的时间线溯源只认 `clip_plan_validated.json`。** `clip_plan.json` 比它新(改了计划却没重新剪)时,assemble 在渲染前报 `clip_plan_validated.json 已过期`,不再改用原始计划拼出与画面不符的 `timeline.json` 和重映射字幕;重新剪辑即可。没有 validated 计划时按整片处理,散落的 `clip_plan.json` 不再参与字幕重映射。
44
+ - **voiceover 的参考音频每次运行只转码一次,并按参数传给各段。** 有段落需要合成时才转码,全部命中缓存的重跑仍不调用 ffmpeg;配音期间参考音频被改动会报 `参考音频在配音期间被修改`,不再静默沿用旧快照。`tts_meta.json` 与 TTS 段缓存键不变。
45
+ - **cut 与 understanding 的脚本模块收窄导出。** `cut.py` 只导出 `main`,video-understanding 删除再导出用的 `brief.py`;video-cut 的 `narration_mapping.py` 改名 `cut_qc.py`;进程内导入这些名字的脚本需改从所属模块导入。cut 计划里源区间重叠的报错结尾改为 `split or remove duplicate source footage in the clip plan`。命令行、参数与产物不变。
46
+ - **video-recap 的 dashboard 与资源库模块归入子包。** `dashboard_{data,io,runs,templates}.py` 移到 `scripts/dashboard/`,`project_binding.py`、`resource_lock.py` 移到 `scripts/resources/{project_binding,lock}.py`;文件身份与 id 函数从 `materials.py`、ffmpeg 字幕滤镜探测从 `doctor.py` 移进 `lib.py`,`TTS_PROVIDERS` 只剩一份。进程内导入这些模块的脚本需改从新路径导入;入口脚本(`recap.py`、`dashboard_server.py`、`library.py`、`doctor.py` 等)、产物与默认值不变。
47
+ - **ASR 缓存缺少 `asr_timing_evidence.json` 时重跑 ASR。** video-understanding 删除 `LEGACY_UNVERIFIED` 状态:sidecar 被删掉、或重跑 ASR 时被 Ctrl-C 中断的 work_dir 不再离线复用旧转写,旧版本写下的 `LEGACY_UNVERIFIED` sidecar 也视为未命中。VLM prompt 模板缺失时直接报错,不再静默换用一份已过时的两段式兜底 prompt。
48
+ - **video-cut 的 `--sources-manifest` 只接受一种形状。** 清单必须是 `{"sources": [{"source_id", "source_path"[, "duration", "source_work_dir"]}]}`(即 recap 写出的 `multi_source_manifest.json`);裸数组、以 `source_id` 为键的映射,以及 `id` / `name`、`path` / `video_path` / `video` / `file`、`duration_seconds` / `source_duration` 等别名一律报错,报错写明期望形状。多源 `clip_plan.json` 的片段必须写 `source_id`,不再把 `id` 当来源;顶层目标时长只认 `target_duration`,不再认 `target_duration_seconds`。形状写进了 video-cut SKILL.md。
49
+ - **多源 cut 只把计划里相邻的同源片段当作无损连接。** 按来源分组吸附时,计划中间夹着别的来源片段的 `a:0–2` 与 `a:2–4` 以前被判为 `continuous_source_join`,讲话中间的切点因此放行;现在只有计划里相邻(`clip_id` 连续)的同源片段才算连续,这类边界照常阻断。
50
+ - **成片响度改为恒定增益加真峰值限幅,交付文件真峰值仍超标时阻断。** 以前测得的真峰值放不下所需增益时,ffmpeg 会改用动态归一(逐 3 秒自动增益,会压扁混音),`loudness_mode` 却仍记 `two_pass_linear`。现在混音先整体增益,再经 4 倍过采样的 lookahead 限幅器把真峰值压到目标下 1 dB,最后按限幅后信号的测量做线性 loudnorm 补足剩余响度。限幅器最多削 `LOUDNESS_LIMITER_MAX_DB`(默认 6 dB),超过时只把余下的增益下调目标响度(`0` 关闭限幅,回到只下调目标);只在动态模式生效的 LRA 目标放宽到测得值。真峰值目标针对交付的 AAC 文件(192k 编码会把真峰值抬高 0.3–1.4 dB):首次渲染瞄准 -1.5 dBTP,渲染后解码成片测量(loudnorm 与 ebur128 取较高的真峰值);仍超过 -1 dBTP 时把编码前目标再降“超出量 + 0.1 dB”,只重编码音频、画面流复制,最多两次,仍超出则以新阻断码 `delivered_true_peak_over_target` 阻断。限幅器削满 6 dB 的混音比 `TARGET_LUFS` 低约 0.5 LU,作为编码余量。长片的组装多花两遍音频解码的时间,需要纠正时再加一遍音频编码。`assembly_qc.json` 新增 `loudnorm_final_pass`(ffmpeg 报告的 `normalization_type`、实际目标与 `gain_capped_db`、编码前的输出响度与真峰值、`peak_limiter`:先增益、上限、需要与实际削去的 dB,以及 `delivered`:成片实测的 `integrated` / `true_peak`、最终的编码前目标 `peak_target_dbtp` 与纠正次数 `corrections`);`loudness_mode` 新增 `two_pass_linear_peak_limited`,仍落到动态模式时记 `two_pass_dynamic`。source-mix 的单遍 loudnorm 同样按交付文件纠正。
51
+ - **ASR 读不到音频文件时报错。** 不再当作空转写继续。
52
+ - **没有 MiMo key 且理解缓存失效时运行停下。** `asr_result.json` 已有转写而 ASR 缓存未命中时停下并保留转写,VLM 缓存未命中时在 ASR 之前退出;以前会把转写写成 `[]` 后报成功。恢复办法见 Fixed。
53
+ - **报错与 brief 里给人看的段号、场景号、块号统一从 1 数。** 此前 `no_safe_fit` 的段号、validate 的 lint 摘要、brief 的 `### Fusion scene` 与 `ASR chunk` 场景号从 0 数;解析这些文字的脚本要减 1 对回 JSON。`narration_lint.json` 的 `index`、`narration_review.json` 的 `segment`、`timeline_fusion.json` / `asr_writing_chunks.json` 的 `scene_id` 仍从 0 数(细节见 Fixed)。
54
+
55
+ ### Removed
56
+
57
+ - **`validate.py` 删除 `--preserve-approved-text`。** 传入即报 unrecognized arguments,recap 不再把它传给校验;`recap.py --preserve-approved-text` 照旧传给 voiceover。
58
+ - **删除 MiMo 多模态建议型 QC。** `recap.py` 不再接受 `--mimo-qc` / `--mimo-qc-refresh`(传入即报 unrecognized arguments),`MIMO_QC` / `MIMO_QC_REFRESH` / `MIMO_QC_MODEL` 环境变量不再被读取;入口 `mimo_qc.py` 与 `scripts/qc/` 子包删除,流水线不再写 `mimo_qc.json`。`final_qc.json` 的 `metadata.artifacts` 不再汇总 `mimo_qc.json`,dashboard 的 QC 页去掉「MiMo 复核」卡片;旧 work_dir 里残留的 `mimo_qc.json` 不再被任何环节读取。确定性的 `final_qc.json` 与解说评审不受影响。
59
+ - **`golden_eval.json` 并入 `final_qc.json`。** 渲染后只写 `final_qc.json`,不再写 `golden_eval.json`;没有 golden fixture 时它只是复述 `final_qc.ok`,而流水线从不传 fixture。`--require-final-qc` 只检查 `final_qc.json` 的摘要(`ok: true` 且整数 `blocker_count: 0`),判定结果不变;`final_qc.py` 去掉 `--golden-fixture` / `--only`(传入即报错),dashboard 的 QC 页去掉「黄金评估」卡片;旧 work_dir 里残留的 `golden_eval.json` 不再被读取。
60
+ - **删除 dub 的手动侧 CLI 与 `dub_review.json`。** `dub.py` 只剩编排入口调用的 `--stage prepare|render`:`--stage lint|review` 与 `--print-schema` 传入即报错,渲染不再写没有任何读取方的 `dub_review.json`(它只是把 `dub_lint.json` 换个形状重写)。`dub_lint.json` 照常在语音克隆前写出,lint 非 PASS 仍中止。dub 翻译规则只保留在 `dub_brief.md` 一处,brief 同时写出目标语速(约 5 字/秒)和 lint 警告阈值(7 字/秒)。
61
+ - **`--doctor` 去掉能力清单。** `recap.py --doctor --json` 不再输出 `capability_menu` 键,人读输出不再有 `[capability menu]` 分组段;`ok`、`checks`、`failures` 不变。清单里独有的两条信息改进 `warnings`:选中的 mimo-tts / fish-audio 未配置密钥时提示要设的变量,MiMo VLM 未配置时提示设 `MIMO_VIDEO_API_KEY` 或 `MIMO_API_KEY`;缺 libass 的 warning 说明默认运行改为交付外挂 `.srt`、显式 `--burn-subtitles` 会失败。
62
+ - **`dashboard_server.py` 删除 `--host`。** 服务固定绑定 127.0.0.1(原来也只接受回环地址),传 `--host` 即报 unrecognized arguments。
63
+ - **删除逐阶段账本 `preflight_qc.json`。** 流水线不再在 `pre_tts` / `post_tts` / `pre_assemble` / `post_cut` / `post_render` 写它:它不含 finding,内容是 `tts_meta.json`、`assembly_manifest.json`、cut QC 的拷贝。`final_qc.json` 的 `metadata.artifacts` 不再列出它;旧 work_dir 里残留的文件不再被读取(损坏的也不再让 narration 运行在解说评审之后崩溃),也不会被清理。
64
+ - **解说评审只产出 verdict 与 findings。** `review.py` 的 prompt 不再要求 16 维 1-5 分 scorecard 和 hook 候选、留存风险、最高回报改动、信息增量、口语改写、断言来源六个建议列表,`narration_review.json` / `.md` 也不再含这些键与小节;它们从不改变 verdict、不进门禁,也没有任何环节读取。评审 prompt 不再嵌入 deslop 报告(其 blocker 在评审前已是 lint error)。模型返回的 `OK` 记为 `PASS`,verdict 词表只剩 `PASS|REVISE|FAIL`。严格评审的门禁不变,仍只看 `findings` 里的 error 和解析失败。
65
+ - **评审、video-understanding 与校验不再写 `grounding_qc.json`、`silence_periods.qc.json`、`deslop_qc.json`。** recap 成片后也不再打印「🧭 Grounding QC」一行(评审关闭或失败时它会打印旧运行留下的文件);每个安静窗口的判定依据仍在 `silence_periods.json`,去 AI 味报告保留在 `narration_lint.json` 的 `deslop_qc` 字段。
66
+ - **删除剪映 timeline-v2 手写扩展面。** `timeline.json` 不再支持变速、倒放、透明度 / 旋转 / 翻转、转场、蒙版、LUT、绿幕复合草稿、富文本样式(`style` / `words` / `style_presets`)以及 `sound` / `sticker` / `text_template` / `video_effect` / `face_effect` 资源轨与 `resource_packages` 离线资源包;导出遇到这些字段或轨道会明确报错,不再静默生成草稿。`timeline.build_timeline` 去掉 `resource_packages` / `style_presets` / `extra_tracks` 参数。流水线从不写这些字段,默认的 `timeline.json` 与导出的草稿(视频、旁白、BGM、字幕、包装图层的 `scale` / `position`)不变;这类效果请在剪映里直接加。
67
+ - **删除 assemble 的独立命令 `pair_media.py` 与 `compose_foreground.py`。** 两者只能手写计划 JSON 单独调用,编排器从不调用:前者把独立画面与已采用音轨按流复制配对成 `paired.mp4`,后者把调用方渲染的 RGBA 序列(可选片尾卡)叠到锁定母版。对应的 `references/pair-media.md`、`references/foreground-compose.md` 一并删除;动画或透明包装改由项目级渲染器自己合成到锁定母版,整片不动的包装继续用 `packaging_layers.json`。`--audio-mode adopted-packet-copy` 与显式混音用到的画面帧钟、AAC 包区间检查移入 `scripts/adoption/av_clock.py`,判定不变,只是三条报错不再以 “Pairing” 开头。
68
+ - **删除走不到的 ducking 模式与 `tts_dynamic_params` 开关。** video-assemble 的混音只保留默认的 fixed 包络:`sidechaincompress` / `none` 两种模式以及 `ducking_mode`、`ducking_threshold` / `ducking_ratio` / `ducking_attack` / `ducking_release` / `ducking_level_sc` / `ducking_makeup` 配置键删除(它们没有任何环境变量或参数能打开),`assembly_manifest.json` 的 `assembly_settings.audio_mix` 不再写这七个键。video-voiceover 删除恒为开启的 `tts_dynamic_params`,MiMo 与 Fish 段落总是按内容计算语速/音高。渲染结果不变;TTS 段缓存的设置载荷少了这个键,已有 work_dir 重跑时会重新合成一次 TTS。
69
+ - **assemble 产物不再镜像 QC 结论,删掉无效的 `SOURCE_VIDEO`。** `assembly_manifest.json` 去掉从 `assembly_qc.json` 抄来的 `qc_verdict` / `qc_blocking_codes` / `qc_loudness_mode` / `qc_loudnorm_measurement` / `audio_operations` / `adopted_audio`(`qc_path` 仍指向它),以及顶层和每段的 `segment_audio_schema_version`;`assembly_qc.json` 去掉恒等的 `release_gate` 块,`visual_qc` 只保留 `verdict` 与 `blocking_codes`,视觉细节请读 `visual_qc.json`。`subtitle_track_validation.json` 不再写 `validation_schema` / `projector_version`。环境变量 `SOURCE_VIDEO` 不再被读取(`assemble.py` 一直用 `--source-video` 覆盖它)。QC 判定、渲染结果和缓存都不变。
70
+ - **删除 19 个未文档化的调参环境变量和旧版旁白入场延迟。** video-assemble 不再读取 `FADE_MS`、`DUCKING_ORIG_VOLUME`、`TARGET_TRUE_PEAK`、`TARGET_LRA`、`FINAL_LIMITER_PEAK`、`NARRATION_RUN_GAP_SECONDS`、`NARRATION_TIGHT_PAUSE_SECONDS`、`NARRATION_MAX_PULL_SECONDS`、`SUBTITLE_MARGIN_L`、`SUBTITLE_MARGIN_R`、`NARRATION_TIGHTEN`、`NARRATION_DELAY_SECONDS`;video-voiceover 不再读取 `MIMO_TTS_STYLE`、`TTS_SEGMENT_NORMALIZE`、`TTS_SEGMENT_TARGET_RMS_DBFS`、`TTS_SEGMENT_PEAK_LIMIT`;两者都不再读取 `NARRATION_CUMULATIVE_TEMPO_MAX`、`NARRATION_CUMULATIVE_TEMPO_HARD_MAX`、`TTS_SEGMENT_TEMPO_MAX`。它们的默认值成为固定值,设置后不再生效;`NARRATION_TIGHTEN=0` 的按 slot 锚定放置和 `NARRATION_DELAY_SECONDS` 的隐藏入场延迟随之删除,段落起点一律采用作者写的 `start`,只在上一块超时时顺延到上一块结尾加停顿之后(段落内与上一块相隔不到 1.6 秒的后续块仍紧接上一块播放,最多提前 1.2 秒,这一点不变)。`assembly_manifest.json` 的 `assembly_settings.narration_timing` 不再写 `delay_seconds` / `tail_pad_seconds`。`SUBTITLE_ORIGINAL_IN_GAPS` 等文档列出的变量不变;默认渲染结果与 TTS 缓存都不变。
71
+ - **删除 `dub.py` 的 `--asr-window` / `--ref-start` / `--ref-dur`。** 传入即报 unrecognized arguments;ASR 窗口 6 秒、克隆参考从第 2 秒取 10 秒的默认值不变。
72
+ - **video-cut 不再写 `cut_delivery_qc.json`,brief 不再写 `deslop_qc_requirements.json`。** `clip_plan_validated.json` 的 `qc` 里不再有 `delivery_qc`,也不再有顶层 `warning`(超出目标时长仍由 `qc.target_duration_drift` 报告),每次剪辑少一次 ffprobe;成片交付检查仍在 `assembly_qc.json`。`narration_lint.json` 里的 `deslop_qc` 报告去掉恒为 `false` 的 `style_card_required` / `style_card_requirement_source`,缺少或为空的 `style_card.json` 一律是建议项(与此前默认行为一致)。渲染参数与 lint 阻断规则不变。
73
+ - **删除 video-cut 的 `--clip-padding` 与 `CLIP_PADDING`。** recap 从不传这个参数、默认值是 0,而片段边界本来就会吸附到句末与自然停顿;现在 `cut.py --clip-padding` 报 unrecognized arguments,`CLIP_PADDING` 环境变量不再被读取。需要前后余量时直接在 `clip_plan.json` 里把入出点写宽。
74
+ - **`shot_review.py` 删除三个未写进文档的召回参数。** `--max-short-seconds` / `--dense-window-seconds` / `--min-dense-cuts` 传入即报错;召回规则固定为 1 秒短镜、2 秒内 4 个切点;`--max-short-frames`、`--threshold`、`--roi`、`--plan` 不变。
75
+
76
+ ### Fixed
77
+
78
+ - **删掉或插入一段旁白不再让后面所有段重新合成、重新计费。** voiceover 的段缓存以前按段序号(连同时间窗)记键,按 `no_safe_fit` 的建议删掉一段后,其后每段序号都变了,全部重新请求 TTS。现在缓存按内容寻址(文本、实际发给供应商的语气请求,以及供应商/模型/声线等设置),存在 `tts_segments/cache/`,`narr_NNN.wav` 改为指向缓存的硬链接(不支持硬链接的文件系统上为副本),`tts_meta.json` 与 assemble 读取的路径不变;只有内容或发给供应商的请求变了的段才重新合成。语气请求按供应商实际收到的内容记:MiMo 是那句自然语言指令,名义语速只在 ≥+6% 或 ≤-3% 时改变措辞,所以删段让某段从 +5% 变成倒数第二段的 -2% 时不再重新合成,复用的段按新位置的语速记 `tts_rate_offset`;Fish Audio 是数值 speed(语速变了就重合成,音高和情绪它不接收,不进键)。批准稿严格模式下,复用的段如果被挪进放不下的时间窗,照样在 TTS 阶段失败,不再为此重新合成。旧版的 `narr_NNN.wav.cache.json` 不再读取,该段重新合成时删除。
79
+ - **TTS 幻读按失败重试,不再写进段缓存。** MiMo TTS 偶尔读完原稿后再编一段话(35 字的句子返回 18.1 秒,正常 8.2–8.6 秒);以前这段音频会进段缓存,时间窗够宽时编出来的话会进成片,否则 assemble 报 `no_safe_fit`。现在段音频超过按 `TTS_MIN_SPEECH_RATE`(默认 2.5 字/秒;半角/全角数字逐个计、`%` 按“百分之”计 3 字)读完全文再加停顿与首尾静音的上限,就按失败重试、不写缓存;重试用尽则该段失败,报错写明时长与上限,并把最后一次被拒的音频留在 `tts_segments/narr_NNN.rejected.wav` 供试听。dub 的 voiceclone 台词走同一道检查(被拒的留在 `dub_tts/line_NNN_raw.rejected.wav`)。旧缓存里的这类 WAV 重跑时重新合成,按 `no_safe_fit` 缩稿后的重跑不再复用同一段坏音频。`TTS_MIN_SPEECH_RATE=0` 关闭。
80
+ - **剪辑接点不再丢帧,`edited_source.mp4` 恒定帧率。** 片段边界不在源帧网格上时,concat 让下一段从网格外开始,每个这样的接点丢一个帧位(25fps 下画面停 80 ms),成片变成可变帧率。现在句界吸附之后,入点对齐到源帧网格、时长对齐到整数个输出帧(只移动不到一帧,优先选句界门禁仍判为安全、仍在停顿内、不切掉必保证据的一侧,两侧同样安全时选不跨过原片硬切的一侧,入点不会停在硬切前一帧闪一下旧镜头),句界门禁检查对齐后的边界;渲染按每段 `frame_count` 精确出帧,多源时按画布帧率重采样(NTSC 用 `30000/1001` 而不是 `29.97`);片段越过比音轨短的视频流末尾时用末帧补足帧数,不再留空洞;标称帧率远高于实际平均帧率的可变帧率手机素材按实际帧率输出,不再翻倍成 60fps。输出时间轴按累计帧数计算,与渲染一致。`clip_plan_validated.json` 每段多 `frame_count`,`qc.frame_grid` 记录输出帧率与总帧数,`qc.boundary_status.frame_snaps` 记录每次对齐。`r_frame_rate` 为 `0/0` 但 `avg_frame_rate` 可用时按平均帧率对齐入点;同源无损连续的接点音频按上一段实际渲染的终点续接,采样连续。首帧比文件起点晚 0.2 秒以内的源,入点 0 仍算源头;晚得更多(如音频先开始的 TS 录制)时,对齐到首帧的入点照常按讲话判定。渲染后若实际帧数与 `qc.frame_grid.frame_count` 不符,cut 会记一条警告(只提示,不阻断)。旧的 `edited_source.mp4` 缓存会重渲染一次;输出时间轴可能比以前差不到一帧,旁白照旧按 validated 计划写。
81
+ - **切镜头避让不再把片段边界拉进原声讲话。** `SCENE_CUT_SNAP`(默认开)会把出点最多回收 `SCENE_CUT_SNAP_MARGIN`(默认 0.5 秒)到原片硬切上;附近没有停顿窗(ASR 空档里是音乐或环境声而不是静音)时,句末吸附修不回来,边界会停在讲话内被阻断。现在这类移动在原位置能过句界门禁时会被撤回(不与其他片段重叠时),按 `nearest_safe` 改后重跑可以收敛;`qc.boundary_status.shot_snaps` 记 `reverted_unsafe`、被撤回的切点与原因;声音优先于画面,片段边界可能离原片硬切不到半秒,开头或结尾带一小段别的镜头。
82
+ - **成片(dub 模式除外)在每条渲染路径上都是 H.264 8-bit 4:2:0 并带色彩标记。** 不烧字幕、不遮罩、不缩放时成片曾直接流复制源画面,10-bit、4:2:2、HEVC 或奇数宽高的源会原样交付,微信、Safari 和不少手机放不了;ffmpeg 缺 libass 降级后这条路径会变得常见。现在只有源画面已是 H.264 8-bit 4:2:0(`yuv420p`,或全范围 `yuvj420p` 原样复制)且宽高为偶数时才流复制,否则重编码为 `yuv420p`,`delivery_qc.reencode_reason` 记为 `normalize_source_format`。最终编码和 cut 的 `edited_source.mp4` 都写色彩标记:源未标记或已是 BT.709 时标为 BT.709 limited(`-colorspace/-color_primaries/-color_trc bt709 -color_range tv`,并在滤镜末尾用 `setparams` 打到每一帧,因为 ffmpeg 8/9 重编码时只给输出参数会丢掉 primaries/transfer),其它已声明的色彩空间原样保留(含 PAL 源的 BT.470 传输特性),全范围源保留 `pc`;单个 YUV 源只改标记,不转换像素。RGB 源按 BT.709 limited 显式转换,识别时既看 ffprobe 的色彩空间 `gbr`(PNG、libx264rgb),也看像素格式,所以不报色彩空间的 QuickTime RLE(`argb`)、GIF(`pal8`)同样按 BT.709 转换。多来源 cut 各源标记一致时保留,不一致(含 RGB、未标记与已标记的源混剪)时标为 BT.709 limited,并把每段的矩阵和范围显式转换过去:ffmpeg 8 的 concat 会自行把各段统一到其中一个来源的色彩空间,BT.601 源与未标记源混剪时两段都按 BT.601 存储却标成 BT.709;原色与传输特性仍只改标记。升级前缓存的 `edited_source.mp4` 会重新剪辑一次。dub 模式(`--edit-mode dub`)仍原样复制源画面,不做这项归一化,只补上 `+faststart`。`assembly_qc.json` 的 `delivery_qc.color_tags` 记录写入的标记;显式混音的 `packet_identity` 比较时不计这四个色彩字段,流复制的画面仍报 `EXACT`。
83
+ - **成片和 `edited_source.mp4` 不再继承原片的容器元数据。** 下载来的原片带的 `title`、`comment`(网址)等标签和章节此前会被 ffmpeg 原样抄进 `edited_source.mp4` 与最终成片,章节时间也对不上剪辑后的画面;现在 cut 渲染、assemble 的所有音频路径(narration、source-mix、adopted-packet-copy、显式混音)和 dub 输出都用 `-map_metadata -1 -map_chapters -1` 不带走任何源标签与章节(原音轨的语言标签也一并去掉)。
84
+ - **guohuo-60s 的 Remotion 透明层按新运行重定时只需改数据。** 总帧数、片名文字与两段显示窗口、四条花字此前写死在 TSX 里,换了配音时长只替换 `captions.json` 会渲染出偏短、错位的透明层。现在它们在 `remotion/src/overlay.json`,与 `captions.json` 一起作为 props 传入,`calculateMetadata` 按 props 定时长,`--props=<文件>` 可整体替换;标准库脚本 `remotion/sync_overlay.py`(见 Added)从运行的 `subtitles.srt` 重建 Remotion 读取的 `remotion/src/captions.json`(每次都写,`--out` 只额外写副本)、按母版时长设 `durationInFrames`,并列出越过母版结尾的字幕、片名窗口和花字(退出码 1);新增 `tsconfig.json` 与 `npm run typecheck`。runbook 第 5 节改为按这条流程复现。
85
+ - **近方形像素的视频可以用测得的原字幕带。** `tools/measure_subtitle.py`、recap 的 `--subtitle-y-top/--subtitle-y-bot` 预检和 assemble 的字幕带校验此前只认精确的 SAR 1:1,`64:63` 这类近方形视频直接被拒,字幕遮罩用不了,`「」` 原声字幕也因此跳过;未标注 SAR(`0:1`)在 assemble 被当成非方形拒绝,在 recap 预检里还会算出 1 像素宽的画布。现在三处都接受与 1:1 相差不超过 2% 的 SAR(`0:1`/`N/A` 按方形),并按显示画布换算:测量工具写出的 `canvas` 宽度按 SAR 缩放,旋转 90°/270° 的近方形视频把解码帧的像素行换算成显示画布行,红框预览也先缩放到显示画布再画网格和红框,从网格读到的值就是提示里要填的行;assemble 画遮罩时再换回解码帧的行。方形、未旋转的视频结果不变;SAR 偏离更大的视频照旧拒绝。
86
+ - **多视频 cut 第二阶段也生成剪后故事板。** video-script 要求写稿前先看剪后故事板,单视频第二阶段由 `understand.py --brief-only` 生成 `storyboard/edited_storyboard.*`,多视频第二阶段却只写 brief,从不生成。现在 recap 在写完多源 brief 后调用 `understand.py --edited-storyboard-only`(见 Added):按 validated 计划从各来源 `sources/<source_id>/frames/` 取帧,每个来源用自己 `frames_manifest.json` 记录的 fps(不同时长的来源抽帧率不同),tile 标 `out mm:ss / S<n> mm:ss`,sidecar 的 `sources` 与 brief 顶部列出 `S<n>` 对应的 `source_id`。所有 tile 统一缩放、补边并转成同一像素格式:混入不同分辨率或色度采样的来源时,ffmpeg 的 tile 会在中途重置,已排好的格子变黑;统一的格子尺寸取第一个被用到的来源的帧尺寸并向下取偶数(帧按存储分辨率抽取,853×480 这类奇数尺寸否则会让每一格都失败)。计划里登记了但没有片段用到的来源不占 `S<n>` 标签、不列入来源表。素材库恢复的来源没有抽帧,其片段不进故事板;故事板失败只打印警告,不影响暂停。
87
+ - **粗粒度 ASR 的句末锚点按实际精度标注。** understanding 按 ASR 窗口推出每个锚点的最坏误差 `timing_bound_seconds`,15 秒窗口里的锚点如实标为 `low` 并带 `boundary_use: unverified`,而不是凭字数比例猜出的 `high`;`speech_boundary_anchors.json` 升到 schema 2,旧文件有 `audio.wav` 时重新检测;素材库恢复(不带音频)时按 `asr_result.json` 原地重标、锚点时间不变,标不了就保持原样,不会被空的 `unavailable` 文件覆盖;没有 `boundary_use` 的 schema 1 锚点一律按 `unverified` 读。cut、script、assemble、brief 按 `boundary_use` 选锚点,选中的集合和门禁结果不变,状态与 brief 改写为 `unverified`(brief 显示 `[unverified ±N s]`)。剪后输出时钟的锚点也映射了 `pause_end` 和 `expected_time`(原片值保留在 `source_pause_end` / `source_expected_time`)。
88
+ - **只有语气词或 ASR 杂音的窗口("啊!"、"Hi.")不再让整段窗口都不能下刀或切入旁白。** cut 门禁、script 的旁白入口检查和 assemble 的入口检查都不再把这类窗口当作对白,只在紧挨真实对白的一侧保留 1 秒保护;"救我!"这类短台词和只有标点的窗口("……")仍算对白。
89
+ - **full 模式的旁白 lint 与 cut、assemble 读同一份转写。** 有 `asr_clean.json` 时,video-script 的声音归属和入口检查改用它(以前只读 `asr_result.json`),cut 门禁和 assemble 入口检查本来就优先读它;清洗把"啊!"还原成真实台词(或反过来)时,lint 不再放行一个 TTS 之后才被 assemble 以 `unsafe_entry` 阻断的入口。单视频的解说评审也改为优先引用清洗后的台词,与多视频评审一致。
90
+ - **文本为空的 ASR 行不再算作对白。** 三份 `_dialogue_speech_spans` 统一把空白文本的行当作只有时间的证据:不算对白,也不在相邻对白一侧留 1 秒保护;没有 `text` 字段的行仍按对白处理。video-script 的整段归属同样不再把只有空白的行算作讲话;assemble 回退读 ASR 时,空白行不再让入口检查误判为打断原声。
91
+ - **解说评审不再把有意留给原声的拍报成漏写。** 评审 prompt 新增「计划内留给原声的区间」:逐条列出 `visual_audio_board.json`(缺项时看 `recap_story_plan.json`)里 `audio_owner` 为原声/沉默或 `narration_job: none` 的拍,以及 `original_subtitles.json` 的字幕块,按评审时钟标时间,并要求不得据此报跳过、`incomplete` 或 `no_throughline`。以前计划 JSON 在 prompt 里只截前 3000 字,靠后的原声拍被截掉,评审看到无旁白的 beat 就报"skipped"。
92
+ - **旁白结束后原声 3 秒内回满。** assemble 只等 3 秒内的句末锚点,否则在旁白结束处回满(`bounded_release`),不再把原声压到远处的锚点或片尾;`assembly_qc.summary.max_source_duck_hold_seconds` 记录最长的压低延续。
93
+ - **默认路径不再截短旁白。** voiceover 超预算时保留原稿只记日志(截短后的产物以前总会被 `truncated_speech` 阻断);assemble 有界提速仍放不下的段在视频编码前以 `no_safe_fit` 阻断,错误里写明段号(`段 N`,按 narration.json 顺序从 1 起,此前从 0 起)与 `needed_tempo_factor`,不再白跑一遍完整渲染、也不再多调一次 TTS;显式 adopted full-sound 路径同样在编码前阻断。旧版截短合成的音频不会被复用:TTS 段缓存改为按内容寻址后,旧版的逐段缓存不再读取(默认策略名改为 `report-over-budget-v2`,只记在 `tts_meta.json` 各段的 `authored_text_policy` 里,不在缓存键中,改名本身不使任何缓存失效)。
94
+ - **MiMo 内容审核拒绝不再被当成对白或画面描述。** MiMo 把审核拦截作为一句英文回复("The request was rejected because it was considered high risk")返回,此前这句话会写进 `asr_result.json` 和逐场景 VLM 描述,再流进 brief,cut 与旁白校验还会把那个 ASR 窗口当成有人说话。现在 ASR 把它记为无文本,VLM 记为 `(VLM 无法识别此场景画面)` 并带 `analysis_status: "moderation_refused"`。只匹配 MiMo 自己的这句措辞,提到“违规”“风险”的真实台词不受影响;旧 work_dir 里已写下的拒绝文本需重跑 ASR / VLM 才会消失。
95
+ - **多视频运行会用上项目级 `background_research.json`。** 理解阶段对每个来源在 `sources/<source_id>/` 里运行,只读那里的调研文件。现在 recap 在每个来源理解前把按 SKILL.md 写在项目 `work_dir` 下的调研复制过去(来源目录里没有、或副本比项目文件旧时),项目级调研因此进入 VLM 上下文、ASR 人名纠错和索引;比项目文件新的来源副本保留,作为单集专用调研。
96
+ - **段落收紧提前的旁白块不再闯进没校验过的原声对白。** 段落内与上一块相隔不到 1.6 秒的块会紧接上一块播放、最多比写的 `start` 提前 1.2 秒,但旁白校验只检查过写的 `start`。assemble 现在只让它提前到不含原声对白的位置(ASR 对白区间减去实测安静窗口),有对白时停在最后一段对白结束处;真的提前了的块在 `assembly_manifest.json` 记 `source_entry_status: "paragraph_tightened"` 和新字段 `written_start`,此前这里是 `null`,看不出它被挪过。
97
+ - **旁白入口落在只有语气词的窗口里时记 `non_dialogue_source`。** 此前尖叫或 "Hi." 上的入口也记 `quiet_source`,像是原声安静;判定与是否阻断都不变。整段都不压低原声的块现在也记入口状态(此前为 `null`)。
98
+ - **assemble 退回读 ASR 时,空文本行也不再算作原声讲话。** 上面的空白行规则只管入口是否打断对白;full 模式下 assemble 从 `asr_clean.json` / `asr_result.json` 取的整段讲话区间此前仍包含没识别出文字的窗口,只落在这种窗口上的旁白也会压低原声并做句末交接。现在与 cut、script 一样先去掉空文本行。
99
+ - **故事索引被截断时不再报 ok。** consolidate 的索引调用此前上限 3000 token,5 分钟的解说素材就会被截断(`finish_reason=length`),解析出空列表后照样写出空的 `understanding_index.json`,`consolidation.status.json` 仍是 `ok`,brief 拿到 0 个角色。现在索引与 ASR 清洗两次调用的上限都是 8000 token,被截断时加倍预算重试一次;仍被截断或返回的不是 JSON 时不写产物,`consolidation.status.json` 记为 `failed` 并写明原因,brief 照常提示。索引 prompt 要求更紧凑的输出(每条描述不超过 40 字、剧情节点最多 20 条等),已有索引会按新 prompt 重建一次。
100
+ - **cut 续跑不再让剪后输出证据失效。** `cut.py` 复用 `edited_source.mp4` 时会重写内容不变的 `clip_plan_validated.json`,绑定其 `{size, mtime_ns}` 的 `speech_boundary_anchors_output.json` 因此过期,第三遍续跑的 `validate --mode cut_output` 对冷开场以外的旁白一律报 `source_sentence_anchors_unavailable`,assemble 的原声闪避也只能退回保守模式。现在计划未改动时不重写,`clip_plan.json` 被重新保存时照常重写。
101
+ - **cut 输出时间轴上的句末锚点不再落进相邻片段或成片之外。** 句末锚点(停顿结束)比片段出点晚几毫秒、或比入点早几毫秒时,`speech_boundary_anchors_output.json` 把它映射到下一段(多视频时是另一个来源)或上一段的输出时间里,却仍标着本段的来源,旁白校验和原声闪避会把别处的讲话当成这里的句末;首尾片段帧对齐后(如 181.42 → 181.40)还会映射到片头之前或成片结尾之后。现在落在 `[0, 成片时长]` 之外的锚点丢掉(brief 也不再列出),片段接缝处的锚点钉在本段的入点或出点上(另一段本身播放该时刻时只归那一段),`pause_start`、`expected_time` 和讲话/安静区间同样不越出本段;`source_time` 仍记实测的原片时间。单视频与多视频相同。
102
+ - **多视频 cut 的旁白校验不再以 `KeyError` 崩溃。** recap 写的多源 `speech_boundary_anchors_output.json` 现在带 `clip_plan_identity`;源锚点缺 `pause_start` 时与单源一样按 `time − 0.12` 处理。
103
+ - **Windows 上经管道运行 recap 时,阶段脚本不再因中文日志崩溃。** recap 调用各阶段脚本时设置 `PYTHONIOENCODING=utf-8`;此前 stdout 被管道捕获(Agent 宿主、CI)时子进程默认 cp1252,第一行中文日志就抛 `UnicodeEncodeError`。
104
+ - **`MIMO_VIDEO_API_KEY` 被拒(401)时报错点名它本身。** 不再让用户去检查 `MIMO_API_KEY`。
105
+ - **素材库保存并恢复 `consolidation.status.json`。** 从素材库恢复的 work_dir 重建 brief 时,仍会提示 consolidate 失败或缺索引。
106
+ - **cut 终轮先判断解说是否过期,再重剪。** `clip_plan.json` 在写稿后改过时,单视频与多视频 cut 现在在调用 `cut.py` 之前就以"clip_plan.json 已改变"退出,不再先重新归一化、吸附、甚至重编码 `edited_source.mp4` 之后才报错。
107
+ - **各技能 SKILL.md 补齐漏写的选项并改正错误说明。** video-cut §4 补上 `--allow-duration-drift`、`--normalize-only` 的用法和多源清单格式,命令块补上 `--clip-plan`、`--review-shots`、`--shot-scene-threshold`、`--shot-roi`,并列出 cut 阻断时 `qc.blocking` 里的错误码(`unsafe_clip_sentence_boundary`、`target_duration_drift`、`REQUIRED_EVIDENCE_*`)及各自的明细位置;`cut.py --normalize-only` 的帮助不再声称会“剪枝”计划。video-understanding §4/§5 改成两张表,列全 `understand.py` 的 13 个参数(含此前未写的 `--style`、`--edit-mode`、`--target-duration`、`--brief-only`、`--no-consolidate`、`--consolidate-asr`)和默认运行写出的产物(含此前未列的 `speech_boundary_anchors.json`、`understanding_index.*`、`consolidation.status.json`、`storyboard/*`)。video-voiceover 的命令示例补上 `--allow-partial-tts`,并把粘在一起的 `--voice-ref` 与 dub 缓存两条说明拆开。video-script 与 video-assemble 写明段落内相隔不到 1.6 秒的旁白块会紧接上一块播放、最多比写的 `start` 提前 1.2 秒,这一提前发生在校验之后。
108
+ - **参考文档去掉不存在的选项与环境变量。** `data-schema.md` 不再提 `--step script`,`config-playbook.md` 删除把写死常量 `NARRATION_COVERAGE_TARGET` / `NARRATION_BLOCK_SECONDS` 当成环境变量的一行。
109
+ - **不设 `MIMO_API_KEY` 重跑理解不再把真实转写覆盖成 `[]`。** ASR 缓存键去掉了 `mimo_asr_api_key_present`(旧 sidecar 里的这个字段忽略,升级后不会重新转写),无 key 的占位转写(`UNAVAILABLE_NO_KEY`)不再算缓存命中;没有 key 时,由 key 前缀决定的默认 endpoint 不参与 ASR、VLM 与 MiMo overview 的缓存比对,所以用 Token Plan key 做出的转写、画面分析和 overview 离线照常复用,overview 也不再被删除。缓存仍未命中(例如 `cp -R` 不带 `-p` 复制 work_dir 改了文件时间)而 `asr_result.json` 里已有转写时,运行停下并保留转写,提示用 `cp -p` / `cp -Rp` / `rsync -t` 保留时间重新复制,或设置 `MIMO_ASR_API_KEY` / `MIMO_API_KEY` 后重跑(会重新转写),并说明 `--skip-asr` 会把现有转写替换成 `[]`、不能拿来绕过,不再写 `[]` 后报成功;VLM 缓存失效而没有 key 时,在 ASR 之前就退出。consolidation 需要调模型而没有 key 时跳过、不发请求,`consolidation.status.json` 记新状态 `skipped_no_key`,brief 的可选阶段警告列出它;已缓存的索引照常复用。
110
+ - **故事索引的剧情时间与重复角色做确定性修复。** `plot_points[*].time` 里 `00:95` 这类秒数 ≥ 60 的写法按分×60+秒改写成规范 `MM:SS`,`约01:20`、`01:20左右`、`12.5秒`、全角冒号 `00:95`、`3分20秒`、`1.5分` 和区间 `01:20-01:45`(取起点)也能读,`第3分钟`、`第95秒` 这类序数单位读作该段的起点(`02:00`、94 秒,`第1分钟` 是 `00:00`),读不出或超出片长的时间删掉;同名条目视为一人,一条角色的名字等于另一条的别名时合并成一条(留在最先出现的条目位置,名字取组内最先出现的名字;第一条没有名字、只靠别名连进来时也不会留下无名角色或把关系改指成空;其余名字进 `aliases`),合并结果与条目顺序无关;只共享"男子""老板"这类别名的两人不合并,同时连到两个互不相连角色的条目(如名叫"男子"的路人,或别名里同时写着两人名字的条目)单独保留、不把两人并成一个,写成字符串的 `aliases` 当作一个别名,关系改指合并后的名字并去重。旧 work_dir 的索引在下次完整理解时就地修好、不调模型,`--brief-only` 生成的 brief 也读修复后的索引。
111
+ - **brief 说明哪些场景被 MiMo 内容审核拒绝。** 有 `analysis_status: moderation_refused` 的场景时,brief 多一行 `Moderation-refused scenes: N/M (Scene …)`,Scene timing guide 里对应的占位描述后加 `[moderation_refused]`,Agent 不会把空描述当成空镜头。
112
+ - **复制 work_dir 后 brief 的 storyboard 路径指向自己的目录。** `storyboard/*.json` 的 `page_images` 改存相对 work_dir 的 `storyboard/<文件名>`,`edited_video_path` 存 `edited_source.mp4`;旧版本写的绝对路径在缓存命中时改写,不重建拼图。
113
+ - **brief 的时长标签不再取整到分钟。** cut 的目标与剪后时长以前按整分钟显示,90 秒目标写成 `~2min`、101.5 秒的剪辑也是 `~2min`;现在不足一分钟写秒(`45s`),整分钟写 `2min`,其余写分秒(`1m30s`、`1m42s`),满一小时带上小时(`2h01m05s`,以前是 `121m05s`)。
114
+ - **cut 第二轮 brief 的 Scene timing guide 改用 OUTPUT 时间。** 第二轮要求按 `edited_source.mp4` 的时间写 `narration.json`,结尾却附着整片原片时间的场景表(含剪掉的场景、片尾演职员表,以及按原片场景算的"fully narrated"字数上限)。现在第二轮的这一节标题为 `## Scene timing guide (OUTPUT time)`,只列保留下来的片段,起止、安静窗口、帧动作、ASR 与字数上限都按输出时间计,被拆到多个片段的场景写作 `source scene N part M`;第一轮(写 `clip_plan.json`)仍是原片时间的场景表。第二轮各节也不再夹带原片时间:VLM 描述与深层分析里引用的原片时刻(`12.0s`、`00:30`)改写成输出时间,落在被剪掉部分的写 `[cut-away moment]`;只被剪进一部分的粗粒度 ASR 窗口不再列出整窗文字(其中有成片里听不到的台词),改为 `[partial ASR window: only part of it is in the cut, text withheld]`。
115
+ - **brief 相邻两节的场景号对得上。** Scene timing guide 写 `Scene 1` / `source scene 1`,`### Fusion scene` 与 `ASR chunk … | scenes …` 却印从 0 数的 `scene_id`,同一个场景在相邻两节差 1;现在 brief 里给人看的场景号都从 1 数(拆分场景写 `N part M`),`timeline_fusion.json` / `asr_writing_chunks.json` 里的 `scene_id` 不变。
116
+ - **`interrupts_source_sentence` 的建议入点不再把块挪到另一块上或越过它。** 以前建议的是入点之后的下一个锚点,可能远在 60 秒外,也可能正好是另一块的开头,照着改就重叠。现在建议入点前后 10 秒内离入点最近的锚点,要求整块按原时长平移过去后仍在前后两块之间(不越过相邻块,故事顺序不变),且不与任何块重叠、也不与它们相接(间隔须大于 0.15 秒);前一块自己也收到建议时,后一块同时避开它原来和建议的位置,所以相邻两块的建议无论照改哪几条都不会互相撞上。cut 模式下平移后仍须在该块所属片段内,cut_output 下不超过 `--output-duration`;full 模式不知道视频结尾,这一点不检查。报告新增 `suggested_end`(平移后的结束时间)与 `max_shift_seconds`;范围内没有这样的锚点时 `suggested_start` 为 `null`,摘要写明前后 10 秒内没有可挪的锚点。lint 无 warning 通过时控制台打印 `narration lint:通过`,与有 warning 时的中文首行一致。
117
+ - **validate 的 lint 失败不再显示为 Python traceback。** `over_budget`、`interrupts_source_sentence` 这类普通 lint 失败以前抛出未处理的异常,最后一行只有 `#1: over_budget`(从 0 数的下标),改稿要的数字全在 `narration_lint.json` 里。现在 `validate.py` 以退出码 1 结束,只打印一段摘要:逐块写「段 N」(narration.json 里第 N 块,从 1 数)、错误码、关键数字(时间窗、字数、预算、硬上限、超出字数,或入点与建议入点)和改法,末行是 `narration_lint.json` 的路径;其他异常仍带 traceback。lint 通过但有 warning 时,控制台按同样格式逐条打印每个 warning,不再只有一行 `narration lint: 1 warnings`;失败摘要在 error 之后也列出全部 warning。cut_output 里时间窗短到 `slot_too_short` 的块不再吞掉同一块的 `over_budget` warning,两条都报(cut_output 的超预算仍只是 warning)。cut_output 越界错误和 `narration_review.md` 的 findings 也改用从 1 数的「段 N」;原声字幕里的去 AI 味 blocker(如破折号)写成「原声字幕第 N 条」并提示改 `original_subtitles.json`;`narration_lint.json` 的 `index` 与 `narration_review.json` 的 `segment` 仍从 0 数。
118
+
13
119
  ## [0.6.0] - 2026-09-27
14
120
 
15
121
  三条主线:资源库与模板(登记与校验、项目绑定、每次运行的资源记录、字体文件、静态包装图层);只读的本机剪辑台 dashboard;以及 skill 层分包、去内容哈希、测试审计后的架构梳理。
@@ -357,7 +463,8 @@ recap feels like a recap, not captions over a clip.
357
463
  MiMo API key. Five independent skills (understanding, script, cut, voiceover, assemble)
358
464
  plus a thin orchestrator; optional 剪映 draft export.
359
465
 
360
- [Unreleased]: https://github.com/zenstory-ai/video-recap-skills/compare/v0.6.0...HEAD
466
+ [Unreleased]: https://github.com/zenstory-ai/video-recap-skills/compare/v0.6.1...HEAD
467
+ [0.6.1]: https://github.com/zenstory-ai/video-recap-skills/compare/v0.6.0...v0.6.1
361
468
  [0.6.0]: https://github.com/zenstory-ai/video-recap-skills/compare/v0.5.0...v0.6.0
362
469
  [0.5.0]: https://github.com/zenstory-ai/video-recap-skills/compare/v0.4.0...v0.5.0
363
470
  [0.4.0]: https://github.com/zenstory-ai/video-recap-skills/compare/v0.3.3...v0.4.0
@@ -7,7 +7,7 @@
7
7
  <h1 align="center">Video Recap Skills</h1>
8
8
 
9
9
  <p align="center">
10
- <b>Turn one or several videos into a Chinese-narration recap: six skills inside the coding agent you already use, ffmpeg locally, one Xiaomi MiMo key remotely, and an optional JianYing/CapCut draft to keep editing by hand.</b>
10
+ <b>Turn one or several videos into a Chinese-narration recap: seven skills (six for production plus one on-demand reference skill) inside the coding agent you already use, ffmpeg locally, one Xiaomi MiMo key remotely, and an optional JianYing/CapCut draft to keep editing by hand.</b>
11
11
  </p>
12
12
 
13
13
  <p align="center">
@@ -40,17 +40,22 @@ The 59-second landscape recap above, *Guohuo (这一秒过火)*, is the final de
40
40
 
41
41
  ## What it is
42
42
 
43
- Six skills install into Claude Code, Codex CLI, OpenCode, or OpenClaw. You give the video paths and the recap you want in plain language; the agent understands picture and dialogue, decides the story and audiovisual plan, cuts, writes, voices, mixes, and subtitles. Supported inputs: `.mp4 / .mov / .mkv / .webm`.
43
+ Seven skills (six for production plus one on-demand reference skill) install into Claude Code, Codex CLI, OpenCode, or OpenClaw. You give the video paths and the recap you want in plain language; the agent understands picture and dialogue, decides the story and audiovisual plan, cuts, writes, voices, mixes, and subtitles. Supported inputs: `.mp4 / .mov / .mkv / .webm`.
44
44
 
45
45
  - **One key, ffmpeg locally.** ASR, VLM, and TTS all go through [Xiaomi MiMo](https://platform.xiaomimimo.com); the local runtime is Python's standard library plus `ffmpeg`, with no GPU, no `pip install`, and no model downloads. Voiceover can switch to Fish Audio, which replaces only that stage.
46
46
  - **The editorial decision comes before the sound allocation.** The agent compares edit hypotheses first, writes the viewer promise, POV, dramatic question, and change-based beats into `recap_story_plan.json`, then assigns each beat a picture job and an audio owner: narration is voiced as a block only when it has a defined job, and strong dialogue, action sound, or silence may own an entire beat.
47
47
  - **Cut first, narrate second, so the timeline is aligned by construction.** Cut mode renders the shortened video first and writes narration against that output timeline; feed several videos at once and pick ranges by `source_id` to cut one story spine; each video's analysis is saved to a filesystem material library for reuse.
48
48
  - **Keep editing after the render.** The multi-track `timeline.json` exports to a JianYing draft with editable source clips, narration, BGM, subtitles, and image overlays; drop in an accurate subtitle file and it becomes the preferred source for original-dialogue captions.
49
- - **Every step leaves a record you can check.** Narration lint, assembly QC, delivery QC, and the revision log are machine-readable files; the optional MiMo adviser only suggests, and a missing key, rate limit, or timeout never blocks the render.
49
+ - **Every step leaves a record you can check.** Narration lint, assembly QC, delivery QC, and the revision log are machine-readable files.
50
50
 
51
51
  ## Install
52
52
 
53
- Prerequisites: Python 3.10 or newer, `ffmpeg` with libass on `PATH` (subtitles are burned in by default), and one [Xiaomi MiMo](https://platform.xiaomimimo.com) API key.
53
+ ### ClawHub
54
+
55
+ ClawHub distribution is governed by the repository's [explicit publish inventory](.clawhub/publish.json), with discovery through [ClawHub](https://clawhub.ai/). A skill-specific link is added here only after its publisher, version, and anonymous accessibility are verified, so this README never presents a nonexistent listing as live.
56
+
57
+
58
+ Prerequisites: Python 3.10 or newer, `ffmpeg` on `PATH`, and one [Xiaomi MiMo](https://platform.xiaomimimo.com) API key. Subtitles are burned in by default, which needs an ffmpeg with libass. Homebrew's stock `ffmpeg` has no libass: the default run then skips the burn, ships a same-name `.srt` sidecar next to the recap, and records a warning in `final_qc.json` (an explicit `--burn-subtitles` stops before the run starts instead). Narration that adds on-screen text overlays (`visual_overlays`) also needs an ffmpeg with drawtext, and stops before voiceover without it. To burn subtitles on macOS, use `brew install ffmpeg-full` (keg-only: put its `bin` first on `PATH`).
54
59
 
55
60
  ```bash
56
61
  brew install ffmpeg # macOS; apt on Debian/Ubuntu, choco / scoop / winget on Windows
@@ -90,7 +95,7 @@ git clone https://github.com/zenstory-ai/video-recap-skills.git
90
95
  cd video-recap-skills
91
96
  mkdir -p .opencode
92
97
  ln -s ../skills .opencode/skills # on Windows, copy skills\* into .opencode\skills\
93
- opencode debug skill # should list all 6 skills
98
+ opencode debug skill # should list all 7 skills
94
99
  ```
95
100
 
96
101
  **OpenClaw**: after cloning, import the Claude plugin bundle:
@@ -276,7 +281,7 @@ The case went through four revision rounds, each written into [`revision-log.jso
276
281
  },
277
282
  ```
278
283
 
279
- The mechanical pre-delivery checks are in [`assembly_qc.json`](examples/guohuo-60s/assembly_qc.json) (loudness, subtitle overflow, release gate) and [`delivery-qc.json`](examples/guohuo-60s/delivery-qc.json):
284
+ The mechanical pre-delivery checks are in [`assembly_qc.json`](examples/guohuo-60s/assembly_qc.json) (loudness, per-segment narration integrity, `verdict` / `blocking_codes`) and [`delivery-qc.json`](examples/guohuo-60s/delivery-qc.json):
280
285
 
281
286
  ```json
282
287
  "checks": {
@@ -326,7 +331,7 @@ Use /path/to/ep1.mp4 and /path/to/ep2.mp4 to make one ten-minute recap with a sh
326
331
 
327
332
  The agent handles understanding, story and audiovisual planning, cutting, scripting, voiceover, and assembly. In cut mode it first chooses the footage, renders the shortened video, and only then writes narration on the output timeline; the internal pauses and resumes are the agent's job too.
328
333
 
329
- ## Workflow and the six skills
334
+ ## Workflow and the seven skills
330
335
 
331
336
  ```mermaid
332
337
  flowchart LR
@@ -342,7 +347,7 @@ flowchart LR
342
347
  class research,cut opt;
343
348
  ```
344
349
 
345
- The six skills hand off through the JSON / MP4 artifacts in `work_dir`:
350
+ The seven skills (six for production plus one on-demand reference skill) hand off through the JSON / MP4 artifacts in `work_dir`:
346
351
 
347
352
  | Skill | Responsibility | In → Out |
348
353
  |---|---|---|
@@ -352,6 +357,7 @@ The six skills hand off through the JSON / MP4 artifacts in `work_dir`:
352
357
  | [`video-cut`](skills/video-cut/) | Clip plan → rendered cut; cut first, narrate second on the output timeline | `clip_plan.json + video` → `edited_source.mp4` |
353
358
  | [`video-voiceover`](skills/video-voiceover/) | Synthesise narration audio (MiMo `mimo-v2.5-tts` / Fish Audio `s2.1-pro-free`) | `narration.json` → `tts_segments/ + tts_meta.json` |
354
359
  | [`video-assemble`](skills/video-assemble/) | Mix · duck original audio · render subtitles · multi-track timeline · optional JianYing export | `video + tts_meta` → `recap_<name>.mp4 + subtitles.srt/.ass + timeline.json` |
360
+ | [`video-reference`](skills/video-reference/) | On demand, off the production path: break a finished video down into a reusable production reference (structure, pacing, shots, narration/subtitles, sound-picture handoff); source facts stay local, the export holds only methods and numbers | `finished video + understanding artifacts` → `production_reference.json` |
355
361
 
356
362
  The recap is always written to `recap_<name>.mp4` alongside `subtitles.srt/.ass`; all intermediate artifacts live in `work_dir/`, with the field contracts in the [data schema](skills/video-recap/references/data-schema.md).
357
363
 
@@ -365,21 +371,19 @@ Analyze /path/to/ep1.mp4 and save reusable understanding artifacts under /path/t
365
371
 
366
372
  The library holds JSON, Markdown, and an index only; it copies no media, builds no database, and uses no embeddings. The agent simply `grep`s the filesystem.
367
373
 
368
- **Run an advisory MiMo review before and after assembly, and export a JianYing draft:**
374
+ **Export a JianYing draft:**
369
375
 
370
376
  ```text
371
- Make a recap of /path/to/video.mp4, run MiMo quality review before assembly and after rendering, and export an editable JianYing draft.
377
+ Make a recap of /path/to/video.mp4 and export an editable JianYing draft.
372
378
  ```
373
379
 
374
- MiMo review makes at most one request per stage, only suggests, and never blocks the render if it fails.
375
-
376
380
  **Align recap subtitles with the source's burned-in subtitle band:**
377
381
 
378
382
  ```text
379
383
  Detect the source subtitle band in /path/to/video.mp4 and let me confirm the preview before rendering recap subtitles in the same region.
380
384
  ```
381
385
 
382
- The preview is stored under `.subtitle_measure/`; it currently requires square-pixel video and bottom-aligned source subtitles.
386
+ The preview is stored under `.subtitle_measure/`; it currently requires square or near-square pixels (SAR within 2% of 1:1) and bottom-aligned source subtitles.
383
387
 
384
388
  **Voice with an authorised reference voice:**
385
389
 
@@ -428,7 +432,7 @@ Yes. Understanding relies on the VLM reading the picture and does not require ex
428
432
 
429
433
  ### A long video hit a 429 or was interrupted halfway. Do I start over?
430
434
 
431
- No. VLM scene analysis resumes from where it stopped and recovers from rate limits; once `narration.json` is written, repeating the same command continues, cut mode records cut/narrate progress in `recap_phase.json`, and a resume only continues a work directory for the same source video and parameters.
435
+ No. VLM scene analysis resumes from where it stopped and recovers from rate limits; once `narration.json` is written, repeating the same command continues, cut mode records in `recap_phase.json` which clip plan the narration was written for (changing the plan asks for a new narration), and a resume only continues a work directory for the same source video and parameters.
432
436
 
433
437
  ### The VLM can't tell who is who and the narration is all "a man in black"?
434
438
 
@@ -5,7 +5,7 @@
5
5
  <h1 align="center">Video Recap Skills</h1>
6
6
 
7
7
  <p align="center">
8
- <b>把一段或几段视频做成中文解说成片:六个技能装进你正在用的编程 Agent,本地只要 ffmpeg,远程只要一个小米 MiMo key,成片还能一键导成剪映草稿接着改。</b>
8
+ <b>把一段或几段视频做成中文解说成片:七个技能(六个生产 + 一个按需参考)装进你正在用的编程 Agent,本地只要 ffmpeg,远程只要一个小米 MiMo key,成片还能一键导成剪映草稿接着改。</b>
9
9
  </p>
10
10
 
11
11
  <p align="center">
@@ -40,18 +40,23 @@
40
40
 
41
41
  ## 这是什么
42
42
 
43
- 六个技能装进 Claude Code、Codex CLI、OpenCode 或 OpenClaw,你用自然语言给出视频路径和想要的成片,Agent 负责理解画面与对白、
43
+ 七个技能(六个生产 + 一个按需参考)装进 Claude Code、Codex CLI、OpenCode 或 OpenClaw,你用自然语言给出视频路径和想要的成片,Agent 负责理解画面与对白、
44
44
  决定故事与视听方案、剪辑、写稿、配音、混音和字幕。支持 `.mp4 / .mov / .mkv / .webm`。
45
45
 
46
46
  - **一个 key,本地只要 ffmpeg。** ASR、VLM、TTS 都走[小米 MiMo](https://platform.xiaomimimo.com),本地只用 Python 标准库和 `ffmpeg`,不需要 GPU,不需要 `pip install`,也不下载模型。配音可以换成 Fish Audio,只替换配音这一段。
47
47
  - **先做创作决定,再分配声音。** Agent 先比较剪辑假设,把观众承诺、POV、戏剧问题和"发生了什么变化"的 beat 写进 `recap_story_plan.json`,再给每一拍指定画面任务和声音归属:旁白只在有明确任务时整块配音,强对白、动作声或沉默可以完整主导一拍。
48
48
  - **先剪后配,时间轴天然对齐。** 剪辑模式先把长视频剪成成片,再对着成片写解说;一次可以传多个视频,按 `source_id` 选段剪成一条主线;每个视频的分析沉淀成文件系统素材库,下次直接复用。
49
49
  - **成片之外还能继续改。** 多轨时间线 `timeline.json` 可一键导出剪映草稿,原片、解说、BGM、字幕、图片叠层都可编辑;自带一份准确字幕文件就会被当作原声字幕的首选来源。
50
- - **每一步都留下可核对的记录。** 旁白 lint、组装 QC、交付 QC 和看片修改日志都是机器可读文件;可选的 MiMo 成片顾问只给建议,缺 key、限流或超时都不会阻断出片。
50
+ - **每一步都留下可核对的记录。** 旁白 lint、组装 QC、交付 QC 和看片修改日志都是机器可读文件。
51
51
 
52
52
  ## 安装
53
53
 
54
- 前提:Python 3.10 或更新版本,`PATH` 上有带 libass 的 `ffmpeg`(默认烧录字幕),以及一个[小米 MiMo](https://platform.xiaomimimo.com) API Key。
54
+ ### ClawHub
55
+
56
+ ClawHub 分发由仓库中的 [显式发布清单](.clawhub/publish.json) 管理,并通过 [ClawHub](https://clawhub.ai/) 提供发现入口。具体 skill 链接只有在发布者、版本和匿名访问均验证后才会写入本文档,避免把尚不存在的条目当成已上架。
57
+
58
+
59
+ 前提:Python 3.10 或更新版本,`PATH` 上有 `ffmpeg`,以及一个[小米 MiMo](https://platform.xiaomimimo.com) API Key。默认把字幕烧录进画面,这需要带 libass 的 ffmpeg;Homebrew 自带的 `ffmpeg` 没有 libass,这时默认运行不烧录,在成片旁输出同名 `.srt` 外挂字幕并在 `final_qc.json` 里记一条警告(显式传 `--burn-subtitles` 则在开跑前报错)。旁白里写了画面文字叠加(`visual_overlays`)时还需要带 drawtext 的 ffmpeg,缺了会在配音前报错。要在 macOS 上烧录字幕,可用 `brew install ffmpeg-full`(keg-only,需把它的 `bin` 放到 `PATH` 前面)。
55
60
 
56
61
  ```bash
57
62
  brew install ffmpeg # macOS;Debian/Ubuntu 用 apt,Windows 用 choco / scoop / winget
@@ -91,7 +96,7 @@ git clone https://github.com/zenstory-ai/video-recap-skills.git
91
96
  cd video-recap-skills
92
97
  mkdir -p .opencode
93
98
  ln -s ../skills .opencode/skills # Windows 把 skills\* 复制到 .opencode\skills\
94
- opencode debug skill # 应列出全部 6 个技能
99
+ opencode debug skill # 应列出全部 7 个技能
95
100
  ```
96
101
 
97
102
  **OpenClaw**:克隆后导入 Claude 插件包:
@@ -267,7 +272,7 @@ Agent 在剪任何一刀之前先写 [`recap_story_plan.json`](examples/guohuo-6
267
272
  },
268
273
  ```
269
274
 
270
- 交付前的机械检查写在 [`assembly_qc.json`](examples/guohuo-60s/assembly_qc.json)(响度、字幕溢出、发布门禁)和 [`delivery-qc.json`](examples/guohuo-60s/delivery-qc.json):
275
+ 交付前的机械检查写在 [`assembly_qc.json`](examples/guohuo-60s/assembly_qc.json)(响度、逐段旁白完整性、`verdict` / `blocking_codes`)和 [`delivery-qc.json`](examples/guohuo-60s/delivery-qc.json):
271
276
 
272
277
  ```json
273
278
  "checks": {
@@ -315,7 +320,7 @@ Agent 在剪任何一刀之前先写 [`recap_story_plan.json`](examples/guohuo-6
315
320
 
316
321
  Agent 会自动完成理解、故事与视听规划、剪辑、写稿、配音和合成。剪辑模式内部会先确定保留片段、生成剪后成片,再按输出时间轴写旁白;这些暂停和续跑也由 Agent 处理。
317
322
 
318
- ## 流程与六个技能
323
+ ## 流程与七个技能
319
324
 
320
325
  ```mermaid
321
326
  flowchart LR
@@ -331,7 +336,7 @@ flowchart LR
331
336
  class research,cut opt;
332
337
  ```
333
338
 
334
- 六个技能通过 `work_dir` 里的 JSON / MP4 产物衔接:
339
+ 七个技能(六个生产 + 一个按需参考)通过 `work_dir` 里的 JSON / MP4 产物衔接:
335
340
 
336
341
  | 技能 | 职责 | 输入 → 输出 |
337
342
  |---|---|---|
@@ -341,6 +346,7 @@ flowchart LR
341
346
  | [`video-cut`](skills/video-cut/) | 片段计划 → 拼剪成片;剪辑模式先剪后配,解说按成片时间轴写 | `clip_plan.json + 视频` → `edited_source.mp4` |
342
347
  | [`video-voiceover`](skills/video-voiceover/) | 合成解说音频(MiMo `mimo-v2.5-tts` / Fish Audio `s2.1-pro-free`) | `narration.json` → `tts_segments/ + tts_meta.json` |
343
348
  | [`video-assemble`](skills/video-assemble/) | 混音 · 压低原声 · 渲染字幕 · 多轨时间线 · 可选导出剪映 | `视频 + tts_meta` → `recap_<名>.mp4 + subtitles.srt/.ass + timeline.json` |
349
+ | [`video-reference`](skills/video-reference/) | 按需拆片,不在生产路径上:把一部成片拆成可复用的制作参考(结构、节奏、镜头、旁白字幕、音画分工),原片事实只留本地,导出物只含方法与数值 | `成片 + 理解产物` → `production_reference.json` |
344
350
 
345
351
  成片固定输出为 `recap_<名>.mp4`,同时产出 `subtitles.srt/.ass`;全部中间产物在 `work_dir/`,字段契约见[数据结构](skills/video-recap/references/data-schema.md)。
346
352
 
@@ -354,21 +360,19 @@ flowchart LR
354
360
 
355
361
  素材库只保存 JSON / Markdown 和索引,不复制原始媒体、不建数据库、不做 embedding;Agent 直接在文件系统里 `grep`。
356
362
 
357
- **合成前后各做一次 MiMo 质量复核,并导出剪映草稿:**
363
+ **导出剪映草稿:**
358
364
 
359
365
  ```text
360
- 给 /path/to/video.mp4 做解说,合成前和成片后都做 MiMo 质量复核,并导出可继续编辑的剪映草稿。
366
+ 给 /path/to/video.mp4 做解说,并导出可继续编辑的剪映草稿。
361
367
  ```
362
368
 
363
- MiMo 复核每个阶段最多一次请求,只给建议,失败也不阻断出片。
364
-
365
369
  **让解说字幕贴合原片硬字幕的位置:**
366
370
 
367
371
  ```text
368
372
  先检测 /path/to/video.mp4 的原片字幕区域并让我确认预览,再把解说字幕贴到同一区域生成成片。
369
373
  ```
370
374
 
371
- 检测预览保存在 `.subtitle_measure/`;当前要求方形像素视频和底部对齐字幕。
375
+ 检测预览保存在 `.subtitle_measure/`;当前要求方形或近方形像素视频(SAR 与 1:1 相差不超过 2%)和底部对齐字幕。
372
376
 
373
377
  **用有授权的参考音色配音:**
374
378
 
@@ -418,7 +422,7 @@ MiMo 复核每个阶段最多一次请求,只给建议,失败也不阻断出
418
422
 
419
423
  ### 长视频跑到一半报 429 或中断了,要从头再来吗?
420
424
 
421
- 不用。VLM 场景分析可断点续传,限流会自愈;写好 `narration.json` 后重复同一条命令即可继续,剪辑模式的剪 / 配进度记录在 `recap_phase.json`,续跑只会接同一个源视频、同一组参数的工作目录。
425
+ 不用。VLM 场景分析可断点续传,限流会自愈;写好 `narration.json` 后重复同一条命令即可继续,剪辑模式在 `recap_phase.json` 记下解说对应的剪辑计划(改了计划会要求重写解说),续跑只会接同一个源视频、同一组参数的工作目录。
422
426
 
423
427
  ### VLM 认不出谁是谁,解说里全是"黑衣男子"?
424
428