@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
@@ -0,0 +1,293 @@
1
+ #!/usr/bin/env python3
2
+ """Compose caller-rendered RGBA pixels over a frozen H264/CFR/AAC base.
3
+
4
+ This operation validates pixels and declared inputs. It does not generate or
5
+ interpret titles, dialogue, brands, typography, or release approval.
6
+ """
7
+
8
+ import argparse
9
+ from fractions import Fraction
10
+ import json
11
+ from pathlib import Path
12
+ import subprocess
13
+
14
+ from adoption.frozen_audio import probe_audio_packets, verify_adopted_audio
15
+ from pair_media import probe_picture, validate_pair_timing
16
+ from adoption.strict_inputs import (
17
+ canonical_fraction, require_declared_path, require_fields, require_integer, run_logged,
18
+ without_digests, write_json_atomic,
19
+ )
20
+
21
+
22
+ PATTERN = "frame_%06d.png"
23
+ ENCODING = {
24
+ "video_codec": "libx264", "preset": "fast", "crf": 18,
25
+ "pixel_format": "yuv420p", "color": "bt709_tv", "audio_codec": "copy",
26
+ }
27
+
28
+
29
+ def _fields(value, required):
30
+ value = without_digests(value, "compose plan")
31
+ require_fields(value, required, "compose plan")
32
+ return value
33
+
34
+
35
+ def _local_file(value, label):
36
+ _fields(value, ["path"])
37
+ return {"path": str(require_declared_path(value, label))}
38
+
39
+
40
+ def _sequence_paths(directory, pattern, start, end):
41
+ if pattern != PATTERN:
42
+ raise ValueError(f"Only the literal simple pattern {PATTERN!r} is supported")
43
+ directory = Path(directory).resolve()
44
+ if not directory.is_dir():
45
+ raise FileNotFoundError(f"Sequence directory missing: {directory}")
46
+ expected = [directory / (pattern % index) for index in range(start, end)]
47
+ actual = sorted(directory.iterdir(), key=lambda item: item.name)
48
+ if [item.name for item in actual] != [item.name for item in expected]:
49
+ raise ValueError("Sequence requires exact contiguous files with no missing or extra entries")
50
+ if not all(path.is_file() for path in expected):
51
+ raise FileNotFoundError("Sequence frame missing or not a file")
52
+ return directory, expected
53
+
54
+
55
+ def _probe_image(path):
56
+ result = subprocess.run(
57
+ ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_streams",
58
+ "-show_entries", "stream=codec_name,width,height,pix_fmt", "-of", "json", str(path)],
59
+ capture_output=True, text=True, timeout=600,
60
+ )
61
+ if result.returncode or result.stderr.strip():
62
+ raise ValueError(f"Image probe failed: {result.stderr.strip()}")
63
+ streams = json.loads(result.stdout).get("streams", [])
64
+ if len(streams) != 1 or streams[0].get("codec_name") != "png":
65
+ raise ValueError("Foreground assets must be PNG images")
66
+ return streams[0]
67
+
68
+
69
+ def _validate_rgba(path, width, height):
70
+ image = _probe_image(path)
71
+ if (image.get("width"), image.get("height")) != (width, height):
72
+ raise ValueError("PNG must exactly match the full output canvas")
73
+ if image.get("pix_fmt") != "rgba":
74
+ raise ValueError("PNG must contain an actual RGBA pixel format")
75
+
76
+
77
+ def _sequence(value, required, *, local_count, width, height):
78
+ value = _fields(value, required)
79
+ directory = value["directory"]
80
+ if not isinstance(directory, str) or not directory or "://" in directory:
81
+ raise ValueError("Sequence requires a local directory")
82
+ if value["pattern"] != PATTERN:
83
+ raise ValueError(f"Only the literal simple pattern {PATTERN!r} is supported")
84
+ resolved, paths = _sequence_paths(directory, value["pattern"], 0, local_count)
85
+ for path in paths:
86
+ _validate_rgba(path, width, height)
87
+ return {**value, "directory": str(resolved), "frame_count": len(paths)}, paths
88
+
89
+
90
+ def validate_endcard(value, *, foreground_end, total_frames, width, height):
91
+ """Validate the exact endcard union and return normalized data and bound paths."""
92
+ if not isinstance(value, dict) or value.get("kind") not in {"none", "still", "sequence"}:
93
+ raise ValueError("Endcard kind must be none, still, or sequence")
94
+ value = without_digests(value, "endcard")
95
+ if value["kind"] == "none":
96
+ _fields(value, ["kind"])
97
+ if foreground_end != total_frames:
98
+ raise ValueError("No endcard requires foreground to cover the full frame clock")
99
+ return {"kind": "none"}, []
100
+ if value["kind"] == "still":
101
+ required = ["kind", "path", "start_frame", "end_frame"]
102
+ else:
103
+ required = ["kind", "directory", "pattern", "start_frame", "end_frame"]
104
+ _fields(value, required)
105
+ end_start = require_integer(value["start_frame"], "endcard start_frame")
106
+ end_end = require_integer(value["end_frame"], "endcard end_frame", minimum=1)
107
+ if end_start >= end_end:
108
+ raise ValueError("Endcard interval must be non-empty")
109
+ if end_start != foreground_end or end_end != total_frames:
110
+ raise ValueError("Foreground and endcard must exactly partition the base frame clock")
111
+ if value["kind"] == "still":
112
+ asset = _local_file({"path": value["path"]}, "endcard")
113
+ _validate_rgba(asset["path"], width, height)
114
+ return {**value, **asset}, [Path(asset["path"])]
115
+ return _sequence(
116
+ value, required, local_count=end_end - end_start, width=width, height=height,
117
+ )
118
+
119
+
120
+ def validate_plan(plan_path):
121
+ plan_path = Path(plan_path).resolve()
122
+ plan = json.loads(plan_path.read_bytes())
123
+ _fields(plan, ["artifact", "schema_version", "base", "video", "foreground",
124
+ "endcard", "producer_receipt"])
125
+ plan = {**plan, "video": _fields(plan["video"], ["fps", "width", "height", "total_frames"])}
126
+ if plan["artifact"] != "foreground_compose_plan" or type(plan["schema_version"]) is not int \
127
+ or plan["schema_version"] != 1:
128
+ raise ValueError("Unsupported foreground_compose_plan schema")
129
+ base = _local_file(plan["base"], "base")
130
+ receipt = _local_file(plan["producer_receipt"], "producer_receipt")
131
+ fps = canonical_fraction(plan["video"]["fps"], "video fps")
132
+ width = require_integer(plan["video"]["width"], "video width", minimum=1)
133
+ height = require_integer(plan["video"]["height"], "video height", minimum=1)
134
+ total = require_integer(plan["video"]["total_frames"], "video total_frames", minimum=1)
135
+ _fields(plan["foreground"], ["directory", "pattern", "start_frame", "end_frame"])
136
+ foreground_start = require_integer(plan["foreground"]["start_frame"], "foreground start_frame")
137
+ foreground_end = require_integer(plan["foreground"]["end_frame"], "foreground end_frame", minimum=1)
138
+ if foreground_start != 0 or foreground_end > total:
139
+ raise ValueError("Foreground must start at frame 0 and not exceed the frame clock")
140
+ foreground, foreground_paths = _sequence(
141
+ plan["foreground"], ["directory", "pattern", "start_frame", "end_frame"],
142
+ local_count=foreground_end, width=width, height=height,
143
+ )
144
+ normalized_endcard, endcard_paths = validate_endcard(
145
+ plan["endcard"], foreground_end=foreground_end, total_frames=total,
146
+ width=width, height=height,
147
+ )
148
+ picture = probe_picture(base["path"])
149
+ decoder = picture["decoder"]
150
+ required_color = {"codec_name": "h264", "pix_fmt": "yuv420p", "color_range": "tv",
151
+ "color_space": "bt709", "color_transfer": "bt709",
152
+ "color_primaries": "bt709"}
153
+ if any(decoder.get(key) != value for key, value in required_color.items()):
154
+ raise ValueError("Base must be H264 yuv420p with explicit BT.709 TV color metadata")
155
+ if (decoder.get("width"), decoder.get("height"), picture["frame_count"],
156
+ Fraction(picture["fps"])) != (width, height, total, fps):
157
+ raise ValueError("Declared fps/canvas/count does not match the actual base")
158
+ audio = probe_audio_packets(base["path"], 0)
159
+ validate_pair_timing(picture, audio)
160
+ return {
161
+ "plan_path": plan_path, "base": base,
162
+ "video": {"fps": str(fps), "width": width, "height": height, "total_frames": total},
163
+ "foreground": foreground, "foreground_paths": foreground_paths,
164
+ "endcard": normalized_endcard, "endcard_paths": endcard_paths,
165
+ "producer_receipt": receipt, "picture": picture, "audio": audio,
166
+ }
167
+
168
+
169
+ def _run_ffmpeg(command, directory):
170
+ run_logged(command, directory, "compose", timeout=600)
171
+
172
+
173
+ def _verify_output(path, validated):
174
+ output_picture = probe_picture(path)
175
+ expected = validated["picture"]
176
+ for key in ("frame_pts", "frame_count", "fps", "duration", "start"):
177
+ if output_picture[key] != expected[key]:
178
+ raise ValueError(f"Output picture {key} differs from the base")
179
+ decoder_keys = ("codec_name", "width", "height", "pix_fmt", "sample_aspect_ratio",
180
+ "field_order", "color_range", "color_space", "color_transfer",
181
+ "color_primaries", "chroma_location")
182
+ if {key: output_picture["decoder"].get(key) for key in decoder_keys} != \
183
+ {key: expected["decoder"].get(key) for key in decoder_keys}:
184
+ raise ValueError("Output codec/canvas/color metadata differs from the base")
185
+ proof = verify_adopted_audio(validated["base"]["path"], path, 0, 0)
186
+ if validate_pair_timing(output_picture, proof["output"]) != \
187
+ validate_pair_timing(expected, validated["audio"]):
188
+ raise ValueError("Output audio interval changed")
189
+ result = subprocess.run(
190
+ ["ffmpeg", "-v", "error", "-xerror", "-threads", "2", "-i", str(path),
191
+ "-map", "0:v:0", "-map", "0:a:0", "-f", "null", "-"],
192
+ capture_output=True, text=True, timeout=600,
193
+ )
194
+ if result.returncode or result.stderr.strip():
195
+ raise ValueError("Foreground output full decode failed")
196
+ return output_picture, proof
197
+
198
+
199
+ def run_compose(plan_path, output_dir, *, plan_only=False):
200
+ directory = Path(output_dir).resolve()
201
+ directory.mkdir(parents=True, exist_ok=False)
202
+ report_path = directory / "foreground_run.json"
203
+ staged = directory / "foreground.rendering.mp4"
204
+ output = directory / "foreground.mp4"
205
+ report = {"artifact": "foreground_compose_run", "schema_version": 1,
206
+ "status": "PREPARING", "direct_listening": "NOT_CHECKED",
207
+ "normal_speed_review": "NOT_CHECKED", "release_approved": False,
208
+ "encoding": ENCODING}
209
+ write_json_atomic(report_path, report)
210
+ try:
211
+ value = validate_plan(plan_path)
212
+ report.update(
213
+ plan={"path": str(value["plan_path"])},
214
+ base=value["base"], video=value["video"], foreground=value["foreground"],
215
+ endcard=value["endcard"],
216
+ producer_receipt={**value["producer_receipt"],
217
+ "semantic_validation": "DECLARED_NOT_CHECKED"},
218
+ )
219
+ if plan_only:
220
+ report["status"] = "PLANNED"
221
+ write_json_atomic(report_path, report)
222
+ return report
223
+ fps = value["video"]["fps"]
224
+ command = ["ffmpeg", "-nostdin", "-v", "error", "-n", "-copyts",
225
+ "-i", value["base"]["path"], "-framerate", fps, "-start_number", "0",
226
+ "-i", str(Path(value["foreground"]["directory"]) / PATTERN)]
227
+ if value["endcard"]["kind"] == "none":
228
+ filters = (
229
+ "[0:v]format=rgb24[base];[1:v]format=rgba,setpts=PTS-STARTPTS[fg];"
230
+ "[base][fg]overlay=0:0:eof_action=pass:format=rgb,"
231
+ "scale=in_range=pc:out_range=tv:"
232
+ "in_color_matrix=bt709:out_color_matrix=bt709,format=yuv420p,"
233
+ f"trim=end_frame={value['video']['total_frames']}[outv]"
234
+ )
235
+ elif value["endcard"]["kind"] == "still":
236
+ command += ["-loop", "1", "-framerate", fps, "-i", value["endcard"]["path"]]
237
+ else:
238
+ command += ["-framerate", fps, "-start_number", "0", "-i",
239
+ str(Path(value["endcard"]["directory"]) / PATTERN)]
240
+ if value["endcard"]["kind"] != "none":
241
+ end_start = value["endcard"]["start_frame"]
242
+ end_offset = Fraction(end_start, 1) / Fraction(fps)
243
+ filters = (
244
+ f"[0:v]format=rgb24[base];[1:v]format=rgba,setpts=PTS-STARTPTS[fg];"
245
+ f"[2:v]format=rgba,setpts=PTS-STARTPTS+{end_offset.numerator}/"
246
+ f"{end_offset.denominator}/TB[end];"
247
+ f"[base][fg]overlay=0:0:eof_action=pass:format=rgb:"
248
+ f"enable='lt(n,{end_start})'[body];"
249
+ f"[body][end]overlay=0:0:eof_action=repeat:format=rgb:"
250
+ f"enable='gte(n,{end_start})',scale=in_range=pc:out_range=tv:"
251
+ "in_color_matrix=bt709:out_color_matrix=bt709,format=yuv420p,"
252
+ f"trim=end_frame={value['video']['total_frames']}[outv]"
253
+ )
254
+ command += ["-filter_complex", filters, "-map", "[outv]", "-map", "0:a:0",
255
+ "-c:v", ENCODING["video_codec"], "-preset", ENCODING["preset"],
256
+ "-crf", str(ENCODING["crf"]), "-threads", "2",
257
+ "-pix_fmt", ENCODING["pixel_format"],
258
+ "-color_range", "tv", "-colorspace", "bt709", "-color_primaries", "bt709",
259
+ "-color_trc", "bt709", "-c:a", "copy", "-movie_timescale",
260
+ str(value["audio"]["sample_rate"]), "-movflags", "+faststart",
261
+ str(staged)]
262
+ _run_ffmpeg(command, directory)
263
+ output_picture, audio_proof = _verify_output(staged, value)
264
+ write_json_atomic(directory / "picture_identity.json", output_picture)
265
+ write_json_atomic(directory / "adopted_audio_identity.json", audio_proof)
266
+ report["output"] = {"path": str(output),
267
+ "full_decode": "PASS", "frame_clock": "EXACT",
268
+ "audio_packet_identity": "EXACT"}
269
+ staged.rename(output)
270
+ report["status"] = "FOREGROUND_RENDERED"
271
+ write_json_atomic(report_path, report)
272
+ return report
273
+ except Exception as exc:
274
+ staged.unlink(missing_ok=True)
275
+ output.unlink(missing_ok=True)
276
+ report.pop("output", None)
277
+ report.update(status="FAILED", error=f"{type(exc).__name__}: {exc}")
278
+ write_json_atomic(report_path, report)
279
+ raise
280
+
281
+
282
+ def main():
283
+ parser = argparse.ArgumentParser(description=__doc__)
284
+ parser.add_argument("plan")
285
+ parser.add_argument("--output-dir", required=True)
286
+ parser.add_argument("--plan-only", action="store_true")
287
+ args = parser.parse_args()
288
+ report = run_compose(args.plan, args.output_dir, plan_only=args.plan_only)
289
+ print(json.dumps(report, ensure_ascii=False, indent=2))
290
+
291
+
292
+ if __name__ == "__main__":
293
+ main()
@@ -20,20 +20,19 @@ are implemented locally and no upstream executable code, resource package,
20
20
  adapter binary, or credential is included. See ACKNOWLEDGEMENTS / 致谢.
