@remixmate/cli 0.1.0 → 0.1.2

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 (126) hide show
  1. package/README.md +100 -83
  2. package/README.zh-CN.md +183 -0
  3. package/dist/handlers/gen-digital-human.d.ts +12 -0
  4. package/dist/handlers/gen-digital-human.js +157 -0
  5. package/dist/handlers/gen-image.js +5 -41
  6. package/dist/handlers/gen-video.d.ts +18 -0
  7. package/dist/handlers/gen-video.js +153 -0
  8. package/dist/handlers/gen-voice.js +2 -12
  9. package/dist/handlers/index.js +4 -2
  10. package/dist/handlers/shared.d.ts +26 -0
  11. package/dist/handlers/shared.js +66 -0
  12. package/dist/http.d.ts +4 -2
  13. package/dist/http.js +5 -3
  14. package/dist/manifest.json +38 -24
  15. package/dist/registry.d.ts +5 -16
  16. package/dist/registry.js +11 -17
  17. package/dist/skill-schema.d.ts +65 -0
  18. package/dist/skill-schema.js +53 -0
  19. package/package.json +5 -4
  20. package/skills/export-jianying/scripts/gen_jianying_draft.py +4 -4
  21. package/skills/export-jianying/skill.json +1 -0
  22. package/skills/gen-digital-human/SKILL.md +23 -46
  23. package/skills/gen-digital-human/skill.json +4 -2
  24. package/skills/gen-digital-human/version.json +1 -1
  25. package/skills/gen-image/SKILL.md +2 -2
  26. package/skills/gen-image/skill.json +3 -1
  27. package/skills/gen-image/version.json +1 -1
  28. package/skills/gen-script/SKILL.md +13 -13
  29. package/skills/gen-script/scripts/gen_script.py +50 -12
  30. package/skills/gen-script/skill.json +3 -1
  31. package/skills/gen-video/SKILL.md +22 -33
  32. package/skills/gen-video/skill.json +4 -2
  33. package/skills/gen-video/version.json +1 -1
  34. package/skills/gen-voice/SKILL.md +1 -1
  35. package/skills/gen-voice/skill.json +1 -0
  36. package/skills/gen-voice/version.json +1 -1
  37. package/skills/prepare-video-assets/SKILL.md +2 -2
  38. package/skills/prepare-video-assets/skill.json +2 -1
  39. package/skills/render-video/scripts/render_video.py +8 -8
  40. package/skills/render-video/skill.json +1 -0
  41. package/skills/{template-bind → template-registry}/README.md +4 -4
  42. package/skills/{template-bind → template-registry}/SKILL.md +14 -12
  43. package/skills/template-registry/scripts/list_templates.py +214 -0
  44. package/skills/{template-bind → template-registry}/scripts/match_template.py +4 -3
  45. package/skills/{template-bind → template-registry}/scripts/registry_loader.py +1 -1
  46. package/skills/{template-bind → template-registry}/scripts/template_paths.py +7 -7
  47. package/skills/{template-bind → template-registry}/skill.json +8 -5
  48. package/skills/template-registry/version.json +7 -0
  49. package/skills/{template-bind → template-registry}/video_dsl/README.md +2 -2
  50. package/skills/{template-bind → template-registry}/video_dsl/runtime/__init__.py +1 -1
  51. package/skills/video-parser/SKILL.md +47 -160
  52. package/skills/video-parser/skill.json +4 -4
  53. package/skills/video-parser/version.json +1 -1
  54. package/skills/web-capture/SKILL.md +407 -116
  55. package/skills/web-capture/scripts/_media_screenshot/__init__.py +21 -0
  56. package/skills/web-capture/scripts/_media_screenshot/bootstrap.py +34 -0
  57. package/skills/web-capture/scripts/_media_screenshot/browser.py +86 -0
  58. package/skills/web-capture/scripts/_media_screenshot/cli_args.py +111 -0
  59. package/skills/web-capture/scripts/_media_screenshot/js/arrow.js +86 -0
  60. package/skills/web-capture/scripts/_media_screenshot/js/caption.js +27 -0
  61. package/skills/web-capture/scripts/_media_screenshot/js/clear_overlay.js +5 -0
  62. package/skills/web-capture/scripts/_media_screenshot/js/cursor_bootstrap.js +26 -0
  63. package/skills/web-capture/scripts/_media_screenshot/js/cursor_hide.js +6 -0
  64. package/skills/web-capture/scripts/_media_screenshot/js/cursor_move.js +12 -0
  65. package/skills/web-capture/scripts/_media_screenshot/js/cursor_ripple.js +25 -0
  66. package/skills/web-capture/scripts/_media_screenshot/js/element_zoom.js +72 -0
  67. package/skills/web-capture/scripts/_media_screenshot/js/element_zoom_restore.js +21 -0
  68. package/skills/web-capture/scripts/_media_screenshot/js/fade_out_overlays.js +10 -0
  69. package/skills/web-capture/scripts/_media_screenshot/js/focus.js +38 -0
  70. package/skills/web-capture/scripts/_media_screenshot/js/highlight.js +97 -0
  71. package/skills/web-capture/scripts/_media_screenshot/js/overlay_bootstrap.js +19 -0
  72. package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_in.js +54 -0
  73. package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_out.js +11 -0
  74. package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_restore.js +13 -0
  75. package/skills/web-capture/scripts/_media_screenshot/js/redact.js +33 -0
  76. package/skills/web-capture/scripts/_media_screenshot/js/scroll.js +26 -0
  77. package/skills/web-capture/scripts/_media_screenshot/js/scroll_through.js +18 -0
  78. package/skills/web-capture/scripts/_media_screenshot/js/sequence.js +76 -0
  79. package/skills/web-capture/scripts/_media_screenshot/js/settled_check.js +15 -0
  80. package/skills/web-capture/scripts/_media_screenshot/js/title_card.js +71 -0
  81. package/skills/web-capture/scripts/_media_screenshot/js_loader.py +14 -0
  82. package/skills/web-capture/scripts/_media_screenshot/overlay.py +17 -0
  83. package/skills/web-capture/scripts/_media_screenshot/recording.py +100 -0
  84. package/skills/web-capture/scripts/_media_screenshot/scenes/__init__.py +39 -0
  85. package/skills/web-capture/scripts/_media_screenshot/scenes/arrow.py +50 -0
  86. package/skills/web-capture/scripts/_media_screenshot/scenes/caption.py +20 -0
  87. package/skills/web-capture/scripts/_media_screenshot/scenes/click.py +35 -0
  88. package/skills/web-capture/scripts/_media_screenshot/scenes/code_lines.py +54 -0
  89. package/skills/web-capture/scripts/_media_screenshot/scenes/focus.py +24 -0
  90. package/skills/web-capture/scripts/_media_screenshot/scenes/highlight.py +54 -0
  91. package/skills/web-capture/scripts/_media_screenshot/scenes/hover.py +28 -0
  92. package/skills/web-capture/scripts/_media_screenshot/scenes/redact.py +32 -0
  93. package/skills/web-capture/scripts/_media_screenshot/scenes/scroll.py +32 -0
  94. package/skills/web-capture/scripts/_media_screenshot/scenes/sequence.py +43 -0
  95. package/skills/web-capture/scripts/_media_screenshot/scenes/title_card.py +20 -0
  96. package/skills/web-capture/scripts/_media_screenshot/scenes/type.py +42 -0
  97. package/skills/web-capture/scripts/_media_screenshot/scenes/wait.py +9 -0
  98. package/skills/web-capture/scripts/_media_screenshot/scenes/zoom.py +72 -0
  99. package/skills/web-capture/scripts/_media_screenshot/screenshot.py +166 -0
  100. package/skills/web-capture/scripts/_media_screenshot/storyboard.py +88 -0
  101. package/skills/web-capture/scripts/_media_screenshot/template.py +119 -0
  102. package/skills/web-capture/scripts/_media_screenshot/trim.py +82 -0
  103. package/skills/web-capture/scripts/record.py +186 -0
  104. package/skills/web-capture/scripts/screenshot.py +94 -0
  105. package/skills/web-capture/skill.json +15 -14
  106. package/skills/web-capture/templates/github-code-tour.json +59 -0
  107. package/skills/web-capture/templates/github-readme-tour.json +77 -0
  108. package/skills/web-capture/templates/github-repo-intro.json +74 -0
  109. package/skills/web-capture/version.json +2 -2
  110. package/dist/handlers/template-bind.d.ts +0 -15
  111. package/dist/handlers/template-bind.js +0 -149
  112. package/skills/gen-digital-human/scripts/gen_digital_human_video.py +0 -574
  113. package/skills/gen-video/scripts/gen_video.py +0 -591
  114. package/skills/template-bind/version.json +0 -7
  115. package/skills/web-capture/scripts/web_capture.py +0 -461
  116. /package/skills/{template-bind → template-registry}/scripts/check_contracts.py +0 -0
  117. /package/skills/{template-bind → template-registry}/scripts/render_job_client.py +0 -0
  118. /package/skills/{template-bind → template-registry}/scripts/sync_registry.py +0 -0
  119. /package/skills/{template-bind → template-registry}/video_dsl/runtime/dsl_validator.py +0 -0
  120. /package/skills/{template-bind → template-registry}/video_dsl/runtime/prompt_enhancer.py +0 -0
  121. /package/skills/{template-bind → template-registry}/video_dsl/runtime/template_binder.py +0 -0
  122. /package/skills/{template-bind → template-registry}/video_dsl/runtime/timeline_compiler.py +0 -0
  123. /package/skills/{template-bind → template-registry}/video_dsl/schema/render-plan-v1alpha1.json +0 -0
  124. /package/skills/{template-bind → template-registry}/video_dsl/schema/template-binding-v1alpha1.json +0 -0
  125. /package/skills/{template-bind → template-registry}/video_dsl/schema/template-definition-v1alpha1.json +0 -0
  126. /package/skills/{template-bind → template-registry}/video_dsl/schema/video-dsl-v1alpha1.json +0 -0
