@remixmate/cli 0.9.17 → 0.9.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/manifest.json +949 -14
- package/dist/project/host.d.ts +15 -1
- package/dist/project/host.js +47 -2
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +1 -0
- package/dist/runner.d.ts +18 -0
- package/dist/runner.js +28 -2
- package/dist/skill-schema.d.ts +40 -0
- package/dist/skill-schema.js +108 -0
- package/package.json +1 -1
- package/skills/export-jianying/skill.json +62 -10
- package/skills/gen-digital-human/skill.json +23 -0
- package/skills/gen-image/skill.json +20 -0
- package/skills/gen-script/skill.json +94 -17
- package/skills/gen-video/skill.json +22 -0
- package/skills/gen-voice/skill.json +14 -0
- package/skills/render-video/SKILL.md +11 -1
- package/skills/render-video/scripts/render_video.py +20 -0
- package/skills/render-video/skill.json +1 -0
- package/skills/video-parser/skill.json +13 -0
- package/skills/web-record/skill.json +38 -0
- package/skills/web-screenshot/skill.json +21 -0
|
@@ -6,39 +6,116 @@
|
|
|
6
6
|
"title": "Video Script Generation",
|
|
7
7
|
"description": "Video script generation: turn a topic into a structured Video DSL (JSON) that describes the full video — scene structure, asset requirements, and narrative flow.",
|
|
8
8
|
"auth": "none",
|
|
9
|
-
"envVars": [
|
|
9
|
+
"envVars": [
|
|
10
|
+
"DEFAULT_IMAGE_MODEL",
|
|
11
|
+
"DEFAULT_VIDEO_MODEL",
|
|
12
|
+
"STUB_IMAGE_URL",
|
|
13
|
+
"STUB_VIDEO_URL"
|
|
14
|
+
],
|
|
10
15
|
"scriptPath": "scripts/gen_script.py",
|
|
11
16
|
"parameters": {
|
|
12
17
|
"type": "object",
|
|
13
18
|
"properties": {
|
|
14
|
-
"topic": {
|
|
19
|
+
"topic": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Video topic (required)"
|
|
22
|
+
},
|
|
15
23
|
"platform": {
|
|
16
24
|
"type": "string",
|
|
17
|
-
"enum": [
|
|
25
|
+
"enum": [
|
|
26
|
+
"douyin",
|
|
27
|
+
"xiaohongshu",
|
|
28
|
+
"bilibili",
|
|
29
|
+
"wechat",
|
|
30
|
+
"youtube",
|
|
31
|
+
"generic"
|
|
32
|
+
],
|
|
18
33
|
"description": "Target platform"
|
|
19
34
|
},
|
|
20
|
-
"duration": {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
"duration": {
|
|
36
|
+
"type": "number",
|
|
37
|
+
"description": "Target duration in seconds"
|
|
38
|
+
},
|
|
39
|
+
"style": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Style tag"
|
|
42
|
+
},
|
|
43
|
+
"ratio": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "Aspect ratio, e.g. 16:9 or 9:16"
|
|
46
|
+
},
|
|
47
|
+
"scenes": {
|
|
48
|
+
"type": "number",
|
|
49
|
+
"description": "Scene count"
|
|
50
|
+
},
|
|
51
|
+
"voice_id": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "Narration voice id. Default depends on the bound template's outputLanguage; query gen_voice with list_voices=true to see available ids."
|
|
54
|
+
},
|
|
55
|
+
"template_id": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"description": "Template id (e.g. html-slide). The template owns outputLanguage and may also declare a defaultVoiceId; both flow into the produced DSL."
|
|
58
|
+
},
|
|
59
|
+
"headline": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "On-screen headline (recommended 4-12 chars / ~3 words). Stored at meta.headline and pushed into every scene's textLayers[role=headline] so the template can render it as the top big-text. **Must** be set when the user explicitly provided a headline / main title; without it, headline falls back to the long-form topic and overflows the top text layer."
|
|
62
|
+
},
|
|
63
|
+
"subheadline": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "On-screen subheadline (project name / slogan / source, e.g. 'Pixelle-Video'). Stored at meta.subheadline and pushed into every scene's textLayers[role=subheadline] so the template can render it as the top small-text. **Must** be set when the user explicitly provided a subtitle / project name. Note: this is the on-screen subheadline, not the CC subtitle (global.subtitle) — they are independent."
|
|
66
|
+
},
|
|
28
67
|
"carousel_items": {
|
|
29
68
|
"type": "array",
|
|
30
|
-
"items": {
|
|
69
|
+
"items": {
|
|
70
|
+
"type": "string"
|
|
71
|
+
},
|
|
31
72
|
"description": "Media URLs for the template's image/video carousel (e.g. spotlight-card's middle carousel). When provided together with a template_id whose capabilities.payloadStyle=carousel-caption, these URLs are placed directly into customPayload.carousel.items as existing assets — NO AI image generation is triggered. **Must** pass when the user explicitly provides image/video URLs for carousel-style templates (spotlight-card, etc.). Each element is a full URL string."
|
|
32
73
|
},
|
|
33
74
|
"caption_lines": {
|
|
34
75
|
"type": "array",
|
|
35
|
-
"items": {
|
|
76
|
+
"items": {
|
|
77
|
+
"type": "string"
|
|
78
|
+
},
|
|
36
79
|
"description": "Bottom typewriter text lines for templates that support a caption/typewriter area (e.g. spotlight-card). Each element is one line of text. Supports **emphasis** syntax (rendered with accent color). **Must** pass when the user explicitly provides bullet-point text / bottom copy for the video."
|
|
37
80
|
},
|
|
38
|
-
"stub_image_url": {
|
|
39
|
-
|
|
40
|
-
|
|
81
|
+
"stub_image_url": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"description": "Test-mode image stub URL. Only pass when the user explicitly says things like 'just testing / don't actually generate / use a placeholder image / stub URL / save credits' AND provides a concrete URL. With this set, every image AssetRef in the produced DSL is written as source=existing, status=generated, url=<this URL> — no gen-image call. Do not pass otherwise; if the user expressed the intent without a URL, ask for one — do not invent one."
|
|
84
|
+
},
|
|
85
|
+
"stub_video_url": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"description": "Test-mode video stub URL. Only pass when the user explicitly says things like 'just testing / don't actually generate the video / placeholder clip / save credits' AND provides a concrete URL. With this set, every video AssetRef in the produced DSL is written as source=existing, status=generated, url=<this URL> — no gen-video call. Do not pass otherwise; if the user expressed the intent without a URL, ask for one — do not invent one."
|
|
88
|
+
},
|
|
89
|
+
"skip_asset_generation": {
|
|
90
|
+
"type": "boolean",
|
|
91
|
+
"description": "All-in-one switch for downstream agents (e.g. template-creator) that only want the DSL shape: every produced AssetRef is marked as already generated with placeholder URLs (image: https://placeholder.local/stub.png, video: stub.mp4, audio: stub.mp3). Implies the equivalent of --stub-image-url + --stub-video-url with sentinel defaults plus the same rewrite for gen-voice / gen-digital-human assets. Useful when the agent only needs to inspect DSL structure or feed it into try_render_local with all assets pre-stubbed."
|
|
92
|
+
}
|
|
41
93
|
},
|
|
42
|
-
"required": [
|
|
94
|
+
"required": [
|
|
95
|
+
"topic"
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
"ui": {
|
|
99
|
+
"primary": [
|
|
100
|
+
"topic",
|
|
101
|
+
"platform",
|
|
102
|
+
"duration"
|
|
103
|
+
],
|
|
104
|
+
"advanced": [
|
|
105
|
+
"style",
|
|
106
|
+
"ratio",
|
|
107
|
+
"scenes",
|
|
108
|
+
"voice_id",
|
|
109
|
+
"template_id",
|
|
110
|
+
"headline",
|
|
111
|
+
"subheadline",
|
|
112
|
+
"carousel_items",
|
|
113
|
+
"caption_lines"
|
|
114
|
+
],
|
|
115
|
+
"hidden": [
|
|
116
|
+
"stub_image_url",
|
|
117
|
+
"stub_video_url",
|
|
118
|
+
"skip_asset_generation"
|
|
119
|
+
]
|
|
43
120
|
}
|
|
44
121
|
}
|
|
@@ -87,5 +87,27 @@
|
|
|
87
87
|
"required": [
|
|
88
88
|
"prompt"
|
|
89
89
|
]
|
|
90
|
+
},
|
|
91
|
+
"ui": {
|
|
92
|
+
"primary": [
|
|
93
|
+
"prompt",
|
|
94
|
+
"model",
|
|
95
|
+
"duration",
|
|
96
|
+
"ratio"
|
|
97
|
+
],
|
|
98
|
+
"advanced": [
|
|
99
|
+
"resolution",
|
|
100
|
+
"first_frame",
|
|
101
|
+
"last_frame",
|
|
102
|
+
"reference",
|
|
103
|
+
"generate_audio",
|
|
104
|
+
"camera_fixed",
|
|
105
|
+
"negative_prompt"
|
|
106
|
+
],
|
|
107
|
+
"hidden": [
|
|
108
|
+
"json_output",
|
|
109
|
+
"seed",
|
|
110
|
+
"person_generation"
|
|
111
|
+
]
|
|
90
112
|
}
|
|
91
113
|
}
|
|
@@ -114,7 +114,17 @@ python3 <SkillDir>/scripts/render_video.py --render-plan <path>.render-plan.json
|
|
|
114
114
|
python3 <SkillDir>/scripts/render_video.py --job-id 42 --upload-title "My video"
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
After rendering, the script auto-uploads by default; `render-manifest.json` then contains an
|
|
117
|
+
After rendering, the script auto-uploads by default; `render-manifest.json` then contains an
|
|
118
|
+
`upload.fileUrl` field, and `upload.playbackUrl` (transcoded) once VOD processing finishes.
|
|
119
|
+
|
|
120
|
+
**Do not retype the video URL into your reply.** On success the script prints a structured
|
|
121
|
+
`__render_video_asset__` line; the host reads the authoritative URL from there and renders a
|
|
122
|
+
player for the user. Tell the user the video is ready — the player appears on its own.
|
|
123
|
+
|
|
124
|
+
Reproducing a 32-char opaque URL from memory is unreliable: on 2026-08-30 a single character
|
|
125
|
+
was dropped (`…c1c20102` → `…c1c2012`), so the user got a 404 while the file sat fine on the
|
|
126
|
+
CDN. The URL in your prose is redundant with the structured asset and is the only copy that
|
|
127
|
+
can be wrong — the UI now renders it as plain, non-clickable text for exactly this reason.
|
|
118
128
|
|
|
119
129
|
### Render but skip the upload
|
|
120
130
|
|
|
@@ -2413,6 +2413,26 @@ Examples:
|
|
|
2413
2413
|
effective_playback = playback_url or remote_url
|
|
2414
2414
|
if effective_playback and not effective_playback.startswith("vod://"):
|
|
2415
2415
|
print(f"\n🎬 Video playback URL: {effective_playback}")
|
|
2416
|
+
|
|
2417
|
+
# 结构化资产标记 —— 宿主(ab-agent)据此把权威 URL 作为 attachment
|
|
2418
|
+
# 下发前端渲染播放器,绕开模型正文。
|
|
2419
|
+
#
|
|
2420
|
+
# 为什么必须绕开:模型复述 32 位不透明 hex 会出错。2026-08-30 实测一次
|
|
2421
|
+
# 成片链接被吞掉一个字符(…c1c20102 → …c1c2012),用户拿到 404,
|
|
2422
|
+
# 而文件本身好好地在 CDN 上。约定与 web-screenshot/scripts/record.py
|
|
2423
|
+
# 的 __web_record_asset__ 一致。
|
|
2424
|
+
#
|
|
2425
|
+
# 只在拿到**非 vod:// 的真实播放地址**时才打标记(上面的 if 已保证):
|
|
2426
|
+
# playbackUrl 来自 VOD 轮询,可能超时未就绪。宁可前端没有内联播放器
|
|
2427
|
+
# (用户仍可从成片面板看),也不要再给出一条不可用的地址。
|
|
2428
|
+
asset = {"url": effective_playback}
|
|
2429
|
+
cover = upload_info.get("coverUrl")
|
|
2430
|
+
if cover:
|
|
2431
|
+
asset["coverUrl"] = cover
|
|
2432
|
+
total_duration = (render_plan.get("renderConfig") or {}).get("totalDuration")
|
|
2433
|
+
if isinstance(total_duration, (int, float)) and total_duration > 0:
|
|
2434
|
+
asset["durationSec"] = total_duration
|
|
2435
|
+
print("__render_video_asset__ " + json.dumps(asset, ensure_ascii=False))
|
|
2416
2436
|
else:
|
|
2417
2437
|
LogPrint(f" Video: {output_path}", file=sys.stderr)
|
|
2418
2438
|
if args.save_job:
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"description": "Loads a persisted RenderPlan by job_id and drives the Remotion engine to produce the final video. Assets must already be generated via prepare_video_assets — this skill never resolves or regenerates assets.",
|
|
8
8
|
"auth": "required",
|
|
9
9
|
"createsTake": true,
|
|
10
|
+
"createsTakeUnless": ["resolve_only"],
|
|
10
11
|
"envVars": [
|
|
11
12
|
"PRIV_TOKEN",
|
|
12
13
|
"MM_API_BASE_URL",
|
|
@@ -147,5 +147,43 @@
|
|
|
147
147
|
"required": [
|
|
148
148
|
"url"
|
|
149
149
|
]
|
|
150
|
+
},
|
|
151
|
+
"ui": {
|
|
152
|
+
"primary": [
|
|
153
|
+
"url",
|
|
154
|
+
"duration",
|
|
155
|
+
"scroll_through"
|
|
156
|
+
],
|
|
157
|
+
"advanced": [
|
|
158
|
+
"device",
|
|
159
|
+
"viewport",
|
|
160
|
+
"max_duration",
|
|
161
|
+
"stop_when_selector",
|
|
162
|
+
"stop_when_hidden",
|
|
163
|
+
"scroll_step",
|
|
164
|
+
"scroll_interval",
|
|
165
|
+
"scroll_pause_top",
|
|
166
|
+
"scroll_pause_bottom",
|
|
167
|
+
"color_scheme",
|
|
168
|
+
"wait_for_selector",
|
|
169
|
+
"wait_for_timeout",
|
|
170
|
+
"vod_title",
|
|
171
|
+
"cover_at_sec",
|
|
172
|
+
"browser"
|
|
173
|
+
],
|
|
174
|
+
"hidden": [
|
|
175
|
+
"output",
|
|
176
|
+
"storyboard",
|
|
177
|
+
"template",
|
|
178
|
+
"param",
|
|
179
|
+
"list_templates",
|
|
180
|
+
"user_agent",
|
|
181
|
+
"timeout",
|
|
182
|
+
"ignore_https_errors",
|
|
183
|
+
"storage_state",
|
|
184
|
+
"cookies",
|
|
185
|
+
"no_upload",
|
|
186
|
+
"keep_webm"
|
|
187
|
+
]
|
|
150
188
|
}
|
|
151
189
|
}
|
|
@@ -76,5 +76,26 @@
|
|
|
76
76
|
"required": [
|
|
77
77
|
"url"
|
|
78
78
|
]
|
|
79
|
+
},
|
|
80
|
+
"ui": {
|
|
81
|
+
"primary": [
|
|
82
|
+
"url",
|
|
83
|
+
"full_page"
|
|
84
|
+
],
|
|
85
|
+
"advanced": [
|
|
86
|
+
"selector",
|
|
87
|
+
"device",
|
|
88
|
+
"viewport",
|
|
89
|
+
"wait_for_selector",
|
|
90
|
+
"wait_for_timeout",
|
|
91
|
+
"browser",
|
|
92
|
+
"clip",
|
|
93
|
+
"annotate",
|
|
94
|
+
"output"
|
|
95
|
+
],
|
|
96
|
+
"hidden": [
|
|
97
|
+
"storage_state",
|
|
98
|
+
"cookies"
|
|
99
|
+
]
|
|
79
100
|
}
|
|
80
101
|
}
|