21
21
  """
22
22
 
23
- import copy
24
23
  import json
25
24
  import os
26
25
  import subprocess
27
26
  import tempfile
28
27
  import uuid
29
28
 
30
- from jianying_builders import build_timeline_track as _build_timeline_track
31
- from jianying_model import DraftBuildContext as _DraftBuildContext
32
- from jianying_schema import draft_content_skeleton as _draft_content_skeleton
33
- from jianying_schema import meta_info as _meta_info
34
- from jianying_schema import us
35
- from jianying_timeline_contract import normalize_timeline as _normalize_timeline
36
- from jianying_writer import write_draft as _write_draft
29
+ from jianying.builders import build_timeline_track as _build_timeline_track
30
+ from jianying.model import DraftBuildContext as _DraftBuildContext
31
+ from jianying.schema import draft_content_skeleton as _draft_content_skeleton
32
+ from jianying.schema import meta_info as _meta_info
33
+ from jianying.schema import us
34
+ from jianying.timeline_contract import normalize_timeline as _normalize_timeline
35
+ from jianying.writer import write_draft as _write_draft
37
36
 
38
37
  __all__ = ["us", "build_draft", "export_timeline_to_jianying", "main"]
39
38
 
@@ -43,46 +42,51 @@ def _default_id():
43
42
 
44
43
 
45
44
  def _probe_media(path):
46
- """Return (duration_us, width, height) via ffprobe; zeros on any failure."""
47
- try:
48
- r = subprocess.run(
49
- [
50
- "ffprobe",
51
- "-v",
52
- "error",
53
- "-of",
54
- "json",
55
- "-show_entries",
56
- "format=duration:stream=width,height,codec_type",
57
- str(path),
58
- ],
59
- capture_output=True,
60
- text=True,
61
- timeout=30,
62
- )
63
- data = json.loads(r.stdout or "{}")
64
- dur_us = us(float(data.get("format", {}).get("duration") or 0))
65
- width = height = 0
66
- for stream in data.get("streams", []):
67
- if stream.get("codec_type") == "video":
68
- width, height = (
69
- int(stream.get("width") or 0),
70
- int(stream.get("height") or 0),
71
- )
72
- break
73
- return dur_us, width, height
74
- except (OSError, ValueError, json.JSONDecodeError, subprocess.TimeoutExpired):
75
- return 0, 0, 0
45
+ """Return (duration_us, width, height) via ffprobe.
46
+
47
+ A probe failure raises: a draft that silently carries a zero or guessed media
48
+ duration is worse than a failed optional export. Still images legitimately
49
+ report no duration (0).
50
+ """
51
+ result = subprocess.run(
52
+ [
53
+ "ffprobe",
54
+ "-v",
55
+ "error",
56
+ "-of",
57
+ "json",
58
+ "-show_entries",
59
+ "format=duration:stream=width,height,codec_type",
60
+ str(path),
61
+ ],
62
+ capture_output=True,
63
+ text=True,
64
+ timeout=30,
65
+ )
66
+ if result.returncode:
67
+ raise RuntimeError(f"ffprobe failed for JianYing media {path}: {result.stderr.strip()}")
68
+ data = json.loads(result.stdout)
69
+ duration = data["format"].get("duration")
70
+ width = height = 0
71
+ for stream in data.get("streams", []):
72
+ if stream.get("codec_type") == "video":
73
+ width, height = int(stream["width"]), int(stream["height"])
74
+ break
75
+ return (us(float(duration)) if duration is not None else 0), width, height
76
76
 
77
77
 
78
78
  def build_draft(timeline, new_id=None, probe=None):
79
79
  """Build the 剪映 draft_content dict and companion meta from a timeline."""
80
- timeline = _normalize_timeline(timeline)
80
+ return _build_normalized_draft(_normalize_timeline(timeline), new_id, probe)
81
+
82
+
83
+ def _build_normalized_draft(timeline, new_id=None, probe=None):
84
+ """`timeline` has already passed jianying.timeline_contract.normalize_timeline."""
81
85
  new_id = new_id or _default_id
82
86
  probe = probe or _probe_media
83
87
  ctx = _DraftBuildContext.from_timeline(timeline, new_id, probe)
84
88
 
85
- for timeline_track in timeline.get("tracks", []):
89
+ for timeline_track in timeline["tracks"]:
86
90
  _build_timeline_track(ctx, timeline_track)
87
91
  ctx.finalize_tracks()
88
92
 
@@ -141,29 +145,20 @@ def _generate_reversed_media(source_path, output_path):
141
145
  )
142
146
 
143
147
 
144
- def _prepare_reverse_sources(timeline, temporary_dir):
145
- prepared = copy.deepcopy(timeline)
148
+ def _prepare_reverse_sources(clips, temporary_dir):
149
+ """Generate a reversed copy for each clip and record it as the clip's reverse_path."""
146
150
  generated = []
147
- for track in prepared.get("tracks", []):
148
- if not isinstance(track, dict) or track.get("kind") != "video":
149
- continue
150
- for clip in track.get("clips", []):
151
- if (
152
- not isinstance(clip, dict)
153
- or not clip.get("reverse")
154
- or clip.get("reverse_path")
155
- ):
156
- continue
157
- source_path = clip.get("source_path")
158
- if not isinstance(source_path, str) or not os.path.isfile(source_path):
159
- raise ValueError(f"reverse source does not exist: {source_path}")
160
- output_path = os.path.join(
161
- temporary_dir, f"reversed-{uuid.uuid4().hex}.mp4"
162
- )
163
- _generate_reversed_media(source_path, output_path)
164
- clip["reverse_path"] = output_path
165
- generated.append(source_path)
166
- return prepared, generated
151
+ for clip in clips:
152
+ source_path = clip["source_path"]
153
+ if not os.path.isfile(source_path):
154
+ raise ValueError(f"reverse source does not exist: {source_path}")
155
+ output_path = os.path.join(
156
+ temporary_dir, f"reversed-{uuid.uuid4().hex}.mp4"
157
+ )
158
+ _generate_reversed_media(source_path, output_path)
159
+ clip["reverse_path"] = output_path
160
+ generated.append(source_path)
161
+ return generated
167
162
 