package/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # @remixmate/cli
2
2
 
3
- > 原名 `ab-skill-cli`(bin `ab-skill`),现已更名为 **`@remixmate/cli`**(bin **`remixmate`**)。旧包已在 npm 标记弃用,请迁移到新包。
3
+ English | [简体中文](./README.zh-CN.md)
4
+
5
+ > Formerly `ab-skill-cli` (bin `ab-skill`), now renamed to **`@remixmate/cli`** (bin **`remixmate`**). The old package is deprecated on npm — please migrate to the new one.
4
6
 
5
7
  AI media generation skills for Claude Code / Codex.
6
8
 
7
- 9 skills covering the full short-video production pipeline: image / video / voice / digital-human asset generation, script planning, template binding, Remotion rendering, and Jianying (CapCut) draft export.
9
+ 11 skills covering the full short-video production pipeline: image / video / voice / digital-human asset generation, web page capture, script planning, template binding, Remotion rendering, Jianying (CapCut) draft export, and video deconstruction.
8
10
 
9
11
  ## Install
10
12
 
@@ -46,121 +48,136 @@ cp .env.example .env
46
48
  source .env
47
49
  ```
48
50
 
49
- Python skills (6 of 9) require `python3 >= 3.10`. `video-parser` additionally requires `ffmpeg`.
50
-
51
- ---
51
+ Python skills (6 of 11) require `python3 >= 3.10`. `web-capture` requires Playwright (auto-installs chromium on first run). `ffmpeg` is only needed for `video-parser`'s optional local tool (`deconstruct_video.py`); the default `video-parser` entry runs server-side via ab-render and needs no local ffmpeg.
52
52
 
53
- ## AI 媒体生成 Agent Skills(中文)
53
+ ## Skills
54
54
 
55
- 本项目包含 9 AI 媒体生成技能,覆盖从素材生成、脚本编排、模板绑定、视频渲染到剪映导出的完整视频内容生产链路。
55
+ This project contains 11 AI media generation skills covering the full pipeline from asset generation, script orchestration, template binding, and video rendering to Jianying export.
56
56
 
57
- ### 技能分层
57
+ ### Skill layers
58
58
 
59
59
  ```
