@remixmate/cli 0.9.53 → 0.9.54

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.9.53",
4
- "generatedAt": "2026-09-28T02:19:31.947Z",
3
+ "version": "0.9.54",
4
+ "generatedAt": "2026-09-28T11:58:29.708Z",
5
5
  "skills": [
6
6
  {
7
7
  "id": "doc-parse",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remixmate/cli",
3
- "version": "0.9.53",
3
+ "version": "0.9.54",
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",
@@ -2,6 +2,6 @@
2
2
  "skillName": "prepare-video-assets",
3
3
  "repoName": "agent-skill-media-maker",
4
4
  "skillId": "476",
5
- "version": "V4",
5
+ "version": "V5",
6
6
  "skillDescription": "Asset-preparation skill: resolves and generates every asset (image / audio / video) referenced by a Video DSL, persists a RenderPlan to the database, and returns a `job_id` for the subsequent `render_video` call.\n\nUse this skill as soon as the user mentions any of these intents:\n- Generate / prepare video assets, resolve assets, render-ready\n- \"Make me a video about X\" (the agent calls gen_script → prepare_video_assets → render_video)\n- Regenerate one asset (image / audio) for a specific scene\n\nNext step: after the user confirms the resolved assets, call `render_video` with the `job_id` returned by this skill.\n\n⚠️ Stop-and-confirm gate: this skill runs only after the user has confirmed the script, and after it returns you must show the resolved assets and wait for the user's explicit confirmation. Never call `render_video` in the same turn."
7
7
  }
@@ -196,6 +196,23 @@ def _narration_language_boost(narration: dict) -> Optional[str]:
196
196
  return raw.strip()
197
197
 
198
198
 
199
+ def _narration_voice(narration: dict) -> Optional[str]:
200
+ """Read a narration block's voice id, or None when unset.
201
+
202
+ Same tolerance as _narration_speed. Exists because the voice used to be read
203
+ only from the audio asset's payload.voiceId — which gen_script bakes once
204
+ when it drafts the skeleton — so changing global.narration.voiceId (or a
205
+ scene's voice) after that never reached TTS: the video kept the original
206
+ voice while every other layer reported the new one (2026-09-28).
207
+ """
208
+ if not isinstance(narration, dict):
209
+ return None
210
+ raw = narration.get("voiceId")
211
+ if not isinstance(raw, str) or not raw.strip():
212
+ return None
213
+ return raw.strip()
214
+
215
+
199
216
  def extract_narration_lines(narration: dict) -> Optional[tuple[list[str], int, list[Optional[float]]]]:
200
217
  """If narration uses the structured {intro, items, outro} form, return
201
218
  (lines, intro_line_count, at_sec_list). `at_sec_list` is parallel to
@@ -783,6 +800,7 @@ def build_render_plan(dsl: dict, binding: dict) -> dict:
783
800
  global_narration = (dsl.get("global") or {}).get("narration") or {}
784
801
  global_speed = _narration_speed(global_narration)
785
802
  global_language_boost = _narration_language_boost(global_narration)
803
+ global_voice = _narration_voice(global_narration)
786
804
  for scene in dsl.get("scenes", []):
787
805
  narration = (scene.get("audio") or {}).get("narration") or {}
788
806
  ref = narration.get("assetRef")
@@ -790,6 +808,14 @@ def build_render_plan(dsl: dict, binding: dict) -> dict:
790
808
  if not asset:
791
809
  continue
792
810
  payload = asset.setdefault("payload", {})
811
+ # Voice follows the same precedence as speed: scene narration.voiceId >
812
+ # global.narration.voiceId. The asset's own payload.voiceId (written once
813
+ # by gen_script) is only the last resort for DSLs that declare neither —
814
+ # letting it win meant a voice change made after the script was drafted
815
+ # never reached TTS.
816
+ voice = _narration_voice(narration) or global_voice
817
+ if voice:
818
+ payload["voiceId"] = voice
793
819
  # Speech rate follows the same route as the narration text: single source
794
820
  # of truth on the DSL, copied down here because resolve_asset_audio only
795
821
  # ever sees the asset. Scene-level overrides global (mirrors the narration
@@ -2,6 +2,6 @@
2
2
  "skillName": "render-video",
3
3
  "repoName": "agent-skill-media-maker",
4
4
  "skillId": "473",
5
- "version": "V31",
5
+ "version": "V32",
6
6
  "skillDescription": "Final-render skill: loads a persisted RenderPlan by `job_id` and drives the Remotion engine to produce the final video.\n\nUse this skill as soon as the user mentions any of these intents (after assets are already prepared):\n- Render the video, composite the video, export the video\n- Turn the prepared assets into the final clip\n- Render with Remotion\n\nPrerequisite: assets must already be generated via `prepare_video_assets`. This skill never resolves or regenerates assets — pass it a `job_id` from a previous `prepare_video_assets` call.\n\n⚠️ Stop-and-confirm gate: never call this skill until the user has explicitly confirmed the assets prepared by `prepare_video_assets`. If those assets were prepared in the current turn and the user has not replied since, stop and ask instead of rendering."
7
7
  }
@@ -169,6 +169,7 @@ Rules:
169
169
  - If the author explicitly provides a `highlightMap`, the system keeps it as-is.
170
170
  - The legacy flat `narration.text` form still works but the author then has to keep `highlightMap` in sync with the subtitle segmentation (error-prone, not recommended).
171
171
  - `narration.languageBoost` (optional, also accepted at `global.narration`) pins the TTS language hint (`auto` / `Chinese` / `English` / …). Leave it unset unless auto-detection gets it wrong — the service applies its own default, and a scene-level value overrides the global one, exactly like `speed`.
172
+ - Voice: to change the narration voice, set `global.narration.voiceId` (whole video) or `narration.voiceId` on a scene (that scene only). Precedence when synthesizing is scene > global > the audio asset's `payload.voiceId`, which is only a fallback — editing the asset payload alone is not how you change a voice.
172
173
 
173
174
  ## Image sources
174
175
 
@@ -2,6 +2,6 @@
2
2
  "skillName": "template-registry",
3
3
  "repoName": "agent-skill-media-maker",
4
4
  "skillId": "475",
5
- "version": "V24",
5
+ "version": "V25",
6
6
  "skillDescription": "Video-template registry skill. Stores every video-template definition and lists the available templates (templateId / name / aspect ratio / style tags).\n\nUse this skill as soon as the user mentions any of these intents:\n- View available templates / list every template\n\nNote: DSL→TemplateBinding is no longer a separate exposed step — once prepare_video_assets receives a template_id it builds the binding internally."
7
7
  }
@@ -247,6 +247,9 @@
247
247
  },
248
248
  "outro": { "type": "string", "description": "可选:收尾句(此期间无卡片高亮)" },
249
249
  "assetRef": { "type": "string", "description": "旁白音频 assetId" },
250
+ "voiceId": { "type": "string", "description": "该场旁白音色,覆盖 global.narration.voiceId;留空跟随全局。合成时优先级:场景 > 全局 > 音频资产 payload.voiceId(仅作兜底)。" },
251
+ "voiceName": { "type": "string", "description": "voiceId 的展示名(仅展示用,不参与合成)" },
252
+ "speed": { "type": "number", "description": "该场旁白语速,覆盖 global.narration.speed;留空跟随全局。" },
250
253
  "languageBoost": { "type": "string", "description": "TTS 语种提示(auto / Chinese / English …)。中英混排的旁白不给提示时,英文词容易被按中文音系读出来;覆盖 global.narration 的同名字段;留空则跟随全局/服务端默认。" }
251
254
  }
252
255
  },