168
163
 
169
164
  def export_timeline_to_jianying(
@@ -175,21 +170,19 @@ def export_timeline_to_jianying(
175
170
  portable. Pass bundle_media=False only when external absolute paths are
176
171
  intentionally required.
177
172
  """
178
- needs_generated_reverse = any(
179
- isinstance(track, dict)
180
- and track.get("kind") == "video"
181
- and any(
182
- isinstance(clip, dict)
183
- and clip.get("reverse")
184
- and not clip.get("reverse_path")
185
- for clip in track.get("clips", [])
186
- )
187
- for track in timeline.get("tracks", [])
188
- )
189
- if needs_generated_reverse and not bundle_media:
173
+ # Validate once at the boundary; everything below trusts the normalized copy.
174
+ timeline = _normalize_timeline(timeline)
175
+ reverse_clips = [
176
+ clip
177
+ for track in timeline["tracks"]
178
+ if track["kind"] == "video"
179
+ for clip in track["clips"]
180
+ if clip.get("reverse") and "reverse_path" not in clip
181
+ ]
182
+ if reverse_clips and not bundle_media:
190
183
  raise ValueError("automatic reverse generation requires media bundling")
191
- if not needs_generated_reverse:
192
- content, meta, notes = build_draft(timeline, new_id=new_id, probe=probe)
184
+ if not reverse_clips:
185
+ content, meta, notes = _build_normalized_draft(timeline, new_id=new_id, probe=probe)
193
186
  return _write_draft(
194
187
  content,
195
188
  meta,
@@ -203,8 +196,8 @@ def export_timeline_to_jianying(
203
196
  with tempfile.TemporaryDirectory(
204
197
  prefix="jianying-reverse-", dir=out_dir
205
198
  ) as temporary_dir:
206
- prepared, generated = _prepare_reverse_sources(timeline, temporary_dir)
207
- content, meta, notes = build_draft(prepared, new_id=new_id, probe=probe)
199
+ generated = _prepare_reverse_sources(reverse_clips, temporary_dir)
200
+ content, meta, notes = _build_normalized_draft(timeline, new_id=new_id, probe=probe)
208
201
  notes.extend(f"已生成倒放素材: {source}" for source in generated)
209
202
  return _write_draft(
210
203
  content,
@@ -0,0 +1 @@
1
+ """Jianying (剪映) draft export subpackage."""