60
60
  ┌─────────────────────────────────────────────────────────────┐
61
- 编排层 Skills
62
- │ gen-script 主题 → Video DSL(脚本生成)
63
- │ template-bind DSL → TemplateBinding(模板列表)
64
- │ prepare-video-assets DSL + Binding → 素材补齐(Phase 1)
65
- │ render-video RenderPlan → Remotion 渲染(Phase 3
66
- │ export-jianying 素材剪映草稿 ZIP
61
+ Orchestration Skills
62
+ │ gen-script Topic → Video DSL (script generation)
63
+ │ template-registry DSL → TemplateBinding (template list)
64
+ │ prepare-video-assets DSL + Binding → asset resolve (Phase1)
65
+ │ render-video RenderPlan → Remotion render (Phase 3)
66
+ │ export-jianying AssetsJianying draft ZIP
67
67
  ├─────────────────────────────────────────────────────────────┤
68
- 原子层 Skills │
69
- │ gen-image 文生图 / 图生图(Seedream / Gemini
70
- │ gen-video 文生视频(Seedance / Veo
71
- │ gen-voice 语音合成(Minimax TTS
72
- │ gen-digital-human 数字人口播(即梦 / 飞影)
68
+ Atomic Skills │
69
+ │ gen-image Text/Image-to-image (Seedream / Gemini)
70
+ │ gen-video Text-to-video (Seedance / Veo)
71
+ │ gen-voice Text-to-speech (Minimax TTS)
72
+ │ gen-digital-human Talking-head (Jimeng / Feiying)
73
73
  ├─────────────────────────────────────────────────────────────┤
74
- 工具层 Skills
75
- │ video-parser 视频解构(音频提取 / ASR / 关键帧)
74
+ Tool Skills
75
+ │ video-parser Video deconstruction (audio / ASR / kf)
76
+ │ web-capture Web page screenshot / scroll-record │
76
77
  └─────────────────────────────────────────────────────────────┘
77
78
  ```
78
79
 
79
- ### 目录结构
80
+ ### Directory structure
80
81
 
81
82
  ```
82
83
  ├── docs/
83
- │ └── video-production-architecture.md # 架构文档
84
+ │ └── video-production-architecture.md # architecture docs
85
+ ├── src/ # TypeScript CLI + http/builtin handlers
84
86
  ├── skills/
85
- │ ├── gen-image/ # 原子: AI 生图
86
- │ ├── gen-video/ # 原子: AI 生视频
87
- │ ├── gen-voice/ # 原子: 语音合成
88
- │ ├── gen-digital-human/ # 原子: 数字人口播
89
- │ ├── gen-script/ # 编排: 主题 → Video DSL
90
- │ ├── template-bind/ # 编排: 模板列表(含模板注册表 + DSL Schema)
91
- │ ├── prepare-video-assets/ # 编排: Phase 1 素材准备(thin wrapper
92
- │ ├── render-video/ # 编排: Phase 3 Remotion 渲染(含 render_video.py 实现)
93
- │ ├── export-jianying/ # 编排: 导出剪映草稿 ZIP
94
- └── video-parser/ # 工具: 视频解构与分析
87
+ │ ├── gen-image/ # atomic: AI image generation (http handler)
88
+ │ ├── gen-video/ # atomic: AI video generation (http handler)
89
+ │ ├── gen-voice/ # atomic: text-to-speech (http handler)
90
+ │ ├── gen-digital-human/ # atomic: talking-head video (http handler)
91
+ │ ├── gen-script/ # orchestration: Topic → Video DSL
92
+ │ ├── template-registry/ # orchestration: template list (python list_templates.py)
93
+ │ ├── prepare-video-assets/ # orchestration: Phase 1 asset prep (thin wrapper)
94
+ │ ├── render-video/ # orchestration: Phase 3 Remotion render (canonical render_video.py)
95
+ │ ├── export-jianying/ # orchestration: export Jianying draft ZIP
96
+ ├── video-parser/ # tool: video deconstruction & analysis
97
+ │ └── web-capture/ # tool: headless-browser screenshot / recording
95
98
  └── README.md
96
99
  ```
97
100
 
98
- ### 技能说明
101
+ ### Skill reference
99
102
 
100
- | 技能 | 类型 | 说明 | 核心脚本 |
101
- |------|------|------|----------|
102
- | gen-image | 原子 | 文生图 / 图生图(SeedreamGemini | `gen_image.py` |
103
- | gen-video | 原子 | 文生视频(SeedanceVeo | `gen_video.py` |
104
- | gen-voice | 原子 | 语音合成(Minimax TTS | `gen_voice.py` |
105
- | gen-digital-human | 原子 | 数字人口播(即梦 / 飞影) | `gen_digital_human_video.py` |
106
- | gen-script | 编排 | 主题 → Video DSL JSON | `gen_script.py` |
107
- | template-bind | 编排 | 模板列表(绑定逻辑内嵌于 prepare-video-assets | `match_template.py` |
108
- | prepare-video-assets | 编排 | DSL + Binding → 素材补齐落库 RenderPlan | `render_video.py --resolve-only`(wrapper) |
109
- | render-video | 编排 | job_id → Remotion 渲染上传 | `render_video.py` |
110
- | export-jianying | 编排 | 素材 URL剪映草稿 ZIP(支持从 RenderPlan 自动转换) | `gen_jianying_draft.py` |
111
- | video-parser | 工具 | 视频音频 + ASR + 关键帧 + 场景分段 | `deconstruct_video.py` |
103
+ | Skill | Type | Description | Runtime / entry |
104
+ |-------|------|-------------|-----------------|
105
+ | gen-image | atomic | Text/Image-to-image (Seedream, Gemini) | http handler |
106
+ | gen-video | atomic | Text-to-video (Seedance, Veo) | http handler |
107
+ | gen-voice | atomic | Text-to-speech (Minimax TTS) | http handler |
108
+ | gen-digital-human | atomic | Talking-head (Jimeng / Feiying) | http handler |
109
+ | gen-script | orchestration | Topic → Video DSL JSON | python `scripts/gen_script.py` |
110
+ | template-registry | orchestration | Template list (binding logic embedded in prepare-video-assets) | python `scripts/list_templates.py` |
111
+ | prepare-video-assets | orchestration | DSL + Binding → asset resolve persist RenderPlan | python `scripts/prepare_video_assets.py` (wraps `render_video.py --resolve-only`) |
112
+ | render-video | orchestration | job_id → Remotion renderupload | python `scripts/render_video.py` |
113
+ | export-jianying | orchestration | Asset URLsJianying draft ZIP (auto-converts from RenderPlan) | python `scripts/gen_jianying_draft.py` |
114
+ | video-parser | tool | Videoaudio + ASR + keyframes + scene segmentation | python `scripts/parse_via_render.py` |
115
+ | web-capture | tool | Web page screenshot / scroll-record / storyboard video | python `scripts/screenshot.py`, `scripts/record.py` |
112
116
 
113
- ### 核心链路
117
+ ### Core workflows
114
118
 
115
- 详见 [视频内容生产架构文档](docs/video-production-architecture.md) [编排流程指南](docs/orchestration-guide.md)
119
+ See the [video production architecture doc](docs/video-production-architecture.md) and the [orchestration guide](docs/orchestration-guide.md).
116
120
 
117
- **链路 A:主题 → Remotion 视频**
121
+ **Workflow A: Topic → Remotion video**
118
122
  ```
119
- gen-script → ✅用户确认脚本 → prepare-video-assets(--template-id)
120
- ✅用户确认素材 → render-video(--job-id) → MP4
123
+ gen-script → user confirms script → prepare-video-assets(--template-id)
124
+ user confirms assets → render-video(--job-id) → MP4
121
125
  ```
122
126
 
123
- **链路 B:主题剪映草稿**
127
+ **Workflow B: Topic Jianying draft**
124
128
  ```
125
- gen-script → ✅用户确认脚本 → prepare-video-assets(--template-id)
126
- ✅用户确认素材 → export-jianying(--from-job-id) → 剪映 ZIP
129
+ gen-script → user confirms script → prepare-video-assets(--template-id)
130
+ user confirms assets → export-jianying(--from-job-id) → Jianying ZIP
127
131
  ```
128
132
 
129
- ### 测试
133
+ ### Testing
130
134
 
131
135
  ```bash
132
- # 各脚本 --help 可正常运行
133
- python3 skills/gen-image/scripts/gen_image.py --help
134
- python3 skills/gen-video/scripts/gen_video.py --help
135
- python3 skills/gen-voice/scripts/gen_voice.py --help
136
- python3 skills/gen-digital-human/scripts/gen_digital_human_video.py --help
137
- python3 skills/gen-script/scripts/gen_script.py --help
138
- python3 skills/template-bind/scripts/match_template.py --help
139
- python3 skills/render-video/scripts/render_video.py --help
140
- python3 skills/prepare-video-assets/scripts/prepare_video_assets.py --help
141
- python3 skills/export-jianying/scripts/gen_jianying_draft.py --help
142
- python3 skills/video-parser/scripts/deconstruct_video.py --help
143
-
144
- # 查看可用音色
145
- python3 skills/gen-voice/scripts/gen_voice.py --list-voices
146
-
147
- # 查看可用模板
148
- python3 skills/template-bind/scripts/match_template.py --list-templates
136
+ # List all skills (name, tool, entry type)
137
+ remixmate --list
138
+
139
+ # Offline registry smoke + spec guards
140
+ npm run smoke
141
+
142
+ # CLI unit tests (argv parser + skill schema)
143
+ npm run test:cli
144
+
145
+ # Python skills forward --help to the underlying script:
146
+ remixmate gen-script --help
147
+ remixmate prepare-video-assets --help
148
+ remixmate render-video --help
149
+ remixmate export-jianying --help
150
+ remixmate video-parser --help
151
+ remixmate web-capture --help
152
+ remixmate template-registry --help
153
+
154
+ # http skills (gen-image, gen-video, gen-voice, gen-digital-human) take no
155
+ # python --help; their flags live in each SKILL.md / skill.json.
156
+
157
+ # List available voices
158
+ remixmate gen-voice --list-voices
159
+
160
+ # List available templates
161
+ remixmate template-registry --list-templates
149
162
  ```
150
163
 
151
- ### 开发流程
164
+ ### Development
152
165
 
153
- - 克隆此项目到本地
154
- - skills 目录下各技能文件夹中开发
155
- - 每个技能包含 `SKILL.md`(技能说明)、`version.json`(元数据)和 `scripts/`(脚本)
166
+ - Clone this project locally
167
+ - Develop inside each skill folder under `skills/`
168
+ - Each skill contains `SKILL.md` (skill docs), `version.json` (metadata), and `scripts/` (scripts)
156
169
 
157
- ### 快速体验
170
+ ### Quick start
158
171
 
159
172
  ```
160
- @skills/gen-image/SKILL.md 生成一张熊猫的图片,9:16,调用gemini 3.1,国画风 + 严格按该文档执行
161
- @skills/gen-video/SKILL.md 生成一段熊猫在竹林奔跑的视频,9:16,长度6秒,调用veo + 严格按该文档执行
162
- @skills/gen-voice/SKILL.md 生成一段语音,介绍熊猫的习性,大概100字左右 + 严格按该文档执行
163
- @skills/gen-digital-human/SKILL.md 获取数字人列表 + 严格按该文档执行
164
- @skills/template-bind/SKILL.md 获取模版列表 + 严格按该文档执行
165
- @skills/gen-script/SKILL.md 基于模版 image-slide,创作一个关于AI学习方法的视频 + 严格按该文档执行
173
+ @skills/gen-image/SKILL.md Generate an image of a panda, 9:16, using gemini 3.1, Chinese-painting style + follow this doc strictly
174
+ @skills/gen-video/SKILL.md Generate a video of a panda running in a bamboo forest, 9:16, 6 seconds, using veo + follow this doc strictly
175
+ @skills/gen-voice/SKILL.md Generate a voiceover introducing panda habits, around 100 words + follow this doc strictly
176
+ @skills/gen-digital-human/SKILL.md Get the digital human list + follow this doc strictly
177
+ @skills/template-registry/SKILL.md Get the template list + follow this doc strictly
178
+ @skills/gen-script/SKILL.md Based on the image-slide template, create a video about AI learning methods + follow this doc strictly
166
179
  ```
180
+
181
+ ## License
182
+
183
+ MIT
@@ -0,0 +1,183 @@
1
+ # @remixmate/cli
2
+
3
+ [English](./README.md) | 简体中文
4
+
5
+ > 原名 `ab-skill-cli`(bin `ab-skill`),现已更名为 **`@remixmate/cli`**(bin **`remixmate`**)。旧包已在 npm 标记弃用,请迁移到新包。
6
+
7
+ 面向 Claude Code / Codex 的 AI 媒体生成技能集。
8
+
9
+ 包含 11 个技能,覆盖完整的短视频生产链路:图片 / 视频 / 语音 / 数字人素材生成、网页捕获、脚本编排、模板绑定、Remotion 渲染、剪映(CapCut)草稿导出,以及视频解构。
10
+
11
+ ## 安装
12
+
13
+ ```bash
14
+ npm install -g @remixmate/cli
15
+ remixmate --help
16
+ remixmate --list
17
+ ```
18
+
19
+ ## 在 Claude Code 中使用
20
+
21
+ 把内置的 `skills/` 拷贝到项目级或全局的 `.claude/skills/` 目录,Claude Code 会自动识别:
22
+
23
+ ```bash
24
+ # 项目级
25
+ mkdir -p .claude/skills
26
+ cp -R "$(npm root -g)/@remixmate/cli/skills/." .claude/skills/
27
+
28
+ # 或全局
29
+ mkdir -p ~/.claude/skills
30
+ cp -R "$(npm root -g)/@remixmate/cli/skills/." ~/.claude/skills/
31
+ ```
32
+
33
+ ## 在 Codex 中使用
34
+
35
+ Codex 不会原生加载 `SKILL.md`。在系统提示里告诉 Codex 这个 CLI,让它在需要媒体生成时调用 `remixmate <skill> ...`:
36
+
37
+ > 当你需要 AI 媒体生成(图片 / 视频 / 语音 / 数字人 / 剪映导出)时,先运行 `remixmate <skill-id> --help` 查看参数,再用 `remixmate <skill-id> --json-output ...` 执行。可用技能:`remixmate --list`。
38
+
39
+ 完整介绍页(Claude Code / Codex 配置、环境变量、端到端工作流示例)见项目主页。
40
+
41
+ ## 环境
42
+
43
+ 多数技能通过 `PRIV_TOKEN` 向 ab-api 鉴权。没有有效 token(以及访问 ab-api 的网络)时,模板 / 媒体生成类技能不可用——代码是开源的,但生成能力托管在 ab-api 服务上。运行前把 `.env.example` 拷为 `.env` 并 source:
44
+
45
+ ```bash
46
+ cp .env.example .env
47
+ # 修改其中的值
48
+ source .env
49
+ ```
50
+
51
+ Python 技能(11 个中的 6 个)需要 `python3 >= 3.10`。`web-capture` 需要 Playwright(首次运行自动安装 chromium)。`ffmpeg` 仅 `video-parser` 的可选本地工具(`deconstruct_video.py`)需要;`video-parser` 默认入口走 ab-render 服务端解构,无需本地 ffmpeg。
52
+
53
+ ## 技能
54
+
55
+ 本项目包含 11 个 AI 媒体生成技能,覆盖从素材生成、脚本编排、模板绑定、视频渲染到剪映导出的完整视频内容生产链路。
56
+
57
+ ### 技能分层
58
+
59
+ ```
60
+ ┌─────────────────────────────────────────────────────────────┐
61
+ │ 编排层 Skills │
62
+ │ gen-script 主题 → Video DSL(脚本生成) │
63
+ │ template-registry DSL → TemplateBinding(模板列表) │
64
+ │ prepare-video-assets DSL + Binding → 素材补齐(Phase 1) │
65
+ │ render-video RenderPlan → Remotion 渲染(Phase 3) │
66
+ │ export-jianying 素材 → 剪映草稿 ZIP │
67
+ ├─────────────────────────────────────────────────────────────┤
68
+ │ 原子层 Skills │
69
+ │ gen-image 文生图 / 图生图(Seedream / Gemini) │
70
+ │ gen-video 文生视频(Seedance / Veo) │
71
+ │ gen-voice 语音合成(Minimax TTS) │
72
+ │ gen-digital-human 数字人口播(即梦 / 飞影) │
73
+ ├─────────────────────────────────────────────────────────────┤
74
+ │ 工具层 Skills │
75
+ │ video-parser 视频解构(音频提取 / ASR / 关键帧) │
76
+ │ web-capture 网页截图 / 滚动录屏 / 分镜视频 │
77
+ └─────────────────────────────────────────────────────────────┘
78
+ ```
79
+
80
+ ### 目录结构
81
+
82
+ ```
83
+ ├── docs/
84
+ │ └── video-production-architecture.md # 架构文档
85
+ ├── src/ # TypeScript CLI + http/builtin handlers
86
+ ├── skills/
87
+ │ ├── gen-image/ # 原子: AI 生图(http handler)
88
+ │ ├── gen-video/ # 原子: AI 生视频(http handler)
89
+ │ ├── gen-voice/ # 原子: 语音合成(http handler)
90
+ │ ├── gen-digital-human/ # 原子: 数字人口播(http handler)
91
+ │ ├── gen-script/ # 编排: 主题 → Video DSL
92
+ │ ├── template-registry/ # 编排: 模板列表(python list_templates.py)
93
+ │ ├── prepare-video-assets/ # 编排: Phase 1 素材准备(thin wrapper)
94
+ │ ├── render-video/ # 编排: Phase 3 Remotion 渲染(含 render_video.py 实现)
95
+ │ ├── export-jianying/ # 编排: 导出剪映草稿 ZIP
96
+ │ ├── video-parser/ # 工具: 视频解构与分析
97
+ │ └── web-capture/ # 工具: 无头浏览器截图 / 录屏
98
+ └── README.md
99
+ ```
100
+
101
+ ### 技能说明
102
+
103
+ | 技能 | 类型 | 说明 | 运行方式 / entry |
104
+ |------|------|------|------------------|
105
+ | gen-image | 原子 | 文生图 / 图生图(Seedream、Gemini) | http handler |
106
+ | gen-video | 原子 | 文生视频(Seedance、Veo) | http handler |
107
+ | gen-voice | 原子 | 语音合成(Minimax TTS) | http handler |
108
+ | gen-digital-human | 原子 | 数字人口播(即梦 / 飞影) | http handler |
109
+ | gen-script | 编排 | 主题 → Video DSL JSON | python `scripts/gen_script.py` |
110
+ | template-registry | 编排 | 模板列表(绑定逻辑内嵌于 prepare-video-assets) | python `scripts/list_templates.py` |
111
+ | prepare-video-assets | 编排 | DSL + Binding → 素材补齐 → 落库 RenderPlan | python `scripts/prepare_video_assets.py`(包装 `render_video.py --resolve-only`) |
112
+ | render-video | 编排 | job_id → Remotion 渲染 → 上传 | python `scripts/render_video.py` |
113
+ | export-jianying | 编排 | 素材 URL → 剪映草稿 ZIP(支持从 RenderPlan 自动转换) | python `scripts/gen_jianying_draft.py` |
114
+ | video-parser | 工具 | 视频 → 音频 + ASR + 关键帧 + 场景分段 | python `scripts/parse_via_render.py` |
115
+ | web-capture | 工具 | 网页截图 / 滚动录屏 / 分镜视频 | python `scripts/screenshot.py`、`scripts/record.py` |
116
+
117
+ ### 核心链路
118
+
119
+ 详见 [视频内容生产架构文档](docs/video-production-architecture.md) 和 [编排流程指南](docs/orchestration-guide.md)。
120
+
121
+ **链路 A:主题 → Remotion 视频**
122
+ ```
123
+ gen-script → ✅用户确认脚本 → prepare-video-assets(--template-id)
124
+ → ✅用户确认素材 → render-video(--job-id) → MP4
125
+ ```
126
+
127
+ **链路 B:主题 → 剪映草稿**
128
+ ```
129
+ gen-script → ✅用户确认脚本 → prepare-video-assets(--template-id)
130
+ → ✅用户确认素材 → export-jianying(--from-job-id) → 剪映 ZIP
131
+ ```
132
+
133
+ ### 测试
134
+
135
+ ```bash
136
+ # 列出所有技能(名称、tool、entry 类型)
137
+ remixmate --list
138
+
139
+ # 离线注册表 smoke + 规范守卫
140
+ npm run smoke
141
+
142
+ # CLI 单元测试(argv 解析器 + skill schema)
143
+ npm run test:cli
144
+
145
+ # Python 技能会把 --help 透传给底层脚本:
146
+ remixmate gen-script --help
147
+ remixmate prepare-video-assets --help
148
+ remixmate render-video --help
149
+ remixmate export-jianying --help
150
+ remixmate video-parser --help
151
+ remixmate web-capture --help
152
+ remixmate template-registry --help
153
+
154
+ # http 技能(gen-image、gen-video、gen-voice、gen-digital-human)没有
155
+ # python --help;参数见各自的 SKILL.md / skill.json。
156
+
157
+ # 查看可用音色
158
+ remixmate gen-voice --list-voices
159
+
160
+ # 查看可用模板
161
+ remixmate template-registry --list-templates
162
+ ```
163
+
164
+ ### 开发流程
165
+
166
+ - 克隆此项目到本地
167
+ - 在 skills 目录下各技能文件夹中开发
168
+ - 每个技能包含 `SKILL.md`(技能说明)、`version.json`(元数据)和 `scripts/`(脚本)
169
+
170
+ ### 快速体验
171
+
172
+ ```
173
+ @skills/gen-image/SKILL.md 生成一张熊猫的图片,9:16,调用gemini 3.1,国画风 + 严格按该文档执行
174
+ @skills/gen-video/SKILL.md 生成一段熊猫在竹林奔跑的视频,9:16,长度6秒,调用veo + 严格按该文档执行
175
+ @skills/gen-voice/SKILL.md 生成一段语音,介绍熊猫的习性,大概100字左右 + 严格按该文档执行
176
+ @skills/gen-digital-human/SKILL.md 获取数字人列表 + 严格按该文档执行
177
+ @skills/template-registry/SKILL.md 获取模版列表 + 严格按该文档执行
178
+ @skills/gen-script/SKILL.md 基于模版 image-slide,创作一个关于AI学习方法的视频 + 严格按该文档执行
179
+ ```
180
+
181
+ ## 许可证
182
+
183
+ MIT
@@ -0,0 +1,12 @@
1
+ /**
2
+ * gen-digital-human handler — talking-head video, three modes:
3
+ * --list-avatars true → POST /digital-human/avatar/page (list)
4
+ * --check-status --generation-id <id> → POST /digital-human/video/status (one-shot)
5
+ * default (--avatar-id <id> ...) → generate: resolve avatar → submit → poll
6
+ *
7
+ * Ported from `scripts/gen_digital_human_video.py` (python → http) so it shares
8
+ * auth / base-URL / business-code handling with the other generators via
9
+ * http.ts. Endpoints and payloads match the backend DigitalHumanVideoGenerateDTO.
10
+ */
11
+ import type { HandlerContext, HandlerInput } from './index.js';
12
+ export declare function genDigitalHuman(input: HandlerInput, ctxIn: HandlerContext): Promise<void>;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * gen-digital-human handler — talking-head video, three modes:
3
+ * --list-avatars true → POST /digital-human/avatar/page (list)
4
+ * --check-status --generation-id <id> → POST /digital-human/video/status (one-shot)
5
+ * default (--avatar-id <id> ...) → generate: resolve avatar → submit → poll
6
+ *
7
+ * Ported from `scripts/gen_digital_human_video.py` (python → http) so it shares
8
+ * auth / base-URL / business-code handling with the other generators via
9
+ * http.ts. Endpoints and payloads match the backend DigitalHumanVideoGenerateDTO.
10
+ */
11
+ import { mmPost, pollUntil, resolveHttpContext, SkillError } from '../http.js';
12
+ import { emitProgress } from '../progress.js';
13
+ import { isTrue, toNumber } from './shared.js';
14
+ const VALID_SOURCES = new Set(['jimeng', 'hifly']);
15
+ const DEFAULT_VOICE_ID = 'male-qn-qingse';
16
+ async function listAvatars(ctx, input) {
17
+ const payload = { current: 1, pageSize: 100 };
18
+ if (input.source)
19
+ payload.source = String(input.source);
20
+ if (input.gender)
21
+ payload.gender = String(input.gender);
22
+ if (isTrue(input.mine))
23
+ payload.mine = true;
24
+ if (input.name)
25
+ payload.name = String(input.name);
26
+ const data = await mmPost(ctx, '/digital-human/avatar/page', payload, { timeoutMs: 30_000 });
27
+ const avatars = data.list ?? [];
28
+ if (isTrue(input.json_output)) {
29
+ process.stdout.write(JSON.stringify({ avatars }) + '\n');
30
+ return;
31
+ }
32
+ if (avatars.length === 0) {
33
+ process.stdout.write('⚠️ No avatars available\n');
34
+ return;
35
+ }
36
+ process.stdout.write(`\n${'ID'.padEnd(8)} ${'Name'.padEnd(16)} ${'Source'.padEnd(10)} ${'Gender'.padEnd(8)} Ratio\n`);
37
+ process.stdout.write(`${'-'.repeat(8)} ${'-'.repeat(16)} ${'-'.repeat(10)} ${'-'.repeat(8)} ${'-'.repeat(10)}\n`);
38
+ for (const a of avatars) {
39
+ process.stdout.write(`${String(a.id ?? '').padEnd(8)} ${String(a.name ?? '').padEnd(16)} ${String(a.source ?? '').padEnd(10)} ${String(a.gender ?? '').padEnd(8)} ${a.aspectRatio ?? ''}\n`);
40
+ }
41
+ process.stdout.write(`\n${avatars.length} avatar(s) available\n`);
42
+ process.stdout.write('💡 Use --avatar-id <ID> to pick an avatar for generation\n');
43
+ }
44
+ /** Look up one avatar's metadata; checks the normal page then `mine: true`. */
45
+ async function fetchAvatarInfo(ctx, avatarId) {
46
+ for (const extra of [{}, { mine: true }]) {
47
+ const data = await mmPost(ctx, '/digital-human/avatar/page', { current: 1, pageSize: 100, ...extra }, { timeoutMs: 30_000 });
48
+ const found = (data.list ?? []).find((a) => String(a.id) === String(avatarId));
49
+ if (found)
50
+ return found;
51
+ }
52
+ throw new SkillError(`❌ avatar_id=${avatarId} not found; use --list-avatars [--mine] to see what is available`);
53
+ }
54
+ function resolveSource(explicit, avatar) {
55
+ const src = (explicit ?? '').trim() || (avatar.source ?? '').trim();
56
+ if (!VALID_SOURCES.has(src)) {
57
+ throw new SkillError('❌ Could not determine a valid source (jimeng/hifly). Pass --source, or confirm the avatar carries a source field.');
58
+ }
59
+ return src;
60
+ }
61
+ async function checkStatus(ctx, generationId, json) {
62
+ const data = await mmPost(ctx, '/digital-human/video/status', { generationId }, { timeoutMs: 30_000 });
63
+ const status = data.status ?? 'unknown';
64
+ if (json) {
65
+ process.stdout.write(JSON.stringify({ status, url: data.videoUrl ?? null, generationId }) + '\n');
66
+ return;
67
+ }
68
+ process.stdout.write(`\ntask status: ${status}\n`);
69
+ if (data.videoUrl)
70
+ process.stdout.write(` video URL: ${data.videoUrl}\n`);
71
+ if (status === 'failed') {
72
+ const err = data.errorMessage ?? data.error ?? data.message ?? 'unknown error';
73
+ process.stdout.write(` failure reason: ${err}\n`);
74
+ }
75
+ }
76
+ async function pollVideoStatus(ctx, generationId) {
77
+ const url = await pollUntil(async () => {
78
+ const data = await mmPost(ctx, '/digital-human/video/status', { generationId }, { timeoutMs: 30_000 });
79
+ const status = data.status ?? 'unknown';
80
+ emitProgress({ phase: 'gen-digital-human:poll', generationId, status });
81
+ if (status === 'completed')
82
+ return data.videoUrl ?? '';
83
+ if (status === 'failed') {
84
+ const err = data.errorMessage ?? data.error ?? data.message ?? 'unknown error';
85
+ throw new SkillError(`❌ video generation failed: ${err}`);
86
+ }
87
+ return null;
88
+ }, { intervalMs: 5_000, timeoutMs: 600_000 });
89
+ return url;
90
+ }
91
+ export async function genDigitalHuman(input, ctxIn) {
92
+ const ctx = resolveHttpContext(ctxIn.skillName, {
93
+ apiBaseUrl: input.api_base_url,
94
+ privateToken: input.priv_token,
95
+ });
96
+ // ── Mode 1: list avatars ────────────────────────────────────────────────
97
+ if (isTrue(input.list_avatars)) {
98
+ return listAvatars(ctx, input);
99
+ }
100
+ // ── Mode 3: check status ────────────────────────────────────────────────
101
+ if (isTrue(input.check_status)) {
102
+ const generationId = toNumber(input.generation_id, 'generation_id');
103
+ if (generationId === undefined) {
104
+ throw new SkillError('❌ check-status mode requires --generation-id');
105
+ }
106
+ return checkStatus(ctx, generationId, isTrue(input.json_output));
107
+ }
108
+ // ── Mode 2: generate (default) ──────────────────────────────────────────
109
+ const avatarId = toNumber(input.avatar_id, 'avatar_id');
110
+ if (avatarId === undefined) {
111
+ throw new SkillError('❌ provide --avatar-id to pick the avatar (use --list-avatars to see available avatars)');
112
+ }
113
+ const audioUrl = (input.audio_url ?? '').trim();
114
+ const text = input.text ?? '';
115
+ if (!audioUrl) {
116
+ if (!text.trim()) {
117
+ throw new SkillError('❌ in TTS mode provide --text, or use --audio-url for audio-driven mode');
118
+ }
119
+ }
120
+ emitProgress({ phase: 'gen-digital-human:resolve-avatar', avatarId });
121
+ const avatar = await fetchAvatarInfo(ctx, avatarId);
122
+ const source = resolveSource(input.source, avatar);
123
+ const payload = { avatarId, source };
124
+ if (audioUrl) {
125
+ payload.audioUrl = audioUrl;
126
+ if (text.trim())
127
+ payload.text = text.trim();
128
+ }
129
+ else {
130
+ payload.text = text;
131
+ payload.voiceId = input.voice_id ?? DEFAULT_VOICE_ID;
132
+ if (input.voice_name)
133
+ payload.voiceName = String(input.voice_name);
134
+ }
135
+ const aspectRatio = input.aspect_ratio ?? avatar.aspectRatio;
136
+ if (aspectRatio)
137
+ payload.aspectRatio = aspectRatio;
138
+ if (input.prompt)
139
+ payload.prompt = String(input.prompt);
140
+ emitProgress({ phase: 'gen-digital-human:request', avatarId, source, mode: audioUrl ? 'audio' : 'tts' });
141
+ const data = await mmPost(ctx, '/digital-human/video/generate', payload, { timeoutMs: 60_000 });
142
+ const generationId = data.generationId;
143
+ if (!generationId) {
144
+ throw new SkillError(`❌ could not parse generationId; API returned: ${JSON.stringify(data)}`);
145
+ }
146
+ emitProgress({ phase: 'gen-digital-human:async', generationId });
147
+ const videoUrl = await pollVideoStatus(ctx, generationId);
148
+ if (!videoUrl) {
149
+ throw new SkillError(`❌ video generated but no URL was returned; rerun --check-status --generation-id ${generationId} later`);
150
+ }
151
+ if (isTrue(input.json_output)) {
152
+ process.stdout.write(JSON.stringify({ url: videoUrl, generationId }) + '\n');
153
+ return;
154
+ }
155
+ process.stdout.write(`\n🔗 Video URL (renders directly, no download needed):\n${videoUrl}\n`);
156
+ process.stdout.write('\n🎉 Digital-human video generation done!\n');
157
+ }