@oh-story/dsh 0.1.9 → 0.1.11

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 (529) hide show
  1. package/README.md +14 -14
  2. package/lib/client.js +209 -73
  3. package/lib/client.js.map +3 -3
  4. package/lib/drama/manifest.json +248 -168
  5. package/lib/drama/skills/short-drama/SKILL.md +16 -4
  6. package/lib/drama/skills/short-drama/assets/project-template/short-drama.json +3 -0
  7. package/lib/drama/skills/short-drama/references/creator-documents.md +3 -0
  8. package/lib/drama/skills/short-drama/references/knowhow-index.md +15 -0
  9. package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +14 -0
  10. package/lib/drama/skills/short-drama/scripts/project_tool.py +131 -0
  11. package/lib/drama/skills/short-drama-assets/SKILL.md +2 -1
  12. package/lib/drama/skills/short-drama-assets/references/asset-review-checklist.md +2 -0
  13. package/lib/drama/skills/short-drama-assets/references/character-and-look.md +10 -0
  14. package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +6 -9
  15. package/lib/drama/skills/short-drama-assets/references/era-anchors.md +37 -0
  16. package/lib/drama/skills/short-drama-assets/references/stage-contract.md +2 -0
  17. package/lib/drama/skills/short-drama-assets/references/voice-direction.md +28 -0
  18. package/lib/drama/skills/short-drama-develop/SKILL.md +10 -4
  19. package/lib/drama/skills/short-drama-develop/assets/adaptation-map.example.jsonl +1 -1
  20. package/lib/drama/skills/short-drama-develop/assets/creative-brief.md +8 -0
  21. package/lib/drama/skills/short-drama-develop/references/adaptation-craft.md +80 -13
  22. package/lib/drama/skills/short-drama-develop/references/episode-design.md +95 -12
  23. package/lib/drama/skills/short-drama-develop/references/genre-and-hook-playbook.md +9 -5
  24. package/lib/drama/skills/short-drama-develop/references/genre-cards//345/244/215/344/273/207/346/211/223/350/204/270.md +1 -1
  25. package/lib/drama/skills/short-drama-develop/references/genre-cards//347/263/273/347/273/237/346/265/201.md +51 -0
  26. package/lib/drama/skills/short-drama-develop/references/genre-cards//351/200/206/350/242/255.md +51 -0
  27. package/lib/drama/skills/short-drama-develop/references/genre-cards//351/207/215/347/224/237/347/251/277/350/266/212.md +51 -0
  28. package/lib/drama/skills/short-drama-develop/references/genre-cards.md +10 -7
  29. package/lib/drama/skills/short-drama-develop/references/premise-devices.md +15 -9
  30. package/lib/drama/skills/short-drama-develop/references/serial-character-and-memory.md +3 -2
  31. package/lib/drama/skills/short-drama-develop/references/stage-contract.md +14 -7
  32. package/lib/drama/skills/short-drama-develop/references/story-craft.md +7 -3
  33. package/lib/drama/skills/short-drama-edit/SKILL.md +65 -44
  34. package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +49 -13
  35. package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +4 -2
  36. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Overlay.tsx +31 -0
  37. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +5 -5
  38. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +68 -69
  39. package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +39 -29
  40. package/lib/drama/skills/short-drama-edit/assets/remotion/src/rules.mjs +188 -0
  41. package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +26 -13
  42. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/Card.tsx +72 -0
  43. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/CornerChip.tsx +39 -0
  44. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/ScreenText.tsx +36 -0
  45. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/SystemPanel.tsx +44 -0
  46. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/TaskPanel.tsx +100 -0
  47. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/chrome.tsx +197 -0
  48. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/tokens.ts +62 -0
  49. package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +1 -0
  50. package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +6 -4
  51. package/lib/drama/skills/short-drama-edit/references/cut-craft.md +26 -67
  52. package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +31 -56
  53. package/lib/drama/skills/short-drama-edit/references/generated-footage.md +42 -78
  54. package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +44 -92
  55. package/lib/drama/skills/short-drama-edit/references/stage-contract.md +14 -16
  56. package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1272 -125
  57. package/lib/drama/skills/short-drama-edit/scripts/selftest.py +113 -9
  58. package/lib/drama/skills/short-drama-image-prompts/SKILL.md +2 -0
  59. package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +11 -0
  60. package/lib/drama/skills/short-drama-novel-analyze/SKILL.md +3 -3
  61. package/lib/drama/skills/short-drama-novel-analyze/assets/episode-candidate.example.jsonl +2 -2
  62. package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-triage.md +8 -4
  63. package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-value.md +10 -3
  64. package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +25 -1
  65. package/lib/drama/skills/short-drama-novel-analyze/references/stage-contract.md +1 -0
  66. package/lib/drama/skills/short-drama-produce/SKILL.md +5 -1
  67. package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +14 -20
  68. package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +8 -26
  69. package/lib/drama/skills/short-drama-produce/references/providers/minimax-speech.md +41 -0
  70. package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +142 -1
  71. package/lib/drama/skills/short-drama-review/SKILL.md +4 -5
  72. package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +6 -19
  73. package/lib/drama/skills/short-drama-review/references/review-method.md +6 -1
  74. package/lib/drama/skills/short-drama-review/references/rubric-assets-prompts.md +11 -0
  75. package/lib/drama/skills/short-drama-review/references/rubric-story-script.md +77 -3
  76. package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +24 -35
  77. package/lib/drama/skills/short-drama-review/references/stage-contract.md +3 -0
  78. package/lib/drama/skills/short-drama-storyboard/SKILL.md +23 -11
  79. package/lib/drama/skills/short-drama-storyboard/references/blocking-playbooks.md +1 -1
  80. package/lib/drama/skills/short-drama-storyboard/references/lighting-craft.md +39 -0
  81. package/lib/drama/skills/short-drama-storyboard/references/production-shot-grammar.md +2 -2
  82. package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +139 -34
  83. package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +5 -3
  84. package/lib/drama/skills/short-drama-video-prompts/SKILL.md +15 -12
  85. package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +29 -0
  86. package/lib/drama/skills/short-drama-video-prompts/references/delivery-profile.md +4 -5
  87. package/lib/drama/skills/short-drama-video-prompts/references/generability.md +4 -2
  88. package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +52 -39
  89. package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +24 -21
  90. package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +9 -23
  91. package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +14 -26
  92. package/lib/drama/skills/short-drama-video-prompts/references/review-and-fixtures.md +1 -1
  93. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +2 -3
  94. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +34 -9
  95. package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +3 -2
  96. package/lib/drama/skills/short-drama-video-prompts/references/target-model-profile.md +8 -1
  97. package/lib/drama/skills/short-drama-video-prompts/references/wan-3.0.md +103 -0
  98. package/lib/drama/skills/short-drama-video-prompts/scripts/motion_timing_check.py +8 -7
  99. package/lib/drama/skills/short-drama-write/SKILL.md +10 -7
  100. package/lib/drama/skills/short-drama-write/references/dialogue-craft.md +1 -1
  101. package/lib/drama/skills/short-drama-write/references/script-craft.md +56 -3
  102. package/lib/drama/skills/short-drama-write/references/stage-contract.md +4 -0
  103. package/lib/drama/skills/short-drama-write/scripts/duration_estimate.py +48 -2
  104. package/lib/index.js +346 -98
  105. package/lib/index.js.map +4 -4
  106. package/lib/novel-to-game/README.md +299 -59
  107. package/lib/novel-to-game/README_ZH.md +299 -56
  108. package/lib/novel-to-game/VERSION +1 -1
  109. package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +3 -1
  110. package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +11 -3
  111. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +397 -8
  112. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +0 -31
  113. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +71 -73
  114. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +78 -89
  115. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +37 -14
  116. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +5 -5
  117. package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +2 -1
  118. package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +11 -16
  119. package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +11 -11
  120. package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +23 -0
  121. package/lib/novel-to-game/manifest.json +77 -87
  122. package/lib/novel-to-game/skills/game-art-direction/SKILL.md +7 -12
  123. package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +27 -106
  124. package/lib/novel-to-game/skills/game-build/SKILL.md +13 -14
  125. package/lib/novel-to-game/skills/game-build/references/blender-asset-workflow.md +24 -0
  126. package/lib/novel-to-game/skills/game-build/references/build-brief-contract.md +45 -82
  127. package/lib/novel-to-game/skills/game-build/references/generative-media-pipeline.md +14 -45
  128. package/lib/novel-to-game/skills/game-build/references/playable-model-contract.md +30 -65
  129. package/lib/novel-to-game/skills/game-build/references/tts-production-contract.md +13 -27
  130. package/lib/novel-to-game/skills/game-concept/SKILL.md +13 -15
  131. package/lib/novel-to-game/skills/game-concept/references/concept-method.md +28 -75
  132. package/lib/novel-to-game/skills/game-qa/SKILL.md +6 -7
  133. package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +9 -5
  134. package/lib/novel-to-game/skills/game-world-design/SKILL.md +12 -16
  135. package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +23 -72
  136. package/lib/novel-to-game/skills/game-world-design/references/numeric-design-method.md +14 -48
  137. package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +36 -103
  138. package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +4 -10
  139. package/lib/novel-to-game/skills/novel-game-analyze/references/gameability-protocol.md +4 -4
  140. package/lib/novel-to-game/skills/novel-to-game/SKILL.md +9 -21
  141. package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +5 -4
  142. package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +5 -8
  143. package/lib/oh-story/manifest.json +607 -327
  144. package/lib/oh-story/roles/chapter-extractor.md +177 -237
  145. package/lib/oh-story/roles/character-designer.md +1 -2
  146. package/lib/oh-story/roles/consistency-checker.md +15 -13
  147. package/lib/oh-story/roles/narrative-writer.md +36 -38
  148. package/lib/oh-story/roles/story-architect.md +9 -61
  149. package/lib/oh-story/roles/story-explorer.md +20 -125
  150. package/lib/oh-story/roles/story-researcher.md +0 -1
  151. package/lib/oh-story/skills/story/SKILL.md +15 -9
  152. package/lib/oh-story/skills/story/VERSION +1 -1
  153. package/lib/oh-story/skills/story/references/author-memory-maintenance.md +75 -0
  154. package/lib/oh-story/skills/story/references/author-memory.md +46 -94
  155. package/lib/oh-story/skills/story/scripts/author_memory_commit.py +934 -170
  156. package/lib/oh-story/skills/story-cover/SKILL.md +10 -1
  157. package/lib/oh-story/skills/story-deslop/SKILL.md +59 -73
  158. package/lib/oh-story/skills/story-deslop/references/agent-calls.md +5 -0
  159. package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +12 -11
  160. package/lib/oh-story/skills/story-deslop/references/author-memory-maintenance.md +75 -0
  161. package/lib/oh-story/skills/story-deslop/references/author-memory.md +46 -94
  162. package/lib/oh-story/skills/story-deslop/references/banned-words.md +2 -2
  163. package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +22 -5
  164. package/lib/oh-story/skills/story-deslop/references/style-resolution.md +4 -4
  165. package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +934 -170
  166. package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +155 -8
  167. package/lib/oh-story/skills/story-import/SKILL.md +64 -584
  168. package/lib/oh-story/skills/story-import/references/character-state-reverse.md +1 -1
  169. package/lib/oh-story/skills/story-import/references/deep-analysis.md +47 -0
  170. package/lib/oh-story/skills/story-import/references/format-and-structure.md +1 -1
  171. package/lib/oh-story/skills/story-import/references/import-report.md +64 -0
  172. package/lib/oh-story/skills/story-import/references/import-special-cases.md +34 -0
  173. package/lib/oh-story/skills/story-import/references/import-tracking.md +95 -0
  174. package/lib/oh-story/skills/story-import/references/length-routing.md +1 -1
  175. package/lib/oh-story/skills/story-import/references/outline-reverse-rules.md +79 -0
  176. package/lib/oh-story/skills/story-import/references/outline-reverse.md +24 -0
  177. package/lib/oh-story/skills/story-import/references/state-tracking.md +4 -69
  178. package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +98 -92
  179. package/lib/oh-story/skills/story-import/references/structure-mapping-short.md +24 -12
  180. package/lib/oh-story/skills/story-import/references/tracking-initialization.md +1 -1
  181. package/lib/oh-story/skills/story-import/references/tracking-transaction.md +15 -11
  182. package/lib/oh-story/skills/story-import/scripts/build_outline_brief.py +332 -0
  183. package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +132 -27
  184. package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +478 -15
  185. package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +182 -23
  186. package/lib/oh-story/skills/story-long-analyze/SKILL.md +81 -270
  187. package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +252 -0
  188. package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +3 -3
  189. package/lib/oh-story/skills/story-long-analyze/references/final-checks.md +19 -0
  190. package/lib/oh-story/skills/story-long-analyze/references/index-rebuild.md +11 -0
  191. package/lib/oh-story/skills/story-long-analyze/references/inspiration-library.md +105 -0
  192. package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +138 -64
  193. package/lib/oh-story/skills/story-long-analyze/references/semantic-acceptance-fixtures.md +84 -0
  194. package/lib/oh-story/skills/story-long-analyze/references/stage1-golden-chapters.md +128 -0
  195. package/lib/oh-story/skills/story-long-analyze/references/stage2-extraction.md +229 -0
  196. package/lib/oh-story/skills/story-long-analyze/references/stage3-plot-rhythm.md +480 -0
  197. package/lib/oh-story/skills/story-long-analyze/references/stage4-characters-settings.md +195 -0
  198. package/lib/oh-story/skills/story-long-analyze/references/stage5-report.md +33 -0
  199. package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +55 -128
  200. package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +6 -6
  201. package/lib/oh-story/skills/story-long-analyze/references/synthesis-inputs.md +39 -0
  202. package/lib/oh-story/skills/story-long-analyze/scripts/build_chapter_index.py +466 -0
  203. package/lib/oh-story/skills/story-long-analyze/scripts/inspect_existing_assets.py +702 -0
  204. package/lib/oh-story/skills/story-long-analyze/scripts/inspiration_index.py +864 -0
  205. package/lib/oh-story/skills/story-long-analyze/scripts/manage_analysis_run.py +1145 -0
  206. package/lib/oh-story/skills/story-long-analyze/scripts/render_relation_chart.py +425 -0
  207. package/lib/oh-story/skills/story-long-scan/SKILL.md +45 -194
  208. package/lib/oh-story/skills/story-long-scan/references/platform-ciweimao.md +19 -0
  209. package/lib/oh-story/skills/story-long-scan/references/platform-fanqie.md +45 -0
  210. package/lib/oh-story/skills/story-long-scan/references/platform-jjwxc.md +28 -0
  211. package/lib/oh-story/skills/story-long-scan/references/platform-qidian.md +35 -0
  212. package/lib/oh-story/skills/story-long-scan/references/platform-qimao.md +27 -0
  213. package/lib/oh-story/skills/story-long-scan/references/topic-decision.md +6 -2
  214. package/lib/oh-story/skills/story-long-write/SKILL.md +49 -81
  215. package/lib/oh-story/skills/story-long-write/references/agent-calls.md +47 -0
  216. package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +12 -11
  217. package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +24 -202
  218. package/lib/oh-story/skills/story-long-write/references/author-memory-maintenance.md +75 -0
  219. package/lib/oh-story/skills/story-long-write/references/author-memory.md +46 -94
  220. package/lib/oh-story/skills/story-long-write/references/banned-words.md +2 -2
  221. package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +7 -11
  222. package/lib/oh-story/skills/story-long-write/references/character-relations.md +49 -1
  223. package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +26 -0
  224. package/lib/oh-story/skills/story-long-write/references/deslop-gates.md +171 -0
  225. package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +4 -0
  226. package/lib/oh-story/skills/story-long-write/references/emotion-on-page.md +116 -0
  227. package/lib/oh-story/skills/story-long-write/references/emotional-arc-design.md +1 -114
  228. package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +2 -2
  229. package/lib/oh-story/skills/story-long-write/references/genre-prose-cards.md +1 -1
  230. package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +7 -15
  231. package/lib/oh-story/skills/story-long-write/references/long-format.md +0 -8
  232. package/lib/oh-story/skills/story-long-write/references/long-genre-catalog.md +1 -1
  233. package/lib/oh-story/skills/story-long-write/references/long-genre-mechanics.md +3 -3
  234. package/lib/oh-story/skills/story-long-write/references/opening-design.md +2 -2
  235. package/lib/oh-story/skills/story-long-write/references/outline-conflict.md +4 -4
  236. package/lib/oh-story/skills/story-long-write/references/outline-methods.md +7 -7
  237. package/lib/oh-story/skills/story-long-write/references/outline-rhythm.md +3 -3
  238. package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +14 -69
  239. package/lib/oh-story/skills/story-long-write/references/plot-frameworks.md +1 -1
  240. package/lib/oh-story/skills/story-long-write/references/plot-special-topics.md +2 -2
  241. package/lib/oh-story/skills/story-long-write/references/project-files.md +19 -13
  242. package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +13 -5
  243. package/lib/oh-story/skills/story-long-write/references/reference-index.md +5 -6
  244. package/lib/oh-story/skills/story-long-write/references/stop-and-fix.md +9 -0
  245. package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -58
  246. package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
  247. package/lib/oh-story/skills/story-long-write/references/style-resolution.md +4 -4
  248. package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +1 -1
  249. package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +15 -11
  250. package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +81 -121
  251. package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +41 -139
  252. package/lib/oh-story/skills/story-long-write/references/workflow-outline.md +157 -0
  253. package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +57 -67
  254. package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +112 -253
  255. package/lib/oh-story/skills/story-long-write/references/workflow-volume.md +142 -0
  256. package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +6 -4
  257. package/lib/oh-story/skills/story-long-write/references/writing-craft.md +19 -65
  258. package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +934 -170
  259. package/lib/oh-story/skills/story-long-write/scripts/build_architect_brief.py +260 -0
  260. package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +226 -25
  261. package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +155 -8
  262. package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +132 -27
  263. package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +7 -2
  264. package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +7 -4
  265. package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +304 -46
  266. package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +478 -15
  267. package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +182 -23
  268. package/lib/oh-story/skills/story-review/SKILL.md +31 -302
  269. package/lib/oh-story/skills/story-review/references/agent-prompts.md +184 -0
  270. package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +12 -11
  271. package/lib/oh-story/skills/story-review/references/author-memory-maintenance.md +75 -0
  272. package/lib/oh-story/skills/story-review/references/author-memory.md +46 -94
  273. package/lib/oh-story/skills/story-review/references/banned-words.md +2 -2
  274. package/lib/oh-story/skills/story-review/references/batch-review.md +19 -0
  275. package/lib/oh-story/skills/story-review/references/character-relations.md +49 -1
  276. package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +4 -0
  277. package/lib/oh-story/skills/story-review/references/review-quality.md +6 -11
  278. package/lib/oh-story/skills/story-review/references/review-tracking.md +10 -0
  279. package/lib/oh-story/skills/story-review/references/solo.md +52 -0
  280. package/lib/oh-story/skills/story-review/references/style-resolution.md +4 -4
  281. package/lib/oh-story/skills/story-review/references/tracking-initialization.md +1 -1
  282. package/lib/oh-story/skills/story-review/references/tracking-transaction.md +15 -11
  283. package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +934 -170
  284. package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +155 -8
  285. package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +478 -15
  286. package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +182 -23
  287. package/lib/oh-story/skills/story-setup/SKILL.md +71 -452
  288. package/lib/oh-story/skills/story-setup/references/agent-references/agent-quality.md +4 -4
  289. package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +12 -11
  290. package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +2 -2
  291. package/lib/oh-story/skills/story-setup/references/agent-references/benchmark-style-load.md +107 -0
  292. package/lib/oh-story/skills/story-setup/references/agent-references/character-relations.md +49 -1
  293. package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +22 -5
  294. package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +4 -0
  295. package/lib/oh-story/skills/story-setup/references/agent-references/emotion-on-page.md +116 -0
  296. package/lib/oh-story/skills/story-setup/references/agent-references/emotional-arc-design.md +1 -114
  297. package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +1 -1
  298. package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards.md +1 -1
  299. package/lib/oh-story/skills/story-setup/references/agent-references/long-emotional-methods.md +2 -2
  300. package/lib/oh-story/skills/story-setup/references/agent-references/long-genre-catalog.md +1 -1
  301. package/lib/oh-story/skills/story-setup/references/agent-references/long-genre-mechanics.md +3 -3
  302. package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +7 -5
  303. package/lib/oh-story/skills/story-setup/references/agent-references/opening-design.md +2 -2
  304. package/lib/oh-story/skills/story-setup/references/agent-references/outline-conflict.md +4 -4
  305. package/lib/oh-story/skills/story-setup/references/agent-references/outline-methods.md +7 -7
  306. package/lib/oh-story/skills/story-setup/references/agent-references/outline-rhythm.md +3 -3
  307. package/lib/oh-story/skills/story-setup/references/agent-references/short-emotional-methods.md +1 -1
  308. package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +0 -15
  309. package/lib/oh-story/skills/story-setup/references/agent-references/short-reversal.md +1 -1
  310. package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -58
  311. package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
  312. package/lib/oh-story/skills/story-setup/references/agent-references/style-resolution.md +4 -4
  313. package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +19 -65
  314. package/lib/oh-story/skills/story-setup/references/diagnostics.md +4 -4
  315. package/lib/oh-story/skills/story-short-analyze/SKILL.md +56 -110
  316. package/lib/oh-story/skills/story-short-analyze/references/analysis-character-relations.md +1 -1
  317. package/lib/oh-story/skills/story-short-analyze/references/analysis-method.md +42 -0
  318. package/lib/oh-story/skills/story-short-analyze/references/optional-modules.md +97 -0
  319. package/lib/oh-story/skills/story-short-analyze/references/output-contract.md +9 -47
  320. package/lib/oh-story/skills/story-short-analyze/references/quality-checklist.md +80 -0
  321. package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +4 -4
  322. package/lib/oh-story/skills/story-short-analyze/references/stage2-3-structure-emotion.md +308 -0
  323. package/lib/oh-story/skills/story-short-analyze/references/stage4-6-reversal-summary.md +611 -0
  324. package/lib/oh-story/skills/story-short-scan/SKILL.md +35 -65
  325. package/lib/oh-story/skills/story-short-scan/references/manual-rank-input.md +36 -0
  326. package/lib/oh-story/skills/story-short-scan/references/platform-dianzhong.md +24 -0
  327. package/lib/oh-story/skills/story-short-scan/references/platform-heiyan.md +21 -0
  328. package/lib/oh-story/skills/story-short-scan/references/topic-match.md +38 -0
  329. package/lib/oh-story/skills/story-short-write/SKILL.md +23 -175
  330. package/lib/oh-story/skills/story-short-write/references/agent-calls.md +13 -0
  331. package/lib/oh-story/skills/story-short-write/references/author-memory-maintenance.md +75 -0
  332. package/lib/oh-story/skills/story-short-write/references/author-memory.md +46 -94
  333. package/lib/oh-story/skills/story-short-write/references/banned-words.md +2 -2
  334. package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +1 -21
  335. package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +4 -0
  336. package/lib/oh-story/skills/story-short-write/references/emotional-methods.md +1 -1
  337. package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +0 -15
  338. package/lib/oh-story/skills/story-short-write/references/output-contract.md +9 -47
  339. package/lib/oh-story/skills/story-short-write/references/reference-index.md +17 -47
  340. package/lib/oh-story/skills/story-short-write/references/scene-craft.md +40 -0
  341. package/lib/oh-story/skills/story-short-write/references/short-craft.md +7 -43
  342. package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -3
  343. package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -1
  344. package/lib/oh-story/skills/story-short-write/references/short-reversal.md +1 -1
  345. package/lib/oh-story/skills/story-short-write/references/style-resolution.md +4 -4
  346. package/lib/oh-story/skills/story-short-write/references/submission-craft.md +1 -1
  347. package/lib/oh-story/skills/story-short-write/references/villain-and-reveal.md +5 -10
  348. package/lib/oh-story/skills/story-short-write/references/workflow-design.md +21 -13
  349. package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +116 -0
  350. package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +99 -0
  351. package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +7 -119
  352. package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +934 -170
  353. package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +155 -8
  354. package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +7 -2
  355. package/lib/types/client/drama-production-view.d.ts.map +1 -1
  356. package/lib/types/client/file-activity.d.ts +19 -1
  357. package/lib/types/client/file-activity.d.ts.map +1 -1
  358. package/lib/types/client/index.d.ts.map +1 -1
  359. package/lib/types/client/production-prompts.d.ts +7 -0
  360. package/lib/types/client/production-prompts.d.ts.map +1 -1
  361. package/lib/types/client/production-runtime.d.ts +16 -0
  362. package/lib/types/client/production-runtime.d.ts.map +1 -1
  363. package/lib/types/client/video-studio.d.ts.map +1 -1
  364. package/lib/types/drama-adapters.d.ts +5 -3
  365. package/lib/types/drama-adapters.d.ts.map +1 -1
  366. package/lib/types/native-hooks.d.ts +53 -1
  367. package/lib/types/native-hooks.d.ts.map +1 -1
  368. package/lib/types/role-identity.d.ts +17 -0
  369. package/lib/types/role-identity.d.ts.map +1 -0
  370. package/lib/types/role-tool.d.ts.map +1 -1
  371. package/lib/types/skill-provider.d.ts.map +1 -1
  372. package/lib/types/video-project.d.ts.map +1 -1
  373. package/lib/types/workspace-route.d.ts.map +1 -1
  374. package/lib/video-recap/CHANGELOG.md +60 -1
  375. package/lib/video-recap/README.en.md +348 -137
  376. package/lib/video-recap/README.md +340 -136
  377. package/lib/video-recap/manifest.json +406 -251
  378. package/lib/video-recap/skills/video-assemble/SKILL.md +30 -15
  379. package/lib/video-recap/skills/video-assemble/references/audio-modes.md +63 -0
  380. package/lib/video-recap/skills/video-assemble/references/explicit-audio-mix.md +75 -0
  381. package/lib/video-recap/skills/video-assemble/references/foreground-compose.md +118 -0
  382. package/lib/video-recap/skills/video-assemble/references/narration-adoption.md +103 -0
  383. package/lib/video-recap/skills/video-assemble/references/packaging.md +45 -0
  384. package/lib/video-recap/skills/video-assemble/references/pair-media.md +74 -0
  385. package/lib/video-recap/skills/video-assemble/references/source-score.md +147 -0
  386. package/lib/video-recap/skills/video-assemble/references/subtitle-track.md +202 -0
  387. package/lib/video-recap/skills/video-assemble/scripts/adoption/__init__.py +1 -0
  388. package/lib/video-recap/skills/video-assemble/scripts/adoption/audio_mix_binding.py +279 -0
  389. package/lib/video-recap/skills/video-assemble/scripts/adoption/frozen_audio.py +187 -0
  390. package/lib/video-recap/skills/video-assemble/scripts/adoption/narration_binding.py +323 -0
  391. package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_inputs.py +109 -0
  392. package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_publish.py +130 -0
  393. package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +10 -46
  394. package/lib/video-recap/skills/video-assemble/scripts/assemble.py +378 -119
  395. package/lib/video-recap/skills/video-assemble/scripts/assemble_constants.py +29 -12
  396. package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +95 -44
  397. package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +75 -32
  398. package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +11 -11
  399. package/lib/video-recap/skills/video-assemble/scripts/compose_foreground.py +293 -0
  400. package/lib/video-recap/skills/video-assemble/scripts/export_jianying.py +71 -78
  401. package/lib/video-recap/skills/video-assemble/scripts/jianying/__init__.py +1 -0
  402. package/lib/video-recap/skills/video-assemble/scripts/{jianying_builders.py → jianying/builders.py} +39 -67
  403. package/lib/video-recap/skills/video-assemble/scripts/{jianying_model.py → jianying/model.py} +3 -11
  404. package/lib/video-recap/skills/video-assemble/scripts/{jianying_optional.py → jianying/optional.py} +1 -1
  405. package/lib/video-recap/skills/video-assemble/scripts/jianying/schema.py +53 -0
  406. package/lib/video-recap/skills/video-assemble/scripts/{jianying_templates.py → jianying/templates.py} +1 -1
  407. package/lib/video-recap/skills/video-assemble/scripts/{jianying_timeline_contract.py → jianying/timeline_contract.py} +34 -13
  408. package/lib/video-recap/skills/video-assemble/scripts/{jianying_writer.py → jianying/writer.py} +7 -17
  409. package/lib/video-recap/skills/video-assemble/scripts/lib.py +37 -4
  410. package/lib/video-recap/skills/video-assemble/scripts/media.py +12 -21
  411. package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +64 -34
  412. package/lib/video-recap/skills/video-assemble/scripts/packaging.py +122 -0
  413. package/lib/video-recap/skills/video-assemble/scripts/pair_media.py +216 -0
  414. package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +1 -3
  415. package/lib/video-recap/skills/video-assemble/scripts/source_score.py +469 -0
  416. package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +25 -9
  417. package/lib/video-recap/skills/video-assemble/scripts/subtitles/__init__.py +1 -0
  418. package/lib/video-recap/skills/video-assemble/scripts/{subtitle_core.py → subtitles/core.py} +13 -6
  419. package/lib/video-recap/skills/video-assemble/scripts/{subtitle_render.py → subtitles/render.py} +5 -4
  420. package/lib/video-recap/skills/video-assemble/scripts/subtitles/track.py +324 -0
  421. package/lib/video-recap/skills/video-assemble/scripts/subtitles/track_binding.py +200 -0
  422. package/lib/video-recap/skills/video-assemble/scripts/timeline.py +30 -46
  423. package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +91 -7
  424. package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +22 -8
  425. package/lib/video-recap/skills/video-cut/SKILL.md +34 -16
  426. package/lib/video-recap/skills/video-cut/references/shot-review.md +50 -0
  427. package/lib/video-recap/skills/video-cut/scripts/cut.py +2 -28
  428. package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +58 -62
  429. package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +21 -106
  430. package/lib/video-recap/skills/video-cut/scripts/cut_render.py +14 -9
  431. package/lib/video-recap/skills/video-cut/scripts/lib.py +39 -0
  432. package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +2 -155
  433. package/lib/video-recap/skills/video-cut/scripts/narrative_selection.py +244 -0
  434. package/lib/video-recap/skills/video-cut/scripts/shot_review.py +357 -0
  435. package/lib/video-recap/skills/video-recap/SKILL.md +86 -42
  436. package/lib/video-recap/skills/video-recap/references/audio-routing.md +126 -0
  437. package/lib/video-recap/skills/video-recap/references/config-playbook.md +12 -8
  438. package/lib/video-recap/skills/video-recap/references/data-schema.md +44 -33
  439. package/lib/video-recap/skills/video-recap/references/resource-library.md +151 -0
  440. package/lib/video-recap/skills/video-recap/references/shift-left-qc-schema.md +1 -1
  441. package/lib/video-recap/skills/video-recap/scripts/doctor.py +123 -30
  442. package/lib/video-recap/skills/video-recap/scripts/final_qc.py +22 -75
  443. package/lib/video-recap/skills/video-recap/scripts/lib.py +3 -3
  444. package/lib/video-recap/skills/video-recap/scripts/library.py +509 -0
  445. package/lib/video-recap/skills/video-recap/scripts/materials.py +63 -91
  446. package/lib/video-recap/skills/video-recap/scripts/mimo_qc.py +8 -70
  447. package/lib/video-recap/skills/video-recap/scripts/project_binding.py +286 -0
  448. package/lib/video-recap/skills/video-recap/scripts/qc/__init__.py +1 -0
  449. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_client.py → qc/mimo_client.py} +1 -1
  450. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_evidence.py → qc/mimo_evidence.py} +33 -66
  451. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_observations.py → qc/mimo_observations.py} +3 -11
  452. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_payload.py → qc/mimo_payload.py} +4 -7
  453. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_report.py → qc/mimo_report.py} +17 -28
  454. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_runner.py → qc/mimo_runner.py} +2 -2
  455. package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +0 -19
  456. package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +119 -50
  457. package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +32 -114
  458. package/lib/video-recap/skills/video-recap/scripts/recap_review.py +9 -23
  459. package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +387 -334
  460. package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +23 -23
  461. package/lib/video-recap/skills/video-recap/scripts/recap_source.py +278 -0
  462. package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +25 -12
  463. package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +59 -52
  464. package/lib/video-recap/skills/video-recap/scripts/resource_lock.py +162 -0
  465. package/lib/video-recap/skills/video-script/SKILL.md +16 -13
  466. package/lib/video-recap/skills/video-script/references/creative-editing-playbook.md +9 -5
  467. package/lib/video-recap/skills/video-script/references/promotional-copy.md +68 -0
  468. package/lib/video-recap/skills/video-script/references/research-guide.md +1 -1
  469. package/lib/video-recap/skills/video-script/scripts/evidence_bundle.py +24 -76
  470. package/lib/video-recap/skills/video-script/scripts/lib.py +10 -87
  471. package/lib/video-recap/skills/video-script/scripts/narration_lint.py +63 -39
  472. package/lib/video-recap/skills/video-script/scripts/review.py +0 -2
  473. package/lib/video-recap/skills/video-script/scripts/review_grounding.py +35 -59
  474. package/lib/video-recap/skills/video-script/scripts/review_response.py +66 -128
  475. package/lib/video-recap/skills/video-script/scripts/review_runner.py +12 -20
  476. package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +4 -4
  477. package/lib/video-recap/skills/video-script/scripts/validate.py +53 -42
  478. package/lib/video-recap/skills/video-understanding/SKILL.md +6 -4
  479. package/lib/video-recap/skills/video-understanding/references/data-schema.md +50 -156
  480. package/lib/video-recap/skills/video-understanding/references/research-guide.md +4 -4
  481. package/lib/video-recap/skills/video-understanding/scripts/asr.py +85 -65
  482. package/lib/video-recap/skills/video-understanding/scripts/asr_timing_evidence.py +270 -0
  483. package/lib/video-recap/skills/video-understanding/scripts/brief.py +2 -5
  484. package/lib/video-recap/skills/video-understanding/scripts/briefing/__init__.py +1 -0
  485. package/lib/video-recap/skills/{video-script/scripts/agent_brief.py → video-understanding/scripts/briefing/builder.py} +38 -35
  486. package/lib/video-recap/skills/video-understanding/scripts/{brief_context.py → briefing/context.py} +4 -35
  487. package/lib/video-recap/skills/{video-script/scripts/brief_inputs.py → video-understanding/scripts/briefing/inputs.py} +9 -31
  488. package/lib/video-recap/skills/{video-script/scripts/brief_timeline.py → video-understanding/scripts/briefing/timeline.py} +5 -6
  489. package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +65 -116
  490. package/lib/video-recap/skills/video-understanding/scripts/detect.py +31 -40
  491. package/lib/video-recap/skills/video-understanding/scripts/lib.py +30 -86
  492. package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +63 -39
  493. package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +4 -4
  494. package/lib/video-recap/skills/video-understanding/scripts/storyboard.py +17 -79
  495. package/lib/video-recap/skills/video-understanding/scripts/understanding_brief.py +14 -40
  496. package/lib/video-recap/skills/video-understanding/scripts/understanding_cache.py +64 -46
  497. package/lib/video-recap/skills/video-understanding/scripts/understanding_runner.py +31 -11
  498. package/lib/video-recap/skills/video-understanding/scripts/understanding_storyboard.py +19 -14
  499. package/lib/video-recap/skills/video-understanding/scripts/vlm.py +80 -108
  500. package/lib/video-recap/skills/video-voiceover/SKILL.md +29 -19
  501. package/lib/video-recap/skills/video-voiceover/references/index-tts.md +31 -0
  502. package/lib/video-recap/skills/video-voiceover/scripts/approved_text_policy.py +123 -0
  503. package/lib/video-recap/skills/video-voiceover/scripts/dub.py +51 -59
  504. package/lib/video-recap/skills/video-voiceover/scripts/lib.py +8 -44
  505. package/lib/video-recap/skills/video-voiceover/scripts/providers/__init__.py +1 -0
  506. package/lib/video-recap/skills/video-voiceover/scripts/providers/index_tts.py +184 -0
  507. package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +212 -134
  508. package/package.json +45 -45
  509. package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +0 -58
  510. package/lib/novel-to-game/skills/game-world-design/references/game-writing-craft.md +0 -53
  511. package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -38
  512. package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +0 -530
  513. package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +0 -559
  514. package/lib/oh-story/skills/story-long-scan/references/scan-output-format.md +0 -207
  515. package/lib/oh-story/skills/story-long-write/references/state-tracking.md +0 -108
  516. package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +0 -678
  517. package/lib/oh-story/skills/story-short-analyze/references/output-templates.md +0 -561
  518. package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +0 -98
  519. package/lib/video-recap/skills/video-recap/references/creative-editing-playbook.md +0 -225
  520. package/lib/video-recap/skills/video-recap/references/research-guide.md +0 -74
  521. package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +0 -250
  522. package/lib/video-recap/skills/video-script/scripts/brief_context.py +0 -348
  523. package/lib/video-recap/skills/video-script/scripts/narration.py +0 -12
  524. package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +0 -399
  525. package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +0 -290
  526. package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +0 -327
  527. /package/lib/video-recap/skills/video-assemble/scripts/{jianying_tracks.py → jianying/tracks.py} +0 -0
  528. /package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_contract.py → qc/mimo_contract.py} +0 -0
  529. /package/lib/video-recap/skills/video-voiceover/scripts/{fish_audio.py → providers/fish_audio.py} +0 -0
@@ -1,6 +1,5 @@
1
1
  """Own recap timeline artifacts, continuation state, and cut QC surfaces."""
2
2
 
3
- import hashlib
4
3
  import json
5
4
  import os
6
5
  import shlex
@@ -15,6 +14,7 @@ from recap_runtime import (
15
14
  _multi_run_manifest_payload,
16
15
  _run_manifest_payload,
17
16
  )
17
+ from recap_source import audio_binding, uses_narration
18
18
 
19
19
  ASSEMBLY_MANIFEST = "assembly_manifest.json"
20
20
 
@@ -23,6 +23,7 @@ PHASE_LEDGER = "recap_phase.json"
23
23
  CUT_TIMELINE_CRAFT_BULLETS = [
24
24
  "- 片段顺序必须服务同一条故事主线,而不是无序高光;可使用 0–1 个 cold open,随后回到 setup → turn → escalation → payoff。",
25
25
  "- 每个片段必须对应 `recap_story_plan.json` 中的一个 change-based beat;删除后不损失因果、人物或情绪的片段通常不保留。",
26
+ "- 已从源证据确认的必保问答、反应或兑现段,写入同一 `clip_plan.json.required_evidence`(nodes登记id/source绝对路径/start/end原片秒/track/content,before登记必要先后);只锁具体区间,不锁整个beat。剪点吸附后工具会核验,reason或花字不能代替缺失的源段。",
26
27
  "- `reason` 统一写成 `beat_id | function | change | POV | preferred moment | 入点 | 出点`,不能只写 hook、重要剧情或事件摘要。",
27
28
  "- 优先保留因果、揭示、决定、关系移动、情绪转向与不可替代的表演/反应;跳过片尾、广告、重复静态画面和水印废片段。",
28
29
  "- 片段追求最短但完整:建立镜头可以短,关键表演/反应允许多停一点;在完整台词、完整动作或自然声音边界结束,避免原声从半句中切入或切出。",
@@ -104,24 +105,15 @@ def _print_grounding_qc_pointer(work_dir):
104
105
  def _print_narration_review_pointer(work_dir, *, review_ran=True):
105
106
  """Surface the advisory narration review produced by this run, if any.
106
107
 
107
- Review is optional/fail-open. Avoid surfacing a stale narration_review.md from an
108
- older run when review was disabled or failed before producing fresh artifacts.
108
+ Review is optional/fail-open: review_ran=False (disabled or failed) prints nothing so a
109
+ stale narration_review.md from an older run is never surfaced. When it ran, video-script's
110
+ review_runner has written both narration_review.json and .md.
109
111
  """
110
112
  _print_grounding_qc_pointer(work_dir)
111
113
  if not review_ran:
112
114
  return
113
115
  review_md = Path(work_dir) / "narration_review.md"
114
- if not review_md.exists():
115
- return
116
- review_json = Path(work_dir) / "narration_review.json"
117
- if not review_json.exists():
118
- print(f"[video-recap] 📋 解说评审(建议性,不拦截)→ {review_md}")
119
- return
120
- try:
121
- data = load_json(review_json)
122
- except (OSError, ValueError):
123
- print(f"[video-recap] 📋 解说评审(建议性,不拦截)→ {review_md}")
124
- return
116
+ data = load_json(Path(work_dir) / "narration_review.json")
125
117
  n_err = sum(1 for f in data["findings"] if f["severity"] == "error")
126
118
  print(
127
119
  f"[video-recap] 📋 解说评审(建议性,不拦截): {data['verdict']} · "
@@ -152,11 +144,17 @@ def _manifest_mismatches(work_dir, video, args):
152
144
  # as a mismatch rather than a crash.
153
145
  mismatches = [
154
146
  f"{key}: expected {expected[key]!r}, got {actual.get(key)!r}"
155
- for key in ("source_video", "source_video_fingerprint")
147
+ for key in ("source_video", "source_video_identity")
156
148
  if actual.get(key) != expected[key]
157
149
  ]
158
150
  if _settings_for_compare(actual["settings"]) != _settings_for_compare(expected["settings"]):
159
151
  mismatches.append("settings: 当前 CLI/env 参数与 Phase A manifest 不匹配")
152
+ actual_audio = actual.get("audio")
153
+ expected_audio = audio_binding(args)
154
+ if actual_audio != expected_audio:
155
+ mismatches.append(
156
+ f"audio: expected {expected_audio!r}, got {actual_audio!r}"
157
+ )
160
158
  return mismatches
161
159
 
162
160
 
@@ -168,15 +166,23 @@ def _multi_manifest_mismatches(work_dir, videos, args, source_records):
168
166
  if actual.get("mode") != "multi_source":
169
167
  return [f"mode: expected 'multi_source', got {actual.get('mode')!r}"]
170
168
  mismatches = []
171
- identity = ("source_id", "source_path", "source_video_fingerprint")
172
- if [{k: s[k] for k in identity} for s in actual["sources"]] != [
169
+ identity = ("source_id", "source_path", "source_video_identity")
170
+ # A 0.5.0 manifest carries `source_video_fingerprint` instead of `source_video_identity`;
171
+ # .get() reports it as a mismatch rather than a crash.
172
+ if [{k: s.get(k) for k in identity} for s in actual["sources"]] != [
173
173
  {k: s[k] for k in identity} for s in expected["sources"]
174
174
  ]:
175
175
  mismatches.append(
176
- "sources: 当前输入视频列表/顺序/source_id/fingerprint 与 Phase A manifest 不匹配"
176
+ "sources: 当前输入视频列表/顺序/source_id/identity 与 Phase A manifest 不匹配"
177
177
  )
178
178
  if _settings_for_compare(actual["settings"]) != _settings_for_compare(expected["settings"]):
179
179
  mismatches.append("settings: 当前 CLI/env 参数与 Phase A manifest 不匹配")
180
+ actual_audio = actual.get("audio")
181
+ expected_audio = audio_binding(args)
182
+ if actual_audio != expected_audio:
183
+ mismatches.append(
184
+ f"audio: expected {expected_audio!r}, got {actual_audio!r}"
185
+ )
180
186
  return mismatches
181
187
 
182
188
 
@@ -184,10 +190,6 @@ def _read_assembly_output(work_dir):
184
190
  return Path(load_json(Path(work_dir) / ASSEMBLY_MANIFEST)["final_output"])
185
191
 
186
192
 
187
- def _file_md5(path):
188
- return hashlib.md5(Path(path).read_bytes()).hexdigest()
189
-
190
-
191
193
  def _read_phase_ledger(work_dir):
192
194
  """Phase ledger (cut mode): which artifacts exist and the clip_plan/narration they match.
193
195
 
@@ -209,14 +211,17 @@ def _write_phase_ledger(work_dir, **fields):
209
211
  return ledger
210
212
 
211
213
 
212
- def _cut_narration_is_stale(ledger, current_clip_plan_fp):
214
+ def _cut_narration_is_stale(ledger, current_clip_plan_identity):
213
215
  """Two-pass cut: the narration is authored against the rendered cut shown at the A2 pause,
214
- i.e. against the clip_plan recorded in the ledger. If clip_plan changed since (a re-cut)
215
- while that narration is still present, it describes the OLD cut — stale."""
216
- return ledger is not None and ledger["clip_plan_fingerprint"] != current_clip_plan_fp
216
+ i.e. against the clip_plan recorded in the ledger (its ``{size, mtime_ns}`` identity). If
217
+ clip_plan.json was rewritten since (a re-cut) while that narration is still present, it
218
+ describes the OLD cut — stale."""
219
+ return ledger is not None and ledger["clip_plan_identity"] != current_clip_plan_identity
217
220
 
218
221
 
219
222
  def _continuation_command(video, work_dir, args):
223
+ # Values a project binding filled in are re-derived from --project on resume.
224
+ bound = getattr(args, "_bound_from_project", frozenset())
220
225
  parts = [
221
226
  sys.executable,
222
227
  str(_entry("video-recap", "recap.py")),
@@ -232,12 +237,14 @@ def _continuation_command(video, work_dir, args):
232
237
  parts += ["--style", args.style]
233
238
  if args.edit_mode != "full":
234
239
  parts += ["--edit-mode", args.edit_mode]
240
+ if args.audio_mode != "narration":
241
+ parts += ["--audio-mode", args.audio_mode]
242
+ if args.audio_stream_index != 0:
243
+ parts += ["--audio-stream-index", str(args.audio_stream_index)]
235
244
  if args.target_duration:
236
245
  parts += ["--target-duration", args.target_duration]
237
246
  if args.allow_duration_drift:
238
247
  parts.append("--allow-duration-drift")
239
- if args.allow_sparse_cut:
240
- parts.append("--allow-sparse-cut")
241
248
  if args.skip_asr:
242
249
  parts.append("--skip-asr")
243
250
  if args.mimo_video_overview:
@@ -250,14 +257,17 @@ def _continuation_command(video, work_dir, args):
250
257
  parts.append("--no-consolidate")
251
258
  if args.consolidate_asr:
252
259
  parts.append("--consolidate-asr")
253
- if args.mimo_tts_voice:
254
- parts += ["--mimo-tts-voice", args.mimo_tts_voice]
255
- if args.tts_provider != "auto":
256
- parts += ["--tts-provider", args.tts_provider]
257
- if args.voice_ref:
258
- parts += ["--voice-ref", args.voice_ref]
259
- if args.allow_partial_tts:
260
- parts.append("--allow-partial-tts")
260
+ if uses_narration(args):
261
+ if args.mimo_tts_voice and "mimo_tts_voice" not in bound:
262
+ parts += ["--mimo-tts-voice", args.mimo_tts_voice]
263
+ if args.tts_provider != "auto" and "tts_provider" not in bound:
264
+ parts += ["--tts-provider", args.tts_provider]
265
+ if args.voice_ref and "voice_ref" not in bound:
266
+ parts += ["--voice-ref", args.voice_ref]
267
+ if args.allow_partial_tts:
268
+ parts.append("--allow-partial-tts")
269
+ if args.preserve_approved_text:
270
+ parts.append("--preserve-approved-text")
261
271
  if args.burn_subtitles is not None:
262
272
  parts.append("--burn-subtitles" if args.burn_subtitles else "--no-burn-subtitles")
263
273
  if args.subtitle_y_top is not None:
@@ -272,16 +282,23 @@ def _continuation_command(video, work_dir, args):
272
282
  parts.append("--jianying-bundle-media")
273
283
  if args.jianying_no_bundle_media:
274
284
  parts.append("--jianying-no-bundle-media")
275
- if args.review_narration is not None:
276
- parts.append("--review-narration" if args.review_narration else "--no-review-narration")
277
- if args.require_narration_review:
278
- parts.append("--require-narration-review")
279
- if args.material_library_dir:
285
+ if uses_narration(args):
286
+ if args.review_narration is not None:
287
+ parts.append(
288
+ "--review-narration" if args.review_narration else "--no-review-narration"
289
+ )
290
+ if args.require_narration_review:
291
+ parts.append("--require-narration-review")
292
+ if args.material_library_dir and "material_library_dir" not in bound:
280
293
  parts += ["--material-library-dir", args.material_library_dir]
294
+ if getattr(args, "project", None):
295
+ parts += ["--project", args.project]
281
296
  if args.use_materials:
282
297
  parts.append("--use-materials")
283
298
  if args.save_materials:
284
299
  parts.append("--save-materials")
300
+ if args.require_final_qc:
301
+ parts.append("--require-final-qc")
285
302
  return " ".join(shlex.quote(part) for part in parts)
286
303
 
287
304
 
@@ -398,7 +415,6 @@ def _write_multi_source_clip_brief(work_dir, source_records, args):
398
415
  f"### {s['source_id']} — {s['source_name']}",
399
416
  f"- path: `{s['source_path']}`",
400
417
  f"- work_dir: `{swd}`",
401
- f"- fingerprint: `{s['source_video_fingerprint']}`",
402
418
  f"- material_id: `{s['material_id']}`",
403
419
  ]
404
420
  excerpt = _brief_excerpt(swd / "agent_narration_brief.md")
@@ -449,11 +465,7 @@ def _write_multi_source_output_speech_evidence(work_dir, source_records, plan):
449
465
  when = float(anchor["time"])
450
466
  if not (source_start - 0.05 <= when <= source_end + 0.05):
451
467
  continue
452
- try:
453
- pause = float(anchor["pause_start"])
454
- except (TypeError, ValueError):
455
- pause = when
456
- pause = max(source_start, min(pause, when))
468
+ pause = max(source_start, min(float(anchor["pause_start"]), when))
457
469
  item = dict(anchor)
458
470
  item.update(
459
471
  source_id=source_id,
@@ -491,11 +503,6 @@ def _write_multi_source_output_speech_evidence(work_dir, source_records, plan):
491
503
  "artifact": "speech_boundary_anchors_output.json",
492
504
  "timeline": "cut_output",
493
505
  "source_artifact": "multi_source_manifest.json",
494
- "clip_plan_fingerprint": hashlib.md5(
495
- json.dumps(
496
- plan, ensure_ascii=False, sort_keys=True, separators=(",", ":"), default=str
497
- ).encode("utf-8")
498
- ).hexdigest(),
499
506
  "sentence_anchors": sorted(mapped_anchors, key=lambda row: row["time"]),
500
507
  "speech_spans": sorted(mapped_speech, key=lambda row: (row["start"], row["end"])),
501
508
  "quiet_windows": sorted(mapped_quiet, key=lambda row: (row["start"], row["end"])),
@@ -0,0 +1,162 @@
1
+ """Record every resource and template a finished run used: ``work_dir/resource_lock.json``.
2
+
3
+ Facts come from artifacts the stages already wrote (run manifest, ``tts_meta.json``,
4
+ ``assembly_manifest.json``) plus the optional project binding. When a library is
5
+ configured, each file-backed entry is matched to a registered resource by resolved path
6
+ so its licence and consent status travel with the run. Nothing here changes a render.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from datetime import datetime, timezone
12
+ from pathlib import Path
13
+
14
+ import library as library_lib
15
+ from materials import file_identity
16
+
17
+ LOCK_NAME = "resource_lock.json"
18
+ LOCK_SCHEMA = "video-recap.resource-lock.v1"
19
+
20
+
21
+ def _read(path: Path):
22
+ try:
23
+ return json.loads(path.read_text(encoding="utf-8"))
24
+ except (OSError, ValueError):
25
+ return None
26
+
27
+
28
+ def _file_entry(role: str, path, detail=None) -> dict:
29
+ entry = {"role": role, "path": None, "size": None, "mtime_ns": None,
30
+ "detail": detail or {}, "library": None}
31
+ if path:
32
+ resolved = Path(path).expanduser().resolve()
33
+ entry["path"] = str(resolved)
34
+ if resolved.is_file():
35
+ entry.update(file_identity(resolved))
36
+ return entry
37
+
38
+
39
+ def _source_entries(work_dir: Path) -> list[dict]:
40
+ manifest = _read(work_dir / "recap_run_manifest.json") or {}
41
+ if manifest.get("mode") == "multi_source":
42
+ return [_file_entry("source_video", s.get("source_path"), {"source_id": s.get("source_id")})
43
+ for s in manifest.get("sources", [])]
44
+ if manifest.get("source_video"):
45
+ return [_file_entry("source_video", manifest["source_video"])]
46
+ return []
47
+
48
+
49
+ def _voice_entry(work_dir: Path) -> dict | None:
50
+ meta = _read(work_dir / "tts_meta.json")
51
+ if not isinstance(meta, dict):
52
+ return None
53
+ voice = meta.get("voice") or {"provider": meta.get("engine")}
54
+ reference = voice.get("reference") or {}
55
+ entry = _file_entry("voice", reference.get("path"), {
56
+ "provider": voice.get("provider"), "model": voice.get("model"),
57
+ "voice_id": voice.get("voice_id"),
58
+ })
59
+ return entry
60
+
61
+
62
+ def _assembly_entries(work_dir: Path) -> list[dict]:
63
+ manifest = _read(work_dir / "assembly_manifest.json") or {}
64
+ settings = manifest.get("assembly_settings") or {}
65
+ entries = []
66
+ bgm = (settings.get("audio_mix") or {}).get("bgm_path")
67
+ if bgm:
68
+ entries.append(_file_entry("bgm", bgm))
69
+ packaging = (settings.get("video_filters") or {}).get("packaging_layers") or {}
70
+ for layer in packaging.get("layers", []):
71
+ entries.append(_file_entry("packaging_layer", layer.get("path"), {"name": layer.get("name")}))
72
+ style = settings.get("subtitle_style")
73
+ if isinstance(style, dict):
74
+ entries.append(_file_entry("subtitle_font", style.get("font_file"),
75
+ {"family": style.get("font_name")}))
76
+ return entries
77
+
78
+
79
+ def _match_library(entries: list[dict], index: dict) -> None:
80
+ by_path = {}
81
+ for resource in index["resources"]:
82
+ for f in resource["files"]:
83
+ by_path[str(Path(f["path"]).resolve())] = resource
84
+ voices = [r for r in index["resources"] if r["kind"] == "voice"]
85
+ records = {r["id"]: json.loads(Path(r["record"]).read_text(encoding="utf-8"))
86
+ for r in index["resources"]}
87
+ for entry in entries:
88
+ resource = by_path.get(entry["path"]) if entry["path"] else None
89
+ if (resource is None and entry["role"] == "voice" and not entry["path"]
90
+ and isinstance(entry["detail"].get("voice_id"), str) and entry["detail"]["voice_id"]):
91
+ detail = entry["detail"]
92
+ resource = next((v for v in voices
93
+ if (records[v["id"]].get("voice") or {}).get("provider") == detail.get("provider")
94
+ and (records[v["id"]].get("voice") or {}).get("voice_id") == detail.get("voice_id")), None)
95
+ if resource is None:
96
+ continue
97
+ record = records[resource["id"]]
98
+ entry["library"] = {"id": resource["id"], "kind": resource["kind"],
99
+ "license": resource["license"],
100
+ "consent": (record.get("consent") or {}).get("status")}
101
+
102
+
103
+ def _attention(entries: list[dict], library_configured: bool) -> list[dict]:
104
+ items = []
105
+ for entry in entries:
106
+ role, lib = entry["role"], entry["library"]
107
+ if role == "source_video":
108
+ continue
109
+ if lib is None:
110
+ if library_configured and (entry["path"] or role == "voice"):
111
+ items.append({"code": "unregistered", "role": role,
112
+ "message": "资源库中没有登记这项资源,授权状态未知"})
113
+ continue
114
+ if lib["license"] in {"unknown", "restricted"}:
115
+ items.append({"code": f"license_{lib['license']}", "role": role,
116
+ "message": f"{lib['id']} 的授权状态为 {lib['license']},交付前需要人工确认"})
117
+ if role == "voice" and entry["path"] and lib.get("consent") != "granted":
118
+ items.append({"code": f"consent_{lib.get('consent') or 'unknown'}", "role": role,
119
+ "message": f"{lib['id']} 的参考音频声音授权未确认"})
120
+ return items
121
+
122
+
123
+ def build_resource_lock(work_dir, *, library_dir=None, project=None) -> dict:
124
+ """Assemble the lock payload from a finished work_dir; ``project`` is a resolved binding."""
125
+ work_dir = Path(work_dir)
126
+ entries = _source_entries(work_dir)
127
+ voice = _voice_entry(work_dir)
128
+ if voice:
129
+ entries.append(voice)
130
+ entries += _assembly_entries(work_dir)
131
+ entries += list((project or {}).get("resources", []))
132
+ library_root = None
133
+ if library_dir and Path(library_dir).is_dir():
134
+ library_root = str(Path(library_dir).resolve())
135
+ index, _ = library_lib.scan_library(library_root)
136
+ _match_library(entries, index)
137
+ return {
138
+ "schema": LOCK_SCHEMA,
139
+ "generated_at": datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z"),
140
+ "work_dir": str(work_dir.resolve()),
141
+ "library": library_root,
142
+ "project": ({"path": project["path"], "name": project.get("name", "")} if project else None),
143
+ "templates": list((project or {}).get("templates", [])),
144
+ "resources": entries,
145
+ "attention": _attention(entries, library_root is not None),
146
+ }
147
+
148
+
149
+ def write_resource_lock(work_dir, *, library_dir=None, project=None) -> dict:
150
+ lock = build_resource_lock(work_dir, library_dir=library_dir, project=project)
151
+ path = Path(work_dir) / LOCK_NAME
152
+ path.write_text(json.dumps(lock, ensure_ascii=False, indent=2), encoding="utf-8")
153
+ return lock
154
+
155
+
156
+ def summary_line(lock: dict) -> str:
157
+ registered = sum(1 for e in lock["resources"] if e["library"])
158
+ text = (f"[video-recap] 资源记录: {LOCK_NAME}({len(lock['resources'])} 项,"
159
+ f"资源库已登记 {registered} 项)")
160
+ if lock["attention"]:
161
+ text += "\n" + "\n".join(f"[video-recap] ⚠ {a['role']}: {a['message']}" for a in lock["attention"])
162
+ return text
@@ -1,15 +1,20 @@
1
1
  ---
2
2
  name: video-script
3
3
  description: >
4
- 对已完成分析的视频进行导演与剪辑策划,再写带时间戳的中文解说并校验。work_dir 已包含
5
- agent_narration_brief.md 与 vlm_analysis.json 时使用。适用于故事方向、片段选择、画面/原声/旁白分工、
6
- 解说写作与复核。输入 work_dir 中的理解索引;输出 recap_story_plan.json、visual_audio_board.json、
7
- 可选 style_card.json、cut 模式需要的 clip_plan.json,以及通过校验的 narration.json。触发词:解说词、写解说、视频旁白、
4
+ 对已完成分析的视频进行导演与剪辑策划,再写带时间戳的中文解说并校验;也处理已有短片的
5
+ 宣发标题、花字修订和外部文案回填。普通策划输入 work_dir 的 agent_narration_brief.md 与
6
+ vlm_analysis.json;文案返修输入当前成片的工程与内容证据。策划输出 recap_story_plan.json、visual_audio_board.json、
7
+ 可选 style_card.json、cut 模式需要的 clip_plan.json,以及通过校验的 narration.json;仅宣发文案任务交付提案或回填既有包装计划。
8
+ 触发词:解说词、写解说、视频旁白、宣发标题、花字修订、文案回填、
8
9
  narration script、写稿、解说文案、剪辑思路、导演思路。
9
10
  ---
10
11
 
11
12
  ## 1. 定位
12
13
 
14
+ 只改宣发标题、封面、花字或回填外部文案时,直接读 `references/promotional-copy.md`,
15
+ 按当前短片的观看理由和兑现位置处理指定文字层,不重做下述策划/旁白链。
16
+ 普通解说写作不因此增加平台调研或包装任务。
17
+
13
18
  本技能负责:创作方向、画面/声音计划、旁白写作与校验。Agent 不是 JSON 填写器,而要依次扮演:
14
19
 
15
20
  1. 导演
@@ -18,9 +23,9 @@ description: >
18
23
  4. 声音/旁白编辑
19
24
  5. 第一次观看的观众
20
25
 
21
- Agent 先记录简洁决定,再写时间线产物。`validate.py` 负责对理解索引做机械校验;full 模式还会把旁白对齐到安静窗口。
26
+ Agent 先记录简洁决定,再写时间线产物。`validate.py` 负责对理解索引做机械校验;full 模式默认还会执行预算整理并计算旁白的原声重叠。已有批准稿应加 `--preserve-approved-text`,保留段落顺序、数量、时间、文本、停顿和扩展元数据,仅允许依据现有声音证据更新 `overlaps_speech`。
22
27
 
23
- 下面的 `scripts/...` 均相对于本技能目录。若执行器从仓库根目录启动,请给脚本路径加上本技能的绝对目录。本技能不从其他技能目录读取参考文件或辅助脚本;外部输入只来自显式路径与 `work_dir` 产物。
28
+ 下面的 `scripts/...` 均相对于本技能目录。若执行器从仓库根目录启动,请给脚本路径加上本技能的绝对目录。
24
29
 
25
30
  ### 1.1 创作控制模式
26
31
 
@@ -125,7 +130,7 @@ cut 模式先根据 `recap_story_plan.json` 与 `visual_audio_board.json` 写原
125
130
  beat_id | function | change | POV | preferred moment | 入点 | 出点
126
131
  ```
127
132
 
128
- 片段顺序必须构成一条完整故事线,而不是无序高光。可使用 0–1 个 cold open,随后回到因果清楚的 setup → turn → escalation → payoff。片段长度服从具体时刻,不使用统一秒数模板;片尾必须保留完整台词或动作。对短时间内密集的 scene-change 候选,先区分原片切点与本次拼接点:原片无关短镜头整段删,相关短镜头扩展到完整动作/反应;本次拼接点优先移动边界、恢复同源连续运动或合并片段,尽量不制造人工闪切。
133
+ 片段顺序必须构成一条完整故事线,而不是无序高光。可使用 0–1 个 cold open,随后回到因果清楚的 setup → turn → escalation → payoff。片段长度服从具体时刻,不使用统一秒数模板;片尾必须保留完整台词或动作。密集 scene-change 候选的来源判断与处理规则由剪辑阶段定义,写计划时遵循同一规则,不制造人工闪切。
129
134
 
130
135
  ## 4. 撰写旁白
131
136
 
@@ -232,17 +237,15 @@ python3 scripts/review.py --work-dir <work_dir>
232
237
 
233
238
  ```bash
234
239
  python3 scripts/validate.py --work-dir <work_dir> --mode full
240
+ python3 scripts/validate.py --work-dir <work_dir> --mode full --preserve-approved-text
235
241
  # cut 输出时间线由编排器使用 --mode cut_output
236
242
  ```
237
243
 
238
- 命令写出 `narration_lint.json`。full 模式还会根据安静窗口重写 `narration.json` 的时间。修复所有 error 后重复运行,直到校验干净,再继续 TTS 与合成。
244
+ 命令写出 `narration_lint.json`。full 模式默认执行字符预算整理、去重合并并依据安静窗口计算 `overlaps_speech`,但不会把时间段移动到安静窗口;`--preserve-approved-text` 则保留批准稿的原始时间、文本、停顿、顺序与扩展元数据,只允许更新实测 `overlaps_speech`。修复所有 error 后重复运行,直到校验干净,再继续 TTS 与合成。
239
245
 
240
246
  片名或题材明确但缺少剧情上下文时,先按本技能的 `references/research-guide.md` 写 `background_research.json`。若理解素材偏薄,brief 中的数量只能当上限:宁可少写、写实,也不要为凑数复述画面。
241
247
 
242
248
  ## 7. 能力边界
243
249
 
244
- - 不运行 ASR / VLM;只消费视频理解索引。
245
- - 不合成 TTS,也不渲染视频。
246
- - 不根据平台分析做优化;先建立内容意图与剪辑一致性。
247
- - `review.py` 不改写 `narration.json`;是否采用严格门禁由调用方决定。
248
- - `validate.py` 不改写文本含义,只检查或对齐时间与安静窗口。
250
+ - 不运行 ASR / VLM,不合成 TTS,不渲染视频;只消费视频理解索引。
251
+ - 平台研究仅用于明确的宣发任务;不替代当前片内事实,也不默认改变解说和剪辑。
@@ -8,7 +8,7 @@
8
8
  - **DIRECTED**:用户已经指定结构、镜头、台词或表达,目标是准确落实而不是展示替代创意。
9
9
  - **REVISION**:基于已有版本看片修改。最新反馈覆盖旧决定;本轮未点名内容默认冻结。
10
10
 
11
- REVISION 先列本轮修改项与冻结项。表达、节奏、字幕意见写回 `style_card.json`,镜头与声音意见写回 `visual_audio_board.json`;只有故事主线改变才更新 `recap_story_plan.json`。删除内容时也删除过期的计划描述。完成后分别验证“该变的确实变了”和“不该变的没有漂移”。
11
+ REVISION 先列本轮修改项与冻结项。表达、节奏、字幕意见写回 `style_card.json`,镜头与声音意见写回 `visual_audio_board.json`;只有故事主线改变才更新 `recap_story_plan.json`。删除内容时也删除过期的计划描述。只提能定位到 beat、镜头边界或句子的具体局部修法,未点名层继续冻结;完成后分别验证“该变的确实变了”和“不该变的没有漂移”。
12
12
 
13
13
  ## 决策优先级
14
14
 
@@ -53,7 +53,9 @@ beat 不是固定秒数、场景名或一句旁白;beat 是一次可感知的
53
53
  - 情绪如何转向;
54
54
  - 风险或代价如何升级。
55
55
 
56
- 如果移除一个 beat 后,因果、人物或情绪都没有损失,它通常不值得占用成片时间。钩子必须提出这条故事真正会兑现的问题,不能制造正文不回答的夸张承诺。
56
+ 如果移除一个 beat 后,因果、人物或情绪都没有损失,它通常不值得占用成片时间。精简不能只保“发生了什么”:还要保住人物动机、接受条件,以及人物为何犹豫或行动;缺前提时回到源证据,用更短的原声或解说补齐,不恢复无关长铺垫。钩子必须提出这条故事真正会兑现的问题,不能制造正文不回答的夸张承诺。
57
+
58
+ 准备移交剪辑时,把这类不可删除的具体源时刻写入同一 `clip_plan.json.required_evidence`:`nodes` 每项记录唯一 `id`、实际文件绝对路径 `source`、原片秒 `start/end`、`track`(audio/video)和 `content`;多源可补 `source_id`。`before` 用 `[前提id, 回应id]` 登记本片必需的顺序。只锁必要区间,不锁整个 beat;不依赖 `reason` 里的“保留前提”一句话。剪辑执行器会在吸附剪点后核对这些要求,缺段时先修选择,再配音包装。
57
59
 
58
60
  ### 3. 画面剪辑:选择时刻,而不只选择事件
59
61
 
@@ -65,16 +67,18 @@ beat 不是固定秒数、场景名或一句旁白;beat 是一次可感知的
65
67
  - **不可替代瞬间**:停顿、迟疑、失误、眼神、动作声音中,哪一个让人物变得真实?
66
68
  - **节奏**:这一拍需要冲过去,还是需要多停半秒让含义落地?
67
69
  - **边界**:优先完整动作、完整台词和自然声音边界;不要机械地把每个片段切成同一长度。
70
+ - **兑现**:以某个可见结果为看点时,只写证据已呈现的结果,不推断更强的结果(例:证据只到受击,就不能写成倒地或胜负)。
68
71
 
69
72
  进入 `clip_plan.json` 的不是“发生过的所有重要事件”,而是最能让观众经历这条主线的具体时刻。
70
73
 
71
- 目标不是绝对最短,而是**最短但完整**:晚进不能丢掉理解动作所需的前提,早出不能吃掉表演的回报。建立空间和事实的镜头通常可以短;关键对视、亲吻、受伤反应、决定落地或沉默可以多停一点,让观众先感受到再离开。
74
+ 目标不是绝对最短,而是**最短但完整**:晚进不能丢掉理解动作所需的前提,早出不能吃掉表演的回报。建立空间和事实的镜头通常可以短;关键对视、亲吻、受伤反应、决定落地或沉默可以多停一点,让观众先感受到再离开。有情感回应或知情变化的反应镜不是冗余,不能仅因它是反打或停留较短就机械删除。
72
75
 
73
76
  场景之间的 IN / OUT 也要有任务:
74
77
 
75
78
  - 新人物、地点或情绪场景,先给画面一个可感知的建立时刻,再让旁白进入;旁白不必与画面同帧起跑。
76
79
  - OUT 优先落在动作完成、反应落地、台词句末、沉默结束或干净硬切前。
77
80
  - 不要在原片叠化、闪白或其他转场的中间再切一次。转场至少由画面变化、动作延续、声音接力或叙事跨越中的一项驱动。
81
+ - 跨场镜头只能作明确的并置或主题呼应,不得拼成同场出手、接触、反应的虚假因果;花字只能补有证据的必要前提,不能替补源证据或提前宣布结果。
78
82
 
79
83
  scene-change score、逐帧亮度和接点 contact sheet 只用于诊断:检查每个接点前后约 0.5–1 秒,定位硬切、白闪或曝光叠化候选。修复优先收进稳定镜头、保留原片完整转场的一侧、扩展源素材,或用相邻有效镜头补足时长;不能为了视觉干净切断台词。最终必须真实播放接点,不能把检测分数当成观看结论。
80
84
 
@@ -90,7 +94,7 @@ ffmpeg -i input.mp4 -vf "select='gt(scene,0.35)',showinfo" -an -f null -
90
94
  - **本次剪辑制造的切点**:优先移动 IN / OUT、恢复同一源镜头的连续运动、合并相邻片段,或换成有叙事任务的连接镜头;能消除就不保留。溶解、闪白和包装不能用来遮掩坏接点。
91
95
  - **有意的原片蒙太奇**:只有当每个短镜头都提供新信息、动作或节奏回报,且正常播放仍清楚可读时才保留;否则按无关或过短镜头处理。
92
96
 
93
- 密集度不是单一固定秒数门槛。先找同一短窗内的连续候选,再以正常速度播放判断观众感受到的是有效节奏还是闪烁。
97
+ 密集度不是单一固定秒数门槛。反打是否保留取决于它有没有新增信息,例如关系、情感回应、知情变化或空间/动作结果,而不是是否达到统一时长;先找同一短窗内的连续候选,再以正常速度播放判断观众感受到的是有效节奏还是闪烁。
94
98
 
95
99
  ### 4. 声音与旁白:先分工,再写字
96
100
 
@@ -128,7 +132,7 @@ ffmpeg -i input.mp4 -vf "select='gt(scene,0.35)',showinfo" -an -f null -
128
132
  再逐 beat 追问:
129
133
 
130
134
  - 删除它,什么会坏?什么都不坏就删。
131
- - 换成反应镜头,情绪是否更强?
135
+ - 删除或换掉反应镜头后,是否丢失情感回应、知情变化或新的动作结果?
132
136
  - 旁白改成原声或沉默,含义是否更好?
133
137
  - 提前揭示或延后揭示,哪一个更符合 POV?
134
138
  - 能否晚进、早出,而不损失理解?
@@ -0,0 +1,68 @@
1
+ # 宣发标题、花字与文案返修
2
+
3
+ 用户要求宣发选题、标题/封面/发布稿、花字优化,或把外部模型的文案回填时使用。
4
+ 只写解说或精修剪点时不增加这一步。
5
+
6
+ ## 先确定这条片卖什么
7
+
8
+ 从当前短片而不是整部剧提炼一个具体观看理由:人物做了什么选择、付出什么代价,
9
+ 观众将看懂什么或感受到什么。先标出片内兑现的画面/原声位置,再写承诺。
10
+ 同一批可以分别卖关系、选择、笑点、动作或推理,不把每条都套成反转或复仇。
11
+
12
+ 用户需要案例研究时,按发行状态选来源:
13
+
14
+ - **已播剧**:看本剧社媒的真实讨论、传播切片与观众关注点,再判断当前短片能否承接。
15
+ - **未发布剧**:用剧本特色和片内证据形成受众假设,参考近期成功宣发案例;不假设本剧已有热度。
16
+
17
+ 记录参考物料的发布者、链接、发布日期、采集日期、具体做法及可借部分。
18
+ 单条播放、整剧热度、话题聚合量分开写;有数字也不等于证明某句标题带来了成绩。
19
+ 旧研究需要更新时再查证;未查到的效果不补数字,离线方案明确只依据已有材料。
20
+
21
+ ## 给其他模型的任务包
22
+
23
+ 按共同剧情与观看理由分组,让每组有足够上下文,但每条分别交付。直接用短 Markdown
24
+ 任务包即可,不另造视频时间线。每条提供:
25
+
26
+ 1. **当前版本**:具体工程、对应成片和待渲染修改;有版本号时沿用已有值。
27
+ 2. **片内内容**:正文结束点、故事起因与回报、当前选镜、原声/解说字幕、时间属于哪版成片。
28
+ 3. **现有文案**:两行标题、花字及其位置/时间、时空提示;封面和发布稿存在时一并给出。
29
+ 4. **本轮范围**:允许修改的文字层,以及保留的剪点、字幕、旁白、声音、样式和片尾。
30
+ 5. **证据缺口**:角色所说与已发生事实的差别、未出现的结果、模糊专名和未核时码。
31
+
32
+ 附一段可直接使用的要求:
33
+
34
+ > 先解释这条短片为什么值得点开、看完得到什么,再给主推文案;需要备选时按不同观看理由区分,
35
+ > 不只替换近义词。两行常驻标题、封面字和发布标题各司其职。花字、时空提示分别列修改;
36
+ > 每处给原文、建议、成片位置和片内依据。没有必要就不加花字。只看到工程/字幕时,
37
+ > 时间窗是提案,不能声称已看片。若问题只能靠改镜头或声音解决,单列出来,不用加字掩盖。
38
+
39
+ ## 写字时的分工
40
+
41
+ | 层 | 工作 | 常见修法 |
42
+ |---|---|---|
43
+ | 常驻标题 | 让陌生观众理解人物处境与本片回报 | 用动作和代价降低人名/术语门槛;不提前宣布未呈现的胜负 |
44
+ | 封面字 | 在封面画面上聚焦一个看点 | 不再塞一遍两行标题;文字需与所选封面帧一致 |
45
+ | 发布标题 | 补关系、背景或观看邀请 | 不把解说全文搬过来,不冒充角色原话 |
46
+ | 花字 | 补必要理解、观察方向或克制的情绪批注 | 不重复对白、不遮关键动作;拥挤时优先撤花字 |
47
+ | 时空提示 | 说明当前/往事、地点或画外判断来源 | 跟随画面切换,不跟跨场旁白提前切换 |
48
+ | 对白/旁白字幕 | 忠实承载当前可听见的话 | 不属于宣发改字范围,不拿新花字覆盖或替代 |
49
+
50
+ “却”“不是……而是……”不是禁词;当素材没有需要纠正的预期时,直接写行动和后果。
51
+ 人物许诺不等于事情已成,单向凝望不等于双方相爱,受伤不等于死亡。
52
+ 批量检查重复的是观看理由和句式,不把共享镜头但回报不同的片子合并成同题。
53
+
54
+ ## 回填到当前工程
55
+
56
+ - 先核任务包对应的工程是否仍是本轮采用基础;已有新剪点、换序、换声或待渲染字幕时,
57
+ 把建议重新对到新版本,不把旧全文覆盖回去,也不凭文件修改时间决定采用。
58
+ - 复制当前工程为新候选,只改本轮采用项;未明确改动的文字、ID、时码、位置和可见性保留。
59
+ **没提到不等于删除**。`notes=[]` 在提案中可表示不新增;回填完整工程时则是清空整轨,
60
+ 必须先把“保留/新增/替换/删除”逐项说明白。
61
+ - 新增或明确调整花字/时空标的时间时,先对照当前成片的真实画面/台词和帧钟确定出入点;
62
+ CFR核实际帧,VFR用真实PTS找到对应帧号。建议窗只到小数三位时,不当作已核准的帧级锚点。
63
+ - 使用已有包装工程的字段,不再造一套对白轨:标题、花字、时空提示各写回它们原本所在的层,
64
+ 时间最终写整数半开区间的帧号,不是浮点秒数;工程里指向素材、字幕和样式的引用原样保留。
65
+ 封面与发布稿仍放文案交付,不塞进画面渲染计划。
66
+ - 回填后比较修改前后:逐项核已采用的文字变化、未改层一致、时窗未超正文。已有制作工具先做
67
+ 计划校验;用户只要改轨时到此停止。渲染后再核新字实际出现、遮挡和阅读负担,不能把
68
+ 工程已改叫成片已更新。
@@ -72,4 +72,4 @@
72
72
  | 结果互相矛盾 | 只使用用户提供的上下文或画面/ASR 可验证的信息 |
73
73
  | 信息可能剧透后续 | 只用于理解人物关系,不在解说里剧透用户没要求的后续剧情 |
74
74
 
75
- **原则**:背景资料只能补上下文,不能替代 `vlm_analysis.json` / `asr_result.json` 里的画面和对白证据,也不能假装已经被此前的视觉分析消费。
75
+ **原则**:背景资料只能补上下文,不能替代 `vlm_analysis.json` / `asr_result.json` 里的画面和对白证据。