@remixmate/cli 0.13.0 → 0.13.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.
package/dist/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.13.
|
|
4
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"version": "0.13.2",
|
|
4
|
+
"generatedAt": "2026-10-25T07:41:14.830Z",
|
|
5
5
|
"skills": [
|
|
6
6
|
{
|
|
7
7
|
"id": "doc-parse",
|
|
@@ -602,6 +602,15 @@
|
|
|
602
602
|
"type": "string",
|
|
603
603
|
"description": "Media fill mode for templates declaring capabilities.mediaBinding.options.fit; one of that option's enum in the template's customPayloadSchema (its descriptions explain each value). Beats the preset's own fit. **Must** pass when the user picked it: `显示方式: <名称>(<id>)` → pass `<id>`; `auto` keeps the template / preset default."
|
|
604
604
|
},
|
|
605
|
+
"narration": {
|
|
606
|
+
"type": "string",
|
|
607
|
+
"enum": [
|
|
608
|
+
"auto",
|
|
609
|
+
"on",
|
|
610
|
+
"off"
|
|
611
|
+
],
|
|
612
|
+
"description": "Narration on / off, overriding the template's needsNarration (auto = the template decides). Templates where narration is optional (image sequences, galton-board) default to none — **must** pass `on` when the replicate card says `旁白: <名称>(narrated)`, otherwise the narration you write is dropped without an error and the video comes back silent. `off` drops narration from a narrated template."
|
|
613
|
+
},
|
|
605
614
|
"background_asset": {
|
|
606
615
|
"type": "string",
|
|
607
616
|
"description": "URL of the user's background image or video (the replicate card's 背景素材 / 背景图片 asset line → its URL). Added as an existing asset and referenced from every scene's customPayload.background (assetRef for an image, videoAssetRef for a video; .mp4/.mov/.webm/.m4v count as video); the background preset becomes image / video, so background_preset can be omitted. **Must** pass when the user gave a background file — without it a preset of image / video renders the template's plain default. Requires template_id; rejected when the template has no background of that kind."
|
|
@@ -616,6 +625,7 @@
|
|
|
616
625
|
"motion": {
|
|
617
626
|
"type": "string",
|
|
618
627
|
"enum": [
|
|
628
|
+
"auto",
|
|
619
629
|
"static",
|
|
620
630
|
"kenburns-in",
|
|
621
631
|
"kenburns-out",
|
|
@@ -623,7 +633,7 @@
|
|
|
623
633
|
"pan-right",
|
|
624
634
|
"float"
|
|
625
635
|
],
|
|
626
|
-
"description": "Camera motion for every scene (scenes[].animationHints.motion), replacing the skeleton's alternating push-in / pull-out. **Must** pass when the user picked one: `运镜效果: 缓慢推近(kenburns-in)` → `kenburns-in
|
|
636
|
+
"description": "Camera motion for every scene (scenes[].animationHints.motion), replacing the skeleton's alternating push-in / pull-out. **Must** pass when the user picked one: `运镜效果: 缓慢推近(kenburns-in)` → `kenburns-in`; `运镜效果: 自动搭配(auto)` → `auto` (the template varies the motion scene by scene; do not write animationHints.motion yourself then)."
|
|
627
637
|
},
|
|
628
638
|
"ending_payload": {
|
|
629
639
|
"type": "array",
|
|
@@ -737,6 +747,7 @@
|
|
|
737
747
|
"background_preset",
|
|
738
748
|
"sequence_preset",
|
|
739
749
|
"sequence_fit",
|
|
750
|
+
"narration",
|
|
740
751
|
"background_asset",
|
|
741
752
|
"payload",
|
|
742
753
|
"ending_payload",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remixmate/cli",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "AI media generation skills for Claude Code / Codex — 12 skills covering image, video, voice, digital human, web screenshot, web recording, script, template registry, rendering, Jianying export, and video deconstruction.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -484,11 +484,12 @@ python3 <SkillDir>/scripts/gen_script.py \
|
|
|
484
484
|
| `--background-preset` | Scene background preset, one of the template's `customPayloadSchema.background.preset` values. Written to every scene's `customPayload.background.preset` (other keys of the template's default background are kept). Pass it whenever the user picked a background, e.g. `背景样式: <名称>(<id>)` → `<id>`. `image` / `video` need the user's file: pass `--background-asset` (which sets the preset itself). Requires `--template-id`; unsupported values are rejected. | template default |
|
|
485
485
|
| `--sequence-preset` | Style preset for templates declaring `capabilities.mediaBinding.options.preset`; one of that option's enum in the template's `customPayloadSchema` (`none` keeps the template defaults). Written next to the media list; the preset sets transitions, motion, text layout and pacing, and the scene duration follows. **Must** pass when the user picked a style preset on the replicate card (pass the id in parentheses, e.g. `风格预设: <名称>(<id>)` → `<id>`); otherwise the choice is silently dropped. Rejected on templates without that option. |
|
|
486
486
|
| `--sequence-fit` | Fill mode for templates declaring `capabilities.mediaBinding.options.fit`; one of that option's enum (`auto` keeps the template / preset default). Beats the preset's own fit. **Must** pass when the user picked it on the replicate card (`显示方式: <名称>(<id>)` → `<id>`). |
|
|
487
|
+
| `--narration` | `auto` (the template's `capabilities.needsNarration` decides), `on` or `off`. Templates where narration is optional default to none; **must** pass `on` when the user picked narration on the replicate card (`旁白: <名称>(narrated)`), otherwise the narration written later is dropped without an error. `on` adds the narration slot, a `gen-voice` asset and subtitles; on `fit-images` templates that declare `customPayload.minDurationSec` it also writes the media's natural length there, so a short narration does not compress the media (a longer one stretches the scene). |
|
|
487
488
|
| `--background-asset` | URL of the user's background image or video (`.mp4/.mov/.webm/.m4v` → video). Added as existing asset `asset-background`; every scene's `customPayload.background` gets `preset: image` + `assetRef`, or `preset: video` + `videoAssetRef`. Conflicts with a different `--background-preset`; rejected when the template's background enum lacks that kind. | none |
|
|
488
489
|
| `--payload KEY=VALUE` | Template-specific card choice, repeatable. `KEY` is a dotted path in `customPayloadSchema` (or `capabilities.frameLevelKeys`), e.g. `<field>=<value>`, `<object>.<field>=<value>`. Value is converted to the declared type (true/false, numbers) and checked against enum / range; undeclared keys are rejected. Written to every scene with sibling keys kept, applied before fit-caption duration estimation. | template default |
|
|
489
490
|
| `--ending-payload KEY=VALUE` | Same as `--payload`, but written only to the ending scene, e.g. `<object>.<field>=<closing line>`. On countdown templates it also appends an ending scene after #1 (it carries the #1 index; fill its narration and the item field `capabilities.countdown.itemProp` names). Errors when the script has no ending scene. | none |
|
|
490
491
|
| `--avatar-id` | Digital-human avatar id (`dh_xxx`) for templates declaring `capabilities.digitalHuman`. Adds asset `asset-avatar` (`type: avatar`, `source: gen-digital-human`, `payload.avatarId`) and sets `visuals.avatar.assetRef` on every scene whose slot reads it — one continuous presenter driven by the narration. Placement: template default, or `--payload digitalHuman.<field>=…` (a photo-only presenter is `--payload digitalHuman.posterUrl=<url>` without this flag). | none |
|
|
491
|
-
| `--motion` | Camera motion for every scene (`animationHints.motion`): `static` / `kenburns-in` / `kenburns-out` / `pan-left` / `pan-right` / `float`. | skeleton alternates in / out |
|
|
492
|
+
| `--motion` | Camera motion for every scene (`animationHints.motion`): `static` / `kenburns-in` / `kenburns-out` / `pan-left` / `pan-right` / `float`. `auto` removes the motion from every scene so the template picks (image-slide rotates push / pan / pull / pan); nothing is locked then. | skeleton alternates in / out |
|
|
492
493
|
| `--font-id` | Font library key (`font.uniq_id`), written to `global.font.fontId`; ab-render resolves and installs the real font at render time. Pass it whenever the user picked a font — the replicate card shows it as `名字(id)`, e.g. `字体: <名字>(<uniqId>)`; pass the id in the parentheses. Never pass a CSS family or the display name: an unknown key falls back to the template font with no error. | template font |
|
|
493
494
|
| `--font-name` | Display name of the picked font → `global.font.fontName` (display only, never used for rendering). Pass it with `--font-id`. | — |
|
|
494
495
|
| `--list-fonts` | Print the live font library (`/font/page`: id, name, lang, category, license) and exit; no script is generated and `--topic` is not needed. The ids it prints are the only valid `--font-id` values — use it when the user asks which fonts exist or names a font without its id. | — |
|
|
@@ -582,6 +582,10 @@ def _template_primary_visual_type(template_config: dict | None) -> str:
|
|
|
582
582
|
return "none"
|
|
583
583
|
|
|
584
584
|
|
|
585
|
+
|
|
586
|
+
NARRATION_MODES = ("auto", "on", "off")
|
|
587
|
+
|
|
588
|
+
|
|
585
589
|
def _template_needs_narration(template_config: dict | None) -> bool:
|
|
586
590
|
|
|
587
591
|
|
|
@@ -1382,10 +1386,6 @@ def _build_carousel_caption_dsl(
|
|
|
1382
1386
|
_write_payload(custom_payload, payload_writes or [])
|
|
1383
1387
|
|
|
1384
1388
|
|
|
1385
|
-
narration_text = _localize_label(output_language, "narration_opening",
|
|
1386
|
-
label="", topic=_clip(topic, _PLACEHOLDER_TOPIC_CHARS), duration=duration)
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
1389
|
|
|
1390
1390
|
|
|
1391
1391
|
|
|
@@ -1403,6 +1403,33 @@ def _build_carousel_caption_dsl(
|
|
|
1403
1403
|
)
|
|
1404
1404
|
|
|
1405
1405
|
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
narration_text = _localize_label(
|
|
1409
|
+
output_language, "narration_opening", label="", topic=_clip(topic, _PLACEHOLDER_TOPIC_CHARS),
|
|
1410
|
+
duration=effective_duration,
|
|
1411
|
+
budget=_budget_suffix(effective_duration, output_language, narration_speed, None),
|
|
1412
|
+
)
|
|
1413
|
+
narration_locks: list[str] = []
|
|
1414
|
+
if narration_enabled and duration_strategy == "fit-images" and _schema_at(template_config, ["minDurationSec"]):
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
custom_payload["minDurationSec"] = effective_duration
|
|
1419
|
+
narration_locks.append("customPayload.minDurationSec")
|
|
1420
|
+
|
|
1421
|
+
|
|
1422
|
+
|
|
1423
|
+
|
|
1424
|
+
pacing_path = container_parts + ["pacing"]
|
|
1425
|
+
pacing_schema = _schema_at(template_config, pacing_path)
|
|
1426
|
+
explicit_pacing = any(parts == pacing_path for parts, _ in (payload_writes or []))
|
|
1427
|
+
if (container_parts and not video_seconds and "fit-scene" in (pacing_schema.get("enum") or [])
|
|
1428
|
+
and not explicit_pacing):
|
|
1429
|
+
container["pacing"] = "fit-scene"
|
|
1430
|
+
narration_locks.append("customPayload." + ".".join(container_parts + ["pacing"]))
|
|
1431
|
+
|
|
1432
|
+
|
|
1406
1433
|
text_layers = [
|
|
1407
1434
|
{"role": "headline", "content": headline, "animation": "slide-up"},
|
|
1408
1435
|
]
|
|
@@ -1459,6 +1486,8 @@ def _build_carousel_caption_dsl(
|
|
|
1459
1486
|
"scenes": [scene],
|
|
1460
1487
|
"transitions": {"default": "fade", "duration": 0.5},
|
|
1461
1488
|
}
|
|
1489
|
+
for path in narration_locks:
|
|
1490
|
+
_lock_scene_path(dsl, path)
|
|
1462
1491
|
|
|
1463
1492
|
return dsl
|
|
1464
1493
|
|
|
@@ -1844,18 +1873,23 @@ def _apply_scene_payload(
|
|
|
1844
1873
|
|
|
1845
1874
|
writes = _parse_payload_specs(template_config, payload_specs)
|
|
1846
1875
|
if motion:
|
|
1847
|
-
allowed = ("static", "kenburns-in", "kenburns-out", "pan-left", "pan-right", "float")
|
|
1876
|
+
allowed = ("auto", "static", "kenburns-in", "kenburns-out", "pan-left", "pan-right", "float")
|
|
1848
1877
|
if motion not in allowed:
|
|
1849
1878
|
raise ValueError(f"--motion {motion!r}: choose one of: {', '.join(allowed)}")
|
|
1850
1879
|
|
|
1851
1880
|
for scene in dsl.get("scenes", []):
|
|
1852
1881
|
_write_payload(scene.setdefault("customPayload", {}), writes)
|
|
1853
|
-
if
|
|
1854
|
-
|
|
1855
|
-
|
|
1882
|
+
hints = scene.get("animationHints") if isinstance(scene.get("animationHints"), dict) else None
|
|
1883
|
+
if motion == "auto":
|
|
1884
|
+
|
|
1885
|
+
|
|
1886
|
+
if hints is not None:
|
|
1887
|
+
hints.pop("motion", None)
|
|
1888
|
+
elif motion:
|
|
1889
|
+
scene["animationHints"] = {**(hints or {}), "motion": motion}
|
|
1856
1890
|
for parts, _ in writes:
|
|
1857
1891
|
_lock_scene_path(dsl, "customPayload." + ".".join(parts))
|
|
1858
|
-
if motion:
|
|
1892
|
+
if motion and motion != "auto":
|
|
1859
1893
|
_lock_scene_path(dsl, "animationHints.motion")
|
|
1860
1894
|
|
|
1861
1895
|
|
|
@@ -2430,6 +2464,7 @@ def build_dsl(
|
|
|
2430
2464
|
sequence_fit: str | None = None,
|
|
2431
2465
|
payload_writes: PayloadWrites | None = None,
|
|
2432
2466
|
countdown_ending: bool = False,
|
|
2467
|
+
narration: str = "auto",
|
|
2433
2468
|
) -> dict:
|
|
2434
2469
|
|
|
2435
2470
|
|
|
@@ -2461,6 +2496,12 @@ def build_dsl(
|
|
|
2461
2496
|
|
|
2462
2497
|
template_config = _load_template_config(template_id) if template_id else None
|
|
2463
2498
|
contract = _resolve_contract(template_config)
|
|
2499
|
+
|
|
2500
|
+
|
|
2501
|
+
if narration not in NARRATION_MODES:
|
|
2502
|
+
raise ValueError(f"--narration must be one of {', '.join(NARRATION_MODES)}, got {narration!r}")
|
|
2503
|
+
if narration != "auto":
|
|
2504
|
+
contract["needs_narration"] = narration == "on"
|
|
2464
2505
|
countdown = contract["countdown"]
|
|
2465
2506
|
if countdown is None and item_count is not None:
|
|
2466
2507
|
raise ValueError(
|
|
@@ -2751,6 +2792,13 @@ Examples:
|
|
|
2751
2792
|
"the template defaults. When the user picked a style preset in the replicate card "
|
|
2752
2793
|
"(`<名称>(<id>)`), pass that id.",
|
|
2753
2794
|
)
|
|
2795
|
+
parser.add_argument(
|
|
2796
|
+
"--narration", default="auto", choices=NARRATION_MODES,
|
|
2797
|
+
help="Narration on / off, overriding the template's capabilities.needsNarration (auto = the template "
|
|
2798
|
+
"decides). Templates where narration is optional default to none; pass `on` when the user picked "
|
|
2799
|
+
"narration in the replicate card (`旁白: <名称>(narrated)`), so the skeleton gets narration slots, "
|
|
2800
|
+
"a gen-voice asset and subtitles. `off` drops narration from a narrated template.",
|
|
2801
|
+
)
|
|
2754
2802
|
parser.add_argument(
|
|
2755
2803
|
"--sequence-fit", default=None,
|
|
2756
2804
|
help="Media fill mode for templates declaring capabilities.mediaBinding.options.fit (one of that "
|
|
@@ -2774,7 +2822,8 @@ Examples:
|
|
|
2774
2822
|
parser.add_argument(
|
|
2775
2823
|
"--motion", default=None,
|
|
2776
2824
|
help="Camera motion for every scene (animationHints.motion): static / kenburns-in / kenburns-out / "
|
|
2777
|
-
"pan-left / pan-right / float. Replaces the skeleton's alternating default."
|
|
2825
|
+
"pan-left / pan-right / float. Replaces the skeleton's alternating default. `auto` removes the "
|
|
2826
|
+
"motion from every scene so the template picks (image-slide rotates push / pan / pull / pan).",
|
|
2778
2827
|
)
|
|
2779
2828
|
parser.add_argument("--allow-digital-human", action="store_true", help="Allow digital-human assets")
|
|
2780
2829
|
parser.add_argument("--avatar-id", default=None, help="Digital-human avatar id (dh_xxx) for templates declaring capabilities.digitalHuman: adds one gen-digital-human asset referenced by every scene's visuals.avatar.assetRef (one continuous presenter driven by the narration). Placement stays the template default unless set with --payload digitalHuman.<field>=...")
|
|
@@ -3084,6 +3133,7 @@ def main():
|
|
|
3084
3133
|
sequence_fit=args.sequence_fit,
|
|
3085
3134
|
payload_writes=payload_writes,
|
|
3086
3135
|
countdown_ending=bool(args.ending_payload),
|
|
3136
|
+
narration=args.narration,
|
|
3087
3137
|
)
|
|
3088
3138
|
except ValueError as exc:
|
|
3089
3139
|
|
|
@@ -64,6 +64,11 @@
|
|
|
64
64
|
"type": "string",
|
|
65
65
|
"description": "Media fill mode for templates declaring capabilities.mediaBinding.options.fit; one of that option's enum in the template's customPayloadSchema (its descriptions explain each value). Beats the preset's own fit. **Must** pass when the user picked it: `显示方式: <名称>(<id>)` → pass `<id>`; `auto` keeps the template / preset default."
|
|
66
66
|
},
|
|
67
|
+
"narration": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"enum": ["auto", "on", "off"],
|
|
70
|
+
"description": "Narration on / off, overriding the template's needsNarration (auto = the template decides). Templates where narration is optional (image sequences, galton-board) default to none — **must** pass `on` when the replicate card says `旁白: <名称>(narrated)`, otherwise the narration you write is dropped without an error and the video comes back silent. `off` drops narration from a narrated template."
|
|
71
|
+
},
|
|
67
72
|
"background_asset": {
|
|
68
73
|
"type": "string",
|
|
69
74
|
"description": "URL of the user's background image or video (the replicate card's 背景素材 / 背景图片 asset line → its URL). Added as an existing asset and referenced from every scene's customPayload.background (assetRef for an image, videoAssetRef for a video; .mp4/.mov/.webm/.m4v count as video); the background preset becomes image / video, so background_preset can be omitted. **Must** pass when the user gave a background file — without it a preset of image / video renders the template's plain default. Requires template_id; rejected when the template has no background of that kind."
|
|
@@ -78,6 +83,7 @@
|
|
|
78
83
|
"motion": {
|
|
79
84
|
"type": "string",
|
|
80
85
|
"enum": [
|
|
86
|
+
"auto",
|
|
81
87
|
"static",
|
|
82
88
|
"kenburns-in",
|
|
83
89
|
"kenburns-out",
|
|
@@ -85,7 +91,7 @@
|
|
|
85
91
|
"pan-right",
|
|
86
92
|
"float"
|
|
87
93
|
],
|
|
88
|
-
"description": "Camera motion for every scene (scenes[].animationHints.motion), replacing the skeleton's alternating push-in / pull-out. **Must** pass when the user picked one: `运镜效果: 缓慢推近(kenburns-in)` → `kenburns-in
|
|
94
|
+
"description": "Camera motion for every scene (scenes[].animationHints.motion), replacing the skeleton's alternating push-in / pull-out. **Must** pass when the user picked one: `运镜效果: 缓慢推近(kenburns-in)` → `kenburns-in`; `运镜效果: 自动搭配(auto)` → `auto` (the template varies the motion scene by scene; do not write animationHints.motion yourself then)."
|
|
89
95
|
},
|
|
90
96
|
"ending_payload": {
|
|
91
97
|
"type": "array",
|
|
@@ -199,6 +205,7 @@
|
|
|
199
205
|
"background_preset",
|
|
200
206
|
"sequence_preset",
|
|
201
207
|
"sequence_fit",
|
|
208
|
+
"narration",
|
|
202
209
|
"background_asset",
|
|
203
210
|
"payload",
|
|
204
211
|
"ending_payload",
|