@docyrus/animaguru 0.35.1 → 0.36.0

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/README.md CHANGED
@@ -63,6 +63,8 @@ CLI 0.34.0 adds `"thumbnail"` to `film.config.json` for a designed cover. It nam
63
63
 
64
64
  CLI 0.35.0 adds photoreal Gaussian splats: `assets generate --type model --model idol --reference SHA` turns the object in a saved image into splats with Sperid Labs' Idol on fal (`--photo` for a camera photo, `--splats` 32,768–1,048,576, `--seed`), saved as `.spz`, upright and facing +Z. New video workspaces include Spark, and the kit's `stage.splat()` draws splats in a three.js shot, sorted for each frame's camera, with `photoView()` to open on the reference image's exact view and `softShadow()` to ground them. See the `animaguru-3d-models` skill. CLI 0.35.1 fixes `photoView()` for product images Idol reads as near-orthographic (a field of view under 0.1°): it widens the view to 6° and moves the camera in, so the shot still opens on the product.
65
65
 
66
+ CLI 0.36.0 adds Mureka 9.5 music on fal, HeyGen Voice speech and Seedance video on BytePlus (`--model byteplus/seedance-2.5`, `-2.0`, `-2.0-fast` or `-2.0-mini`). `--type music --model fal/mureka-9.5-song` sings `--lyrics` with `--vocals female|male` or writes a song from the prompt in `--styles`, for `--seconds` 120–300 or a length of its own; `fal/mureka-9.5-instrumental` writes from the prompt; `fal/mureka-9.5-soundtrack --source SHA` scores a saved video, image or sprite art. `--type speech --model heygen-voice-1` or `heygen-voice-1-turbo` speaks a HeyGen public voice ID given as `--voice` (Nadine by default). `catalog` lists `musicOptions` and `heygenVoices`. See [image, video, music and speech generation](#image-video-music-and-speech-generation).
67
+
66
68
  CLI 0.16.2 also installs `animaguru-art-motion` for Codex and Claude Code: one skill with 36 English art-treatment references and nine explainer motion grammars, plus AnimaGuru generation, timing, camera and review guidance. Request it explicitly for a custom film treatment; its references are separate from the gallery presets. Source coverage and the upstream MIT notice are included in the skill.
67
69
 
68
70
  CLI 0.5.2 includes a complete local PixiJS video workspace, now with 60 visual styles:
@@ -248,6 +250,22 @@ animaguru assets generate PROJECT_ID --type sfx --name "Magic spell" \
248
250
  --prompt-influence 0.6 --dry-run
249
251
  ```
250
252
 
253
+ CLI 0.36.0 adds Mureka 9.5 music on fal and HeyGen Voice speech. A Mureka song sings `--lyrics` (with `--vocals female` or `male`, the prompt setting the style) or writes its own from the prompt in optional `--styles`; `--seconds` asks for 120–300 seconds. A soundtrack scores a saved video, image or sprite art given as `--source`, and runs as long as the video. HeyGen Voice speaks a public voice ID (Nadine is the default; `catalog --type speech` lists `heygenVoices`) and reads the transcript as written, so it takes no `--delivery`:
254
+
255
+ ```sh
256
+ animaguru assets generate PROJECT_ID --type music --model fal/mureka-9.5-song \
257
+ --name "Studio song" --prompt "Upbeat synth-pop" --vocals female \
258
+ --lyrics $'[Verse]\nTiny robots in the studio light\n[Chorus]\nAnimate, animate' --dry-run
259
+ animaguru assets generate PROJECT_ID --type music --model fal/mureka-9.5-song \
260
+ --name "Summer song" --prompt "A bright summer love song" --styles pop,r&b --dry-run
261
+ animaguru assets generate PROJECT_ID --type music --model fal/mureka-9.5-instrumental \
262
+ --name "Menu loop" --prompt "Calm lo-fi piano for a cozy game menu" --dry-run
263
+ animaguru assets generate PROJECT_ID --type music --model fal/mureka-9.5-soundtrack \
264
+ --name "Trailer score" --source VIDEO_BLOB_SHA --prompt "Tense, then hopeful" --dry-run
265
+ animaguru assets generate PROJECT_ID --type speech --model heygen-voice-1-turbo \
266
+ --name "Host" --prompt "Welcome to AnimaGuru." --dry-run
267
+ ```
268
+
251
269
  Replace `--dry-run` with `--yes` to generate within your authorized credit budget. ElevenLabs accepts a voice ID in `--voice` and defaults to George when omitted. Use audio tags in the transcript; `--delivery` is only for Gemini and is rejected for ElevenLabs. SFX has a single model, `eleven_text_to_sound_v2`; `--seconds` accepts 0.5–30 (default 5), `--loop` requests a seamless loop, and `--prompt-influence` accepts 0–1 (default 0.3). Both return MP3. `catalog` includes `sfxModels` and `elevenLabsVoices`. The server needs `AI_PROVIDER_KEY_ELEVENLABS`; provider keys never belong in CLI credentials.
252
270
 
253
271
  CLI 0.8.0 adds MiniMax H3 Max Turbo and the H3 workflows. MiniMax H3 Max and H3 Max Turbo on fal.ai (`fal/minimax-h3-max`, `fal/minimax-h3-max-turbo`) also write videos from text and extend saved videos. Choose with `--workflow`:
@@ -334,6 +352,19 @@ animaguru assets generate PROJECT_ID --type video --model heygen/heygen-video-1
334
352
 
335
353
  From an image or text, HeyGen's clips run to 30 seconds while it rewrites the prompt: `--prompt-expansion balanced` asks for its fastest rewriting and `quality` its fuller one. Every second of a clip over 15 seconds costs its long-clip rate. At 1080p and 2K, text-to-video and reference-to-video are 16:9 or 9:16; from an image, the clip keeps the image's shape. `reference-to-video` takes up to nine `--references` images, three `--reference-videos` (HeyGen reads the first 5 seconds of each) and three `--audio-references`, twelve files in all, named Image 1, Video 1, Audio 1 in the prompt. It takes no `--reference`, `--end-reference` or `--middle-reference`, and `--aspect-ratio auto` (default) follows the first image or clip. HeyGen takes images of up to 5 MB, and clips and audio of up to 16 MB. Up to 5 seconds of each reference clip, and each reference image after the second, add to the cost; audio references are free.
336
354
 
355
+ CLI 0.36.0 adds ByteDance's Seedance on BytePlus: `byteplus/seedance-2.5`, `byteplus/seedance-2.0`, `byteplus/seedance-2.0-fast` and `byteplus/seedance-2.0-mini`. Each films from an image (`--reference`, optionally ending on `--end-reference`; the clip keeps the image's shape), from text (`--workflow text-to-video`, with `--aspect-ratio`), or from saved images and audio (`--workflow reference-to-video`: up to nine `--references` and three `--audio-references`, named Image 1 and Audio 1 in the prompt; 2.0, fast and mini need an image beside audio). Clips are 4–15 whole seconds (2.5 up to 30), at 480p or 720p (2.0 also 1080p), with sound of their own and no `--soundtrack`, `--seed` or `--prompt-expansion`. Seedance takes no reference videos or extensions here, and refuses images of real people's faces. A clip is charged the tokens BytePlus counts, at most the estimate: a 5-second 720p clip is about 118 credits on 2.5, 77 on 2.0, 62 on fast and 39 on mini.
356
+
357
+ ```sh
358
+ # A sprite's wave, from its art to its art.
359
+ animaguru assets generate PROJECT_ID --type video --model byteplus/seedance-2.0-mini \
360
+ --name "Wave" --reference ART_SHA --end-reference ART_SHA \
361
+ --prompt "The robot waves its right hand, then stands still again" --seconds 5 --resolution 720p --dry-run
362
+ # A 20-second scene from text on Seedance 2.5.
363
+ animaguru assets generate PROJECT_ID --type video --model byteplus/seedance-2.5 \
364
+ --workflow text-to-video --name "Harbor" --aspect-ratio 21:9 \
365
+ --prompt "Fishing boats leave a foggy harbor at dawn, gulls calling, one slow continuous shot" --seconds 20 --dry-run
366
+ ```
367
+
337
368
  ### Vectors
338
369
 
339
370
  CLI 0.27.0 adds vectors: editable SVG files drawn by Ideogram on fal.ai (`fal/ideogram-vector`), for logos, icons, mascots and flat illustrations that stay sharp at any size and can be animated shape by shape.
package/dist/animaguru.js CHANGED
@@ -19761,7 +19761,7 @@ var require_ignore2 = __commonJS({
19761
19761
  // cli/package.json
19762
19762
  var package_default = {
19763
19763
  name: "@docyrus/animaguru",
19764
- version: "0.35.1",
19764
+ version: "0.36.0",
19765
19765
  description: "Agent-friendly AnimaGuru CLI built with CrustJS",
19766
19766
  type: "module",
19767
19767
  bin: {
@@ -45013,7 +45013,11 @@ var SPRITE_IMAGE_MODELS = [
45013
45013
  { id: "bytedance/seedream-5-pro", label: "Seedream 5 Pro", provider: "workers-ai", edit: true, maxImages: 10, relCost: 1.5 },
45014
45014
  { id: "xai/grok-imagine-image-2.0", label: "Grok Imagine Image 2.0", provider: "workers-ai", edit: true, maxImages: 5, relCost: 1 },
45015
45015
  { id: "alibaba/qwen-image-3.0-pro", label: "Qwen Image 3.0 Pro", provider: "workers-ai", edit: false, maxImages: 0, relCost: 0.5 },
45016
- { id: "krea/krea-2-medium-turbo", label: "Krea 2 Medium Turbo", provider: "workers-ai", edit: false, maxImages: 0, relCost: 0.25 }
45016
+ { id: "krea/krea-2-medium-turbo", label: "Krea 2 Medium Turbo", provider: "workers-ai", edit: false, maxImages: 0, relCost: 0.25 },
45017
+ // Seedream on AnimaGuru's own BytePlus account: $0.045 an image (Pro, up to 2.61 MP), $0.018 (Flash), $0.035 (Lite).
45018
+ { id: "byteplus/seedream-5.0-pro", label: "Seedream 5.0 Pro (BytePlus)", provider: "byteplus", providerModel: "dola-seedream-5-0-pro-260628", edit: true, spriteBackupCutout: true, maxImages: 10, relCost: 0.35 },
45019
+ { id: "byteplus/seedream-5.0-flash", label: "Seedream 5.0 Flash (BytePlus)", provider: "byteplus", providerModel: "dola-seedream-5-0-flash-260915", edit: true, spriteBackupCutout: true, maxImages: 10, relCost: 0.15 },
45020
+ { id: "byteplus/seedream-5.0-lite", label: "Seedream 5.0 Lite (BytePlus)", provider: "byteplus", providerModel: "seedream-5-0-260128", edit: true, spriteBackupCutout: true, maxImages: 14, relCost: 0.3 }
45017
45021
  ];
45018
45022
  var SPRITE_IMAGE_MODEL_IDS = SPRITE_IMAGE_MODELS.map((m) => m.id);
45019
45023
  function spriteImageModel(id2) {
@@ -45048,6 +45052,8 @@ var HEYGEN_LONG = { max: 30, creditsPerSecond: { "480p": 4.5, "768p": 7.5, "1080
45048
45052
  var H3_MAX = "minimax/h3-max";
45049
45053
  var FLUX_3_MAX = "blackforestlabs/flux-3-max";
45050
45054
  var h3Endpoints = (route) => ({ "image-to-video": `${route}/image-to-video`, "text-to-video": `${route}/text-to-video`, "extend-video": `${route}/extend-video` });
45055
+ var SEEDANCE_WORKFLOWS = ["image-to-video", "text-to-video", "reference-to-video"];
45056
+ var SEEDANCE_REFERENCES = { referencesOnly: true, mediaReferences: ["images", "audio"] };
45051
45057
  var SPRITE_VIDEO_MODELS = [
45052
45058
  {
45053
45059
  id: "pruna/p-video-2-pro",
@@ -45145,6 +45151,59 @@ var SPRITE_VIDEO_MODELS = [
45145
45151
  promptExpansion: ["balanced", "quality"],
45146
45152
  estimatedCreditsPerSecond: { "720p": { quality: 17 }, "1080p": { quality: 29 } },
45147
45153
  seconds: { min: 5, max: 20 }
45154
+ },
45155
+ // BytePlus bills a clip's tokens (width × height × frames / 1024, at 24 fps plus a frame); credits take each resolution's largest shape.
45156
+ {
45157
+ id: "byteplus/seedance-2.5",
45158
+ label: "Seedance 2.5 (BytePlus)",
45159
+ provider: "byteplus",
45160
+ providerModel: "dreamina-seedance-2-5-260628",
45161
+ workflows: SEEDANCE_WORKFLOWS,
45162
+ resolutions: ["480p", "720p"],
45163
+ workflowOptions: { "reference-to-video": { ...SEEDANCE_REFERENCES, mediaSeconds: 30 } },
45164
+ modes: ["quality"],
45165
+ lastFrame: true,
45166
+ estimatedCreditsPerSecond: { "480p": { quality: 10.86 }, "720p": { quality: 23.51 } },
45167
+ seconds: { min: 4, max: 30 }
45168
+ },
45169
+ {
45170
+ id: "byteplus/seedance-2.0",
45171
+ label: "Seedance 2.0 (BytePlus)",
45172
+ provider: "byteplus",
45173
+ providerModel: "dreamina-seedance-2-0-260128",
45174
+ workflows: SEEDANCE_WORKFLOWS,
45175
+ resolutions: ["480p", "720p", "1080p"],
45176
+ workflowOptions: { "reference-to-video": { ...SEEDANCE_REFERENCES, audioNeedsImages: true } },
45177
+ modes: ["quality"],
45178
+ lastFrame: true,
45179
+ estimatedCreditsPerSecond: { "480p": { quality: 7.11 }, "720p": { quality: 15.38 }, "1080p": { quality: 38.06 } },
45180
+ seconds: { min: 4, max: 15 }
45181
+ },
45182
+ {
45183
+ id: "byteplus/seedance-2.0-fast",
45184
+ label: "Seedance 2.0 Fast (BytePlus)",
45185
+ provider: "byteplus",
45186
+ providerModel: "dreamina-seedance-2-0-fast-260128",
45187
+ workflows: SEEDANCE_WORKFLOWS,
45188
+ resolutions: ["480p", "720p"],
45189
+ workflowOptions: { "reference-to-video": { ...SEEDANCE_REFERENCES, audioNeedsImages: true } },
45190
+ modes: ["speed"],
45191
+ lastFrame: true,
45192
+ estimatedCreditsPerSecond: { "480p": { speed: 5.69 }, "720p": { speed: 12.3 } },
45193
+ seconds: { min: 4, max: 15 }
45194
+ },
45195
+ {
45196
+ id: "byteplus/seedance-2.0-mini",
45197
+ label: "Seedance 2.0 Mini (BytePlus)",
45198
+ provider: "byteplus",
45199
+ providerModel: "dreamina-seedance-2-0-mini-260615",
45200
+ workflows: SEEDANCE_WORKFLOWS,
45201
+ resolutions: ["480p", "720p"],
45202
+ workflowOptions: { "reference-to-video": { ...SEEDANCE_REFERENCES, audioNeedsImages: true } },
45203
+ modes: ["cost"],
45204
+ lastFrame: true,
45205
+ estimatedCreditsPerSecond: { "480p": { cost: 3.56 }, "720p": { cost: 7.69 } },
45206
+ seconds: { min: 4, max: 15 }
45148
45207
  }
45149
45208
  ];
45150
45209
  var SPRITE_VIDEO_MODEL_IDS = SPRITE_VIDEO_MODELS.map((m) => m.id);
@@ -46985,18 +47044,48 @@ var modelCostUsd = (p) => generationCostUsd(p) + (p.rig ? rigCostUsd(p.animation
46985
47044
  // shared/assets.ts
46986
47045
  var ASSET_TYPES = ["image", "vector", "video", "music", "speech", "sfx", "model"];
46987
47046
  var SPEECH_MODELS = [
46988
- { id: "gemini-3.8-flash-tts", label: "Gemini 3.8 Flash TTS" },
46989
- { id: "gemini-3.8-flash-lite-tts", label: "Gemini 3.8 Flash-Lite TTS" },
46990
- { id: "eleven_v4", label: "ElevenLabs v4" },
46991
- { id: "eleven_v4_turbo", label: "ElevenLabs v4 Turbo" }
47047
+ { id: "gemini-3.8-flash-tts", label: "Gemini 3.8 Flash TTS", provider: "google" },
47048
+ { id: "gemini-3.8-flash-lite-tts", label: "Gemini 3.8 Flash-Lite TTS", provider: "google" },
47049
+ { id: "eleven_v4", label: "ElevenLabs v4", provider: "elevenlabs" },
47050
+ { id: "eleven_v4_turbo", label: "ElevenLabs v4 Turbo", provider: "elevenlabs" },
47051
+ { id: "heygen-voice-1", label: "HeyGen Voice 1", provider: "heygen" },
47052
+ { id: "heygen-voice-1-turbo", label: "HeyGen Voice 1 Turbo", provider: "heygen" }
46992
47053
  ];
46993
47054
  var ELEVENLABS_SPEECH_MODEL_IDS = ["eleven_v4", "eleven_v4_turbo"];
47055
+ var HEYGEN_SPEECH_MODEL_IDS = ["heygen-voice-1", "heygen-voice-1-turbo"];
46994
47056
  var SFX_MODELS = [{ id: "eleven_text_to_sound_v2", label: "ElevenLabs Sound Effects v2" }];
46995
47057
  var DEFAULT_ELEVENLABS_VOICE = "JBFqnCBsd6RMkjVDRZzb";
46996
47058
  var ELEVENLABS_VOICES = [{ id: DEFAULT_ELEVENLABS_VOICE, label: "George" }];
46997
47059
  var isElevenLabsSpeech = (model) => ELEVENLABS_SPEECH_MODEL_IDS.includes(model);
46998
- var MUSIC_MODELS = [{ id: "lyria-3.5", label: "Lyria 3.5" }];
47060
+ var isHeyGenSpeech = (model) => HEYGEN_SPEECH_MODEL_IDS.includes(model);
47061
+ var DEFAULT_HEYGEN_VOICE = "83548de556df48ba8c09c42a57c51d85";
47062
+ var HEYGEN_VOICES = [
47063
+ { id: DEFAULT_HEYGEN_VOICE, label: "Nadine \xB7 Calm & Gentle" },
47064
+ { id: "75300849b571414c8d62693289cb6509", label: "Sabrina \xB7 Upbeat & Lively" },
47065
+ { id: "aa9746e325ff46d482a54fe5bc87890f", label: "Meredith \xB7 Serious & Composed" },
47066
+ { id: "fe333747c7d04a7188d20a8ea2a222d9", label: "Claire \xB7 Rich & Expressive" },
47067
+ { id: "7e48c8d406b04a8089c5eb3cd057cb2e", label: "Jonah \xB7 Clear & Professional" },
47068
+ { id: "826be797681d4b1a92042b54b3c75c64", label: "Gareth \xB7 Conversational & Easygoing" },
47069
+ { id: "9b71011176ac49ee8d0936c36566d665", label: "Hugh \xB7 Firm & Measured" },
47070
+ { id: "7bb4df56d7714d33bb88ed1dde8128f6", label: "Rory \xB7 Upbeat & Lively" }
47071
+ ];
46999
47072
  var SPEECH_VOICES = ["Kore", "Puck", "Charon", "Fenrir", "Aoede", "Leda", "Orus", "Zephyr"];
47073
+ var defaultSpeechVoice = (model) => isElevenLabsSpeech(model) ? DEFAULT_ELEVENLABS_VOICE : isHeyGenSpeech(model) ? DEFAULT_HEYGEN_VOICE : "Kore";
47074
+ var speechVoiceValid = (model, voice) => isElevenLabsSpeech(model) ? /^[a-zA-Z0-9]{20}$/.test(voice) : isHeyGenSpeech(model) ? /^[A-Za-z0-9_]{8,64}$/.test(voice) : SPEECH_VOICES.includes(voice);
47075
+ var MUSIC_MODELS = [
47076
+ { id: "lyria-3.5", label: "Lyria 3.5", provider: "google" },
47077
+ { id: "fal/mureka-9.5-song", label: "Mureka 9.5 Song", provider: "fal" },
47078
+ { id: "fal/mureka-9.5-instrumental", label: "Mureka 9.5 Instrumental", provider: "fal" },
47079
+ { id: "fal/mureka-9.5-soundtrack", label: "Mureka 9.5 Soundtrack", provider: "fal" }
47080
+ ];
47081
+ var MUSIC_MODEL_IDS = ["lyria-3.5", "fal/mureka-9.5-song", "fal/mureka-9.5-instrumental", "fal/mureka-9.5-soundtrack"];
47082
+ var MUREKA_STYLES = ["pop", "rock", "jazz", "r&b", "edm", "ambient", "folk", "latin", "k-pop", "j-pop", "house", "gospel", "lo-fi"];
47083
+ var MUREKA_VOCALS = ["female", "male"];
47084
+ var MAX_SONG_LYRICS = 5e3;
47085
+ var SONG_SECONDS = { min: 120, max: 300 };
47086
+ var SONG_LENGTH = `Choose a length of ${SONG_SECONDS.min}\u2013${SONG_SECONDS.max} whole seconds.`;
47087
+ var SOUNDTRACK_IMAGE_MAX_BYTES = 50 * 1024 * 1024;
47088
+ var SOUNDTRACK_VIDEO_MAX_BYTES = 100 * 1024 * 1024;
47000
47089
  var base = { name: external_exports.string().trim().min(1).max(80), prompt: external_exports.string().trim().min(3).max(4e3) };
47001
47090
  var blob = external_exports.string().regex(/^[a-f0-9]{64}$/);
47002
47091
  var cameraKeyframe = external_exports.object({
@@ -47197,6 +47286,12 @@ function videoChecks(p, ctx) {
47197
47286
  if (options?.referencesOnly) {
47198
47287
  for (const field of ["reference", "endReference", "middleReference"]) if (p[field]) issue2(field, "This video model's reference-to-video takes references only, without a first, last or middle frame.");
47199
47288
  }
47289
+ const kinds = options?.mediaReferences;
47290
+ const files = [["images", "references", references.length], ["videos", "referenceVideos", p.referenceVideos?.length ?? 0], ["audio", "audioReferences", p.audioReferences.length]];
47291
+ if (kinds) {
47292
+ for (const [kind, field, count] of files) if (count && !kinds.includes(kind)) issue2(field, `This video model's reference-to-video takes reference ${kinds.join(" and ")}, not ${kind}.`);
47293
+ }
47294
+ if (options?.audioNeedsImages && p.audioReferences.length && !references.length && !p.referenceVideos?.length) issue2("audioReferences", "This video model needs a reference image beside reference audio.");
47200
47295
  if (references.length + (p.referenceVideos?.length ?? 0) + p.audioReferences.length > MAX_REFERENCE_FILES) issue2("references", `reference-to-video takes at most ${MAX_REFERENCE_FILES} reference files in all.`);
47201
47296
  const frames = !options?.referencesOnly && (p.reference || p.endReference);
47202
47297
  if (!references.length && !p.referenceVideos?.length && !p.audioReferences.length && !frames) issue2("references", `reference-to-video needs reference images, videos or audio${options?.referencesOnly ? "" : ", or a first or last frame"}.`);
@@ -47290,6 +47385,60 @@ function vectorChecks(p, ctx) {
47290
47385
  if (p.references.length) issue2("references", "image-to-vector traces its source alone and takes no references.");
47291
47386
  }
47292
47387
  var vectorDefaults = (p) => p.workflow === "text-to-vector" ? { ...p, quality: p.quality ?? "medium", aspectRatio: p.aspectRatio ?? "auto" } : { ...p, shapes: p.shapes ?? "detailed" };
47388
+ var musicAsset = external_exports.object({
47389
+ name: base.name,
47390
+ /** A soundtrack may leave it out, and so may a song sung from lyrics, where it sets the style. */
47391
+ prompt: external_exports.string().trim().max(4e3).default(""),
47392
+ type: external_exports.literal("music"),
47393
+ model: external_exports.enum(MUSIC_MODEL_IDS).default("lyria-3.5"),
47394
+ /** Mureka Song: the words to sing. */
47395
+ lyrics: external_exports.string().trim().min(1).max(MAX_SONG_LYRICS).optional(),
47396
+ /** Mureka Song written from the prompt: its genres. */
47397
+ styles: external_exports.array(external_exports.enum(MUREKA_STYLES)).min(1).max(MUREKA_STYLES.length).optional(),
47398
+ /** Mureka Song sung from lyrics: who sings. */
47399
+ vocals: external_exports.enum(MUREKA_VOCALS).optional(),
47400
+ /** Mureka Song: about how long, in whole seconds; the model chooses when it's left out. */
47401
+ seconds: external_exports.number().int(SONG_LENGTH).min(SONG_SECONDS.min, SONG_LENGTH).max(SONG_SECONDS.max, SONG_LENGTH).optional(),
47402
+ /** Mureka Soundtrack: the saved image or video to score. */
47403
+ source: blob.optional()
47404
+ });
47405
+ var MUSIC_ONLY = {
47406
+ lyrics: ["fal/mureka-9.5-song", "Only Mureka 9.5 Song sings lyrics."],
47407
+ styles: ["fal/mureka-9.5-song", "Only Mureka 9.5 Song takes styles; describe the genre in the prompt."],
47408
+ vocals: ["fal/mureka-9.5-song", "Only Mureka 9.5 Song takes vocals."],
47409
+ seconds: ["fal/mureka-9.5-song", "Only Mureka 9.5 Song takes a length; the other music models choose their own."],
47410
+ source: ["fal/mureka-9.5-soundtrack", "Only Mureka 9.5 Soundtrack scores a saved image or video."]
47411
+ };
47412
+ function musicChecks(p, ctx) {
47413
+ const issue2 = (path, message) => ctx.addIssue({ code: "custom", message, path: [path] });
47414
+ for (const [field, [model, message]] of Object.entries(MUSIC_ONLY)) if (p[field] !== void 0 && p.model !== model) issue2(field, message);
47415
+ const most = (max2) => {
47416
+ if (p.prompt.length > max2) issue2("prompt", `Describe the music in at most ${max2.toLocaleString("en-US")} characters.`);
47417
+ };
47418
+ if (p.model === "fal/mureka-9.5-song") {
47419
+ if (p.lyrics) {
47420
+ most(1024);
47421
+ if (p.styles) issue2("styles", "A song sung from lyrics takes its style from the prompt; leave out styles.");
47422
+ } else {
47423
+ if (p.prompt.length < 3) issue2("prompt", "Describe the song in at least 3 characters, or give lyrics to sing.");
47424
+ most(2e3);
47425
+ if (p.vocals) issue2("vocals", "Vocals choose who sings lyrics; describe the singer in the prompt instead.");
47426
+ }
47427
+ if (p.styles && new Set(p.styles).size !== p.styles.length) issue2("styles", "Choose each style once.");
47428
+ return;
47429
+ }
47430
+ if (p.model === "fal/mureka-9.5-soundtrack") {
47431
+ if (!p.source) issue2("source", "Choose a saved image or video to score.");
47432
+ return most(1024);
47433
+ }
47434
+ if (p.prompt.length < 3) issue2("prompt", "Describe the music in at least 3 characters.");
47435
+ if (p.model === "fal/mureka-9.5-instrumental") most(1024);
47436
+ }
47437
+ function musicCostUsd(p) {
47438
+ if (p.model === "lyria-3.5") return 0.08;
47439
+ if (p.model === "fal/mureka-9.5-song") return p.lyrics ? 0.15 : 0.5;
47440
+ return p.model === "fal/mureka-9.5-instrumental" ? 0.15 : 0.11;
47441
+ }
47293
47442
  var animationClip = external_exports.union([external_exports.enum(MODEL_ANIMATION_IDS), external_exports.number().int().min(0).max(MAX_MESHY_ACTION)]);
47294
47443
  var modelAsset = external_exports.object({
47295
47444
  name: base.name,
@@ -47346,11 +47495,12 @@ var modelDefaults = (p) => ({ ...p, animations: p.rig && !p.animations.length ?
47346
47495
  var assetRequest = external_exports.discriminatedUnion("type", [
47347
47496
  imageAsset.superRefine(imageChecks),
47348
47497
  videoAsset.superRefine(videoChecks).transform(videoDefaults),
47349
- external_exports.object({ ...base, type: external_exports.literal("music"), model: external_exports.literal("lyria-3.5").default("lyria-3.5") }),
47350
- external_exports.object({ ...base, type: external_exports.literal("speech"), model: external_exports.enum(["gemini-3.8-flash-tts", "gemini-3.8-flash-lite-tts", ...ELEVENLABS_SPEECH_MODEL_IDS]).default("gemini-3.8-flash-lite-tts"), voice: external_exports.string().trim().max(80).default(""), delivery: external_exports.string().trim().max(600).default("") }).superRefine((p, ctx) => {
47351
- if (p.voice && (isElevenLabsSpeech(p.model) ? !/^[a-zA-Z0-9]{20}$/.test(p.voice) : !SPEECH_VOICES.includes(p.voice))) ctx.addIssue({ code: "custom", message: "Choose a voice supported by the speech provider.", path: ["voice"] });
47498
+ musicAsset.superRefine(musicChecks),
47499
+ external_exports.object({ ...base, type: external_exports.literal("speech"), model: external_exports.enum(["gemini-3.8-flash-tts", "gemini-3.8-flash-lite-tts", ...ELEVENLABS_SPEECH_MODEL_IDS, ...HEYGEN_SPEECH_MODEL_IDS]).default("gemini-3.8-flash-lite-tts"), voice: external_exports.string().trim().max(80).default(""), delivery: external_exports.string().trim().max(600).default("") }).superRefine((p, ctx) => {
47500
+ if (p.voice && !speechVoiceValid(p.model, p.voice)) ctx.addIssue({ code: "custom", message: "Choose a voice supported by the speech provider.", path: ["voice"] });
47352
47501
  if (isElevenLabsSpeech(p.model) && p.delivery) ctx.addIssue({ code: "custom", message: "ElevenLabs uses audio tags in the transcript; separate delivery instructions are only supported by Gemini.", path: ["delivery"] });
47353
- }).transform((p) => ({ ...p, voice: p.voice || (isElevenLabsSpeech(p.model) ? DEFAULT_ELEVENLABS_VOICE : "Kore") })),
47502
+ if (isHeyGenSpeech(p.model) && p.delivery) ctx.addIssue({ code: "custom", message: "HeyGen Voice speaks the transcript as written; separate delivery instructions are only supported by Gemini.", path: ["delivery"] });
47503
+ }).transform((p) => ({ ...p, voice: p.voice || defaultSpeechVoice(p.model) })),
47354
47504
  external_exports.object({ ...base, type: external_exports.literal("sfx"), model: external_exports.literal("eleven_text_to_sound_v2").default("eleven_text_to_sound_v2"), seconds: external_exports.number().min(0.5).max(30).default(5), loop: external_exports.boolean().default(false), promptInfluence: external_exports.number().min(0).max(1).default(0.3) }),
47355
47505
  vectorAsset.superRefine(vectorChecks).transform(vectorDefaults),
47356
47506
  modelAsset.superRefine(modelChecks).transform(modelDefaults)
@@ -47385,9 +47535,10 @@ function assetEstimate(p, now = Date.now()) {
47385
47535
  if (p.type === "vector") return vectorEstimate(p);
47386
47536
  if (p.type === "model") return modelEstimate(p);
47387
47537
  if (p.type === "video") return spriteVideoEstimate(spriteVideoModel(p.model), p, videoExtras(p));
47388
- if (p.type === "music") return 80;
47538
+ if (p.type === "music") return Math.ceil(musicCostUsd(p) / 1e-3);
47389
47539
  const units = (credits) => Math.max(1, Math.ceil(credits * UNITS_PER_CREDIT));
47390
47540
  if (p.type === "sfx") return units(Math.max(0, p.seconds) * 0.2);
47541
+ if (isHeyGenSpeech(p.model)) return units(speechCharacters(p.prompt) * (p.model === "heygen-voice-1-turbo" ? 0.4 : 1.5) / 1e3);
47391
47542
  if (isElevenLabsSpeech(p.model)) {
47392
47543
  const promotion2 = now < Date.UTC(2026, 9, 13);
47393
47544
  const perThousandCharacters = p.model === "eleven_v4_turbo" ? promotion2 ? 1.1 : 4 : promotion2 ? 2.2 : 8;
@@ -47411,7 +47562,7 @@ var VIDEO_PART_BYTES = 8 * 1024 * 1024;
47411
47562
  var VIDEO_MAX_BYTES = { html5: 64 * 1024 * 1024, mp4: 512 * 1024 * 1024 };
47412
47563
  var VIDEO_LIBRARY_BYTES = { user: 2 * 1024 ** 3, team: 10 * 1024 ** 3 };
47413
47564
  var VIDEO_VISIBILITIES = ["private", "public"];
47414
- var VIDEO_SHARING_AGREEMENT_VERSION = "2026-10-15-draft-2";
47565
+ var VIDEO_SHARING_AGREEMENT_VERSION = "2026-11-02";
47415
47566
  var videoAgreementAcceptance = external_exports.object({
47416
47567
  version: external_exports.literal(VIDEO_SHARING_AGREEMENT_VERSION),
47417
47568
  language: external_exports.enum(["en", "tr"])
@@ -48652,7 +48803,7 @@ var extras = {
48652
48803
  "style",
48653
48804
  "damage"
48654
48805
  ],
48655
- music: [],
48806
+ music: ["lyrics", "styles", "vocals", "seconds", "source"],
48656
48807
  speech: ["voice", "delivery"],
48657
48808
  sfx: ["seconds", "loop", "prompt-influence"],
48658
48809
  model: ["reference", "texture", "pbr", "faces", "rig", "animations", "height", "splats", "photo", "seed"],
@@ -48660,7 +48811,6 @@ var extras = {
48660
48811
  };
48661
48812
  var list2 = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
48662
48813
  function accepted(type) {
48663
- if (type === "music") return "Music accepts only --name, --prompt and --model; the model chooses the length, so fit it during the edit.";
48664
48814
  const options = extras[type];
48665
48815
  if (!options) return "";
48666
48816
  return `${type[0].toUpperCase()}${type.slice(1)} assets accept ${list2(["--name", "--prompt", "--model", ...options.map((option) => `--${option}`)])}.`;
@@ -48695,7 +48845,8 @@ function assetFromFlags(flags) {
48695
48845
  const given2 = value !== void 0 && (value !== false || (name2 === "texture" || name2 === "pbr") && flags.type !== "model");
48696
48846
  if (given2 && !extras[flags.type]?.includes(name2)) throw new Error(`--${name2} is not an option for ${flags.type} assets. ${accepted(flags.type)}`.trim());
48697
48847
  }
48698
- if (flags.type !== "video" && flags.type !== "vector" && !(flags.type === "model" && (flags.reference || isSplatGenerator(flags.model ?? ""))) && flags.prompt === void 0) throw new Error(`--prompt is required for ${flags.type} assets${flags.type === "model" ? " unless --reference names an image to build from" : ""}.`);
48848
+ const promptOptional = flags.type === "video" || flags.type === "vector" || flags.type === "model" && (flags.reference || isSplatGenerator(flags.model ?? "")) || flags.type === "music" && (flags.model === "fal/mureka-9.5-soundtrack" || flags.lyrics !== void 0);
48849
+ if (!promptOptional && flags.prompt === void 0) throw new Error(`--prompt is required for ${flags.type} assets${flags.type === "model" ? " unless --reference names an image to build from" : flags.type === "music" ? " unless Mureka 9.5 Song sings --lyrics or Mureka 9.5 Soundtrack scores --source" : ""}.`);
48699
48850
  const base2 = { type: flags.type, name: flags.name, prompt: flags.prompt, model: flags.model };
48700
48851
  if (flags.type === "image") return parseAsset({ ...base2, aspectRatio: flags["aspect-ratio"], transparent: flags.transparent, references: shas(flags.references), mask: regions(flags.mask) });
48701
48852
  if (flags.type === "video") {
@@ -48733,6 +48884,7 @@ function assetFromFlags(flags) {
48733
48884
  });
48734
48885
  }
48735
48886
  if (flags.type === "sfx") return parseAsset({ ...base2, seconds: flags.seconds, loop: flags.loop, promptInfluence: flags["prompt-influence"] });
48887
+ if (flags.type === "music") return parseAsset({ ...base2, lyrics: flags.lyrics, styles: shas(flags.styles), vocals: flags.vocals, seconds: flags.seconds, source: flags.source });
48736
48888
  if (flags.type === "model") return parseAsset({ ...base2, reference: flags.reference, texture: flags.texture, pbr: flags.pbr, faces: flags.faces, rig: flags.rig, animations: clips(flags.animations), height: flags.height, splats: flags.splats, photo: flags.photo || void 0, seed: flags.seed });
48737
48889
  if (flags.type === "vector") return parseAsset({ ...base2, workflow: flags.workflow, quality: flags.quality, aspectRatio: flags["aspect-ratio"], references: shas(flags.references), source: flags.source, shapes: flags.shapes, seed: flags.seed });
48738
48890
  return parseAsset({ ...base2, ...flags.type === "speech" ? { voice: flags.voice, delivery: flags.delivery } : {} });
@@ -50843,13 +50995,13 @@ var catalogSections = {
50843
50995
  image: ["assetTypes"],
50844
50996
  vector: ["assetTypes", "vectorModels", "vectorOptions"],
50845
50997
  video: ["assetTypes", "videoModels", "videoProfiles"],
50846
- music: ["assetTypes", "musicModels"],
50847
- speech: ["assetTypes", "speechModels", "voices", "elevenLabsVoices"],
50998
+ music: ["assetTypes", "musicModels", "musicOptions"],
50999
+ speech: ["assetTypes", "speechModels", "voices", "elevenLabsVoices", "heygenVoices"],
50848
51000
  sfx: ["assetTypes", "sfxModels"],
50849
51001
  model: ["assetTypes", "modelGenerators", "modelAnimations"],
50850
51002
  avatars: ["avatarTypes", "avatarLookTypes"]
50851
51003
  };
50852
- var catalog = () => ({ styles: SPRITE_STYLES, kinds: SPRITE_KINDS, actions: ALL_SPRITE_ACTIONS, videoModels: SPRITE_VIDEO_MODEL_IDS, assetTypes: ASSET_TYPES, musicModels: MUSIC_MODELS.map((m) => m.id), speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), modelGenerators: MODEL_GENERATORS.map((g) => ({ id: g.id, label: g.label, output: g.output, ...g.output === "spz" ? { splats: g.splats } : { faces: g.faces } })), modelAnimations: MODEL_ANIMATIONS, vectorModels: VECTOR_MODELS.map((m) => m.id), vectorOptions: { workflows: VECTOR_WORKFLOWS, qualities: VECTOR_QUALITIES, aspectRatios: VECTOR_ASPECT_RATIOS, shapes: VECTOR_SHAPES, maxReferences: MAX_VECTOR_REFERENCES }, elevenLabsVoices: ELEVENLABS_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES });
51004
+ var catalog = () => ({ styles: SPRITE_STYLES, kinds: SPRITE_KINDS, actions: ALL_SPRITE_ACTIONS, videoModels: SPRITE_VIDEO_MODEL_IDS, assetTypes: ASSET_TYPES, musicModels: MUSIC_MODELS.map((m) => m.id), musicOptions: { styles: MUREKA_STYLES, vocals: MUREKA_VOCALS, songSeconds: SONG_SECONDS, maxLyrics: MAX_SONG_LYRICS }, speechModels: SPEECH_MODELS.map((m) => m.id), sfxModels: SFX_MODELS.map((m) => m.id), modelGenerators: MODEL_GENERATORS.map((g) => ({ id: g.id, label: g.label, output: g.output, ...g.output === "spz" ? { splats: g.splats } : { faces: g.faces } })), modelAnimations: MODEL_ANIMATIONS, vectorModels: VECTOR_MODELS.map((m) => m.id), vectorOptions: { workflows: VECTOR_WORKFLOWS, qualities: VECTOR_QUALITIES, aspectRatios: VECTOR_ASPECT_RATIOS, shapes: VECTOR_SHAPES, maxReferences: MAX_VECTOR_REFERENCES }, elevenLabsVoices: ELEVENLABS_VOICES, heygenVoices: HEYGEN_VOICES, voices: SPEECH_VOICES, videoProfiles: SPRITE_VIDEO_MODELS, avatarTypes: AVATAR_CREATE_TYPES, avatarLookTypes: AVATAR_LOOK_TYPES });
50853
51005
  var modelFlags = [
50854
51006
  { name: "video-model", type: "string", choices: SPRITE_VIDEO_MODEL_IDS, description: "Video model override for this operation" }
50855
51007
  ];
@@ -51170,20 +51322,20 @@ Confirm code: ${device.user_code}`);
51170
51322
  })))).command("assets", (assets) => assets.add(defineCommand("list", { description: "List saved assets, their blob hashes, and configured generation models" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).action(async ({ args, flags, stdout, signal }) => out(stdout, await new Client(flags.url, signal).request(`${projectPath(args.id)}/assets`))))).add(defineCommand("generate", { description: "Generate an image, vector (SVG), video, music, speech, sound-effect or 3D model asset; --yes authorizes credits" }, (command) => command.flags({ name: "url", type: "string", default: "https://animaguru.com", env: { name: "ANIMAGURU_URL" } }).args(id).flags(
51171
51323
  { name: "type", type: "string", required: true, choices: ASSET_TYPES },
51172
51324
  { name: "name", type: "string", required: true },
51173
- { name: "prompt", type: "string", description: "Description to generate, or verbatim transcript for speech; video lip-sync and relight and vector image-to-vector take none, and camera-controls, insert-video, recast and 3d-to-video may leave it out" },
51325
+ { name: "prompt", type: "string", description: "Description to generate, or verbatim transcript for speech; video lip-sync and relight and vector image-to-vector take none, and camera-controls, insert-video, recast, 3d-to-video, a Mureka soundtrack and a song with --lyrics (where it sets the style) may leave it out" },
51174
51326
  { name: "model", type: "string", choices: assetModelIds, description: "Model for the chosen asset type" },
51175
51327
  { name: "aspect-ratio", type: "string", choices: [.../* @__PURE__ */ new Set([...IMAGE_ASPECT_RATIOS, "auto", ...VIDEO_ASPECT_RATIOS, ...VECTOR_ASPECT_RATIOS])], description: "Image: 1:1 (default), 3:2, 2:3, 16:9 or 9:16; a masked edit keeps Image 1's shape. Video from text or a style without --reference: 21:9\u20139:16 (default 16:9). Extension, reference-to-video, relight and keyframes-to-video: auto (default, the inputs' shape) or a ratio to crop to. Vector from text: auto (default, the model's choice) or 1:4\u20134:1" },
51176
51328
  { name: "transparent", type: "boolean", description: "Image: transparent background" },
51177
51329
  { name: "references", type: "string", description: "Comma-separated blob SHAs of this project's images or sprite art, named Image 1, Image 2\u2026 in the prompt. Image: up to 4 to follow, such as a character sheet. Vector from text: up to 5, the first leading. Video: subjects or looks to keep (reference-to-video and insert-video up to 9, 3d-to-video up to 8), or recast's new people, one photo each (up to 4)" },
51178
51330
  { name: "mask", type: "string", description: "Image: edit only these rectangles of Image 1 (the first --references image), as x,y,width,height fractions of its size from the top left, up to 8 separated by semicolons; the rest is kept" },
51179
- { name: "workflow", type: "string", choices: [...VIDEO_WORKFLOWS, ...VECTOR_WORKFLOWS], description: "Video: image-to-video (default), text-to-video or extend-video; H3 Max also reference-to-video, lip-sync, camera-controls, insert-video, recast, relight, 3d-to-video and style, FLUX 3 Max keyframes-to-video, HeyGen Video 1 reference-to-video, as the model's videoProfiles allow. Vector: text-to-vector (default) or image-to-vector, which traces --source" },
51331
+ { name: "workflow", type: "string", choices: [...VIDEO_WORKFLOWS, ...VECTOR_WORKFLOWS], description: "Video: image-to-video (default), text-to-video or extend-video; H3 Max also reference-to-video, lip-sync, camera-controls, insert-video, recast, relight, 3d-to-video and style, FLUX 3 Max keyframes-to-video, HeyGen Video 1 and Seedance reference-to-video, as the model's videoProfiles allow. Vector: text-to-vector (default) or image-to-vector, which traces --source" },
51180
51332
  { name: "reference", type: "string", description: "Video: starting image blob SHA from this project's assets or sprites; the speaking face for lip-sync, the image the camera moves around for camera-controls. Model: the image or sprite art to build it from (image-to-3D); without one the prompt describes it" },
51181
51333
  { name: "end-reference", type: "string", description: "Video: ending image blob SHA; models with endFrameOnly accept it without --reference" },
51182
51334
  { name: "middle-reference", type: "string", description: "Reference-to-video: image blob SHA reached at --middle-seconds; needs --reference and --end-reference, 480p or 768p" },
51183
51335
  { name: "middle-seconds", type: "number", description: "Reference-to-video: when the middle image is reached, in seconds" },
51184
- { name: "source", type: "string", description: "Blob SHA of a video asset in this project: the clip to extend, insert a scene into, recast or relight, or the 3D render 3d-to-video turns into footage. Vector image-to-vector: the image or sprite art to trace" },
51336
+ { name: "source", type: "string", description: "Blob SHA of a video asset in this project: the clip to extend, insert a scene into, recast or relight, or the 3D render 3d-to-video turns into footage. Vector image-to-vector: the image or sprite art to trace. Music with --model fal/mureka-9.5-soundtrack: the video (up to 100 MB), image or sprite art to score; a video's soundtrack runs as long as the video" },
51185
51337
  { name: "soundtrack", type: "string", description: "Video from an image or text: blob SHA of a music, speech or SFX asset pinned as the soundtrack (2 s or longer). Lip-sync: the speech to say (5 s\u201315 min), which sets the length" },
51186
- { name: "audio-references", type: "string", description: "Extension or reference-to-video: up to 3 comma-separated audio asset blob SHAs (on fal 2\u201315 s each, 15 s total) guiding the sound; refer to them as Audio 1, Audio 2\u2026 in the prompt" },
51338
+ { name: "audio-references", type: "string", description: "Extension or reference-to-video: up to 3 comma-separated audio asset blob SHAs (on fal and Seedance 2\u201315 s each, 15 s total; Seedance 2.5 30 s) guiding the sound; refer to them as Audio 1, Audio 2\u2026 in the prompt" },
51187
51339
  { name: "reference-videos", type: "string", description: "Reference-to-video or insert-video: up to 3 comma-separated video asset blob SHAs (on fal 2\u201315 s each, 15 s total; HeyGen reads the first 5 s of each) guiding motion, named Video 1, Video 2\u2026 in the prompt" },
51188
51340
  { name: "camera", type: "string", description: 'Camera-controls: 2\u201312 keyframes time,azimuth,elevation,distance (time 0\u20131, angles in degrees, elevation \u221290\u201390) separated by semicolons, e.g. "0,0,0,1;1,90,15,1.2"' },
51189
51341
  { name: "keyframes", type: "string", description: 'Keyframes-to-video (FLUX 3 Max): 1\u201310 seconds,image-SHA pairs separated by semicolons, e.g. "0,SHA;2.5,SHA;5,SHA"; each image is reached at its second, on a frame of its own of the 24 fps clip, within --seconds' },
@@ -51197,14 +51349,17 @@ Confirm code: ${device.user_code}`);
51197
51349
  { name: "generated-references", type: "number", description: "3d-to-video without --references: how many reference images it may draw, 1\u20138 (default 2)" },
51198
51350
  { name: "style", type: "string", choices: VIDEO_STYLES, description: "Style workflow: the preset look, at 768p for 5\u201315 whole seconds" },
51199
51351
  { name: "damage", type: "string", choices: VHS_DAMAGE_LEVELS, description: "VHS style: tape damage (fal's default medium)" },
51200
- { name: "seconds", type: "number", description: "Video or SFX duration in seconds (default 5); H3 takes fractions (6.5), FLUX 3 Max 5\u201320 whole seconds, HeyGen Video 1 5\u201315 (up to 30 from an image or text with --prompt-expansion balanced or quality); extensions add this many seconds, insert-video's scene is 5\u201313; lip-sync, recast, relight and 3d-to-video take their input's length; SFX supports 0.5\u201330" },
51352
+ { name: "seconds", type: "number", description: "Video, SFX or song duration in seconds (default 5; a Mureka song picks its own); H3 takes fractions (6.5), FLUX 3 Max 5\u201320 whole seconds, HeyGen Video 1 5\u201315 (up to 30 from an image or text with --prompt-expansion balanced or quality), Seedance 4\u201315 whole seconds (2.5 up to 30); extensions add this many seconds, insert-video's scene is 5\u201313; lip-sync, recast, relight and 3d-to-video take their input's length; SFX supports 0.5\u201330; Mureka 9.5 Song 120\u2013300 whole seconds" },
51201
51353
  { name: "resolution", type: "string", choices: VIDEO_RESOLUTIONS, description: "Video resolution supported by the selected model and workflow (default its first)" },
51202
51354
  { name: "mode", type: "string", choices: ["cost", "speed", "quality"], description: "Video generation mode supported by the selected model (default its first)" },
51203
51355
  { name: "prompt-expansion", type: "string", choices: PROMPT_EXPANSION_MODES, description: "Video: how much the model may rewrite the prompt (default disabled); extensions treat any other value as on. FLUX 3 Max always reasons about the prompt: quality thoroughly, any other value lightly. HeyGen Video 1 needs balanced or quality for clips over 15 s" },
51204
51356
  { name: "seed", type: "number", description: "Video, vector from text, or model with --model idol: seed for repeatable results, where the model takes one" },
51205
51357
  { name: "extend-output", type: "string", choices: EXTEND_OUTPUTS, description: "Extension: extended (default, source plus new footage) or continuation (a 1.625 s overlap, then the new footage)" },
51206
- { name: "voice", type: "string", description: "Gemini voice name or ElevenLabs voice ID (defaults: Kore / George)" },
51207
- { name: "delivery", type: "string", description: "Gemini speech delivery instructions; ElevenLabs uses audio tags in the transcript" },
51358
+ { name: "voice", type: "string", description: "Gemini voice name, or an ElevenLabs or HeyGen public voice ID (defaults: Kore / George / Nadine; catalog --type speech suggests more)" },
51359
+ { name: "delivery", type: "string", description: "Gemini speech delivery instructions; ElevenLabs uses audio tags in the transcript, and HeyGen Voice reads it as written" },
51360
+ { name: "lyrics", type: "string", description: `Music with --model fal/mureka-9.5-song: the words to sing, up to ${MAX_SONG_LYRICS.toLocaleString("en-US")} characters, sections tagged [Verse], [Chorus]\u2026; --prompt then sets the style. A sung song costs 15 credits, one written from the prompt 50` },
51361
+ { name: "styles", type: "string", description: `Music with --model fal/mureka-9.5-song and no --lyrics: comma-separated genres from ${MUREKA_STYLES.join(", ")}` },
51362
+ { name: "vocals", type: "string", choices: MUREKA_VOCALS, description: "Music with --model fal/mureka-9.5-song and --lyrics: who sings" },
51208
51363
  { name: "loop", type: "boolean", description: "SFX: create a seamless loop" },
51209
51364
  { name: "texture", type: "boolean", description: "Model: textured (default on); --no-texture makes a plain white model" },
51210
51365
  { name: "pbr", type: "boolean", description: "Model: metallic, roughness and normal maps with the texture (default on); --no-pbr leaves them out" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docyrus/animaguru",
3
- "version": "0.35.1",
3
+ "version": "0.36.0",
4
4
  "description": "Agent-friendly AnimaGuru CLI built with CrustJS",
5
5
  "type": "module",
6
6
  "bin": {
@@ -62,10 +62,16 @@ animaguru assets generate PROJECT_ID --type speech --name "Welcome" \
62
62
  --prompt "Welcome, traveler." --voice Kore --delivery "Warm and welcoming" --yes
63
63
  ```
64
64
 
65
- Images use the staff-managed route automatically. Use `--model` to select a model for video, music, speech or sound effects; discover the choices with `catalog` and the server's configured subset with `assets list`. Asset defaults are per type, independently of sprite project defaults. Image backgrounds are retained unless `--transparent` is supplied. CLI 0.17.0 adds `--references`, `--mask` and the 16:9 and 9:16 image shapes. `--references SHA,SHA` (up to four) makes an image follow this project's saved images, uploads or sprite art. To keep a recurring character consistent, generate a character sheet once and reference its `file` SHA in every later image; refer to references in the prompt as Image 1, Image 2 and so on, and say what to take from each. `--aspect-ratio` is 1:1, 3:2, 2:3, 16:9 or 9:16; use 16:9 or 9:16 for video scenes. `--mask x,y,width,height[;…]` (up to eight rectangles, in fractions of Image 1 from the top left) edits only those parts of Image 1, the first reference, and keeps the rest and Image 1's shape. Look at the image before choosing the rectangles. Videos require an image asset's `file` SHA from `assets list`, or a character's `art` SHA from `projects get`, in the same project. Validate video options against the selected model's `videoProfiles` in `catalog`; omitted video settings use five seconds and that provider's first resolution/mode. MiniMax H3 Max and H3 Max Turbo (`fal/minimax-h3-max`, `fal/minimax-h3-max-turbo`) also take `--workflow text-to-video` (with `--aspect-ratio`) and `--workflow extend-video` (with `--source VIDEO_SHA`, 2K resolution, `--extend-output`, and up to three comma-separated `--audio-references`). From images, they accept `--end-reference` with or without `--reference` and a `--soundtrack AUDIO_SHA`. All workflows take `--prompt-expansion` and `--seed`. These need CLI 0.8.0 or newer. CLI 0.18.0 adds H3 Max's (not Turbo's) `--workflow reference-to-video` (keep a character across clips from up to nine `--references`, three `--reference-videos` and three `--audio-references`, named Image 1, Video 1, Audio 1 in the prompt; optional `--reference`, `--end-reference`, `--middle-reference` with `--middle-seconds`), `lip-sync` (the face in `--reference` says `--soundtrack` speech of 5 s–15 min; no `--prompt`; `--transcribe`), `camera-controls` (`--camera "time,azimuth,elevation,distance;…"`, 2–12 keyframes around `--reference`; without a prompt only the camera moves), `insert-video` (a 5–13 s scene inside `--source` from `--insert-at` to `--resume-at`, guided by `--references`/`--reference-videos`), `recast` (people in `--references` replace those in `--source`; pass `--subject-consent` only after each person agreed), `relight` (`--source` relit from a `--lighting` sphere image; no prompt), `3d-to-video` (a 3D render `--source` into footage, from `--references` or `--generated-references`) and `style` (`--style vhs|retro-toon-70s|low-poly|hand-drawn|16bit-pixel`, `--damage` for VHS, 768p, 5–15 whole seconds). Lip-sync, recast, relight and 3d-to-video take their input's length; their dry runs, like reference-to-video's and insert-video's, are server estimates because the price depends on the files. H3 takes fractional `--seconds` (6.5). CLI 0.21.0 adds FLUX 3 Max (`fal/flux-3-max`): image-to-video (with an optional `--end-reference`) and text-to-video for 5–20 whole seconds at 720p or 1080p with its own sound and no `--soundtrack`, and `--workflow keyframes-to-video`, which passes through 1–10 `--keyframes "SECONDS,SHA;…"` images, each reached at its second within `--seconds`. It always reasons about the prompt: `--prompt-expansion quality` thoroughly, other values lightly. CLI 0.30.0 adds HeyGen Video 1's (`heygen/heygen-video-1`) `--workflow text-to-video` (with `--aspect-ratio`) and `reference-to-video` (up to nine `--references`, three `--reference-videos`, of which it reads the first 5 s, and three `--audio-references`, named Image 1, Video 1, Audio 1 in the prompt; no `--reference`, `--end-reference` or `--middle-reference`), 1080p and 2K (16:9 or 9:16 from text or references), and `--seed`. From an image or text it runs to 30 whole seconds with `--prompt-expansion balanced` or `quality`, and every second past 15 costs more. For Gemini speech, `--prompt` is spoken verbatim and `--delivery` is a separate instruction. Music uses Lyria; the Gemini TTS models are for speech.
65
+ Images use the staff-managed route automatically. Use `--model` to select a model for video, music, speech or sound effects; discover the choices with `catalog` and the server's configured subset with `assets list`. Asset defaults are per type, independently of sprite project defaults. Image backgrounds are retained unless `--transparent` is supplied. CLI 0.17.0 adds `--references`, `--mask` and the 16:9 and 9:16 image shapes. `--references SHA,SHA` (up to four) makes an image follow this project's saved images, uploads or sprite art. To keep a recurring character consistent, generate a character sheet once and reference its `file` SHA in every later image; refer to references in the prompt as Image 1, Image 2 and so on, and say what to take from each. `--aspect-ratio` is 1:1, 3:2, 2:3, 16:9 or 9:16; use 16:9 or 9:16 for video scenes. `--mask x,y,width,height[;…]` (up to eight rectangles, in fractions of Image 1 from the top left) edits only those parts of Image 1, the first reference, and keeps the rest and Image 1's shape. Look at the image before choosing the rectangles. Videos require an image asset's `file` SHA from `assets list`, or a character's `art` SHA from `projects get`, in the same project. Validate video options against the selected model's `videoProfiles` in `catalog`; omitted video settings use five seconds and that provider's first resolution/mode. MiniMax H3 Max and H3 Max Turbo (`fal/minimax-h3-max`, `fal/minimax-h3-max-turbo`) also take `--workflow text-to-video` (with `--aspect-ratio`) and `--workflow extend-video` (with `--source VIDEO_SHA`, 2K resolution, `--extend-output`, and up to three comma-separated `--audio-references`). From images, they accept `--end-reference` with or without `--reference` and a `--soundtrack AUDIO_SHA`. All workflows take `--prompt-expansion` and `--seed`. These need CLI 0.8.0 or newer. CLI 0.18.0 adds H3 Max's (not Turbo's) `--workflow reference-to-video` (keep a character across clips from up to nine `--references`, three `--reference-videos` and three `--audio-references`, named Image 1, Video 1, Audio 1 in the prompt; optional `--reference`, `--end-reference`, `--middle-reference` with `--middle-seconds`), `lip-sync` (the face in `--reference` says `--soundtrack` speech of 5 s–15 min; no `--prompt`; `--transcribe`), `camera-controls` (`--camera "time,azimuth,elevation,distance;…"`, 2–12 keyframes around `--reference`; without a prompt only the camera moves), `insert-video` (a 5–13 s scene inside `--source` from `--insert-at` to `--resume-at`, guided by `--references`/`--reference-videos`), `recast` (people in `--references` replace those in `--source`; pass `--subject-consent` only after each person agreed), `relight` (`--source` relit from a `--lighting` sphere image; no prompt), `3d-to-video` (a 3D render `--source` into footage, from `--references` or `--generated-references`) and `style` (`--style vhs|retro-toon-70s|low-poly|hand-drawn|16bit-pixel`, `--damage` for VHS, 768p, 5–15 whole seconds). Lip-sync, recast, relight and 3d-to-video take their input's length; their dry runs, like reference-to-video's and insert-video's, are server estimates because the price depends on the files. H3 takes fractional `--seconds` (6.5). CLI 0.21.0 adds FLUX 3 Max (`fal/flux-3-max`): image-to-video (with an optional `--end-reference`) and text-to-video for 5–20 whole seconds at 720p or 1080p with its own sound and no `--soundtrack`, and `--workflow keyframes-to-video`, which passes through 1–10 `--keyframes "SECONDS,SHA;…"` images, each reached at its second within `--seconds`. It always reasons about the prompt: `--prompt-expansion quality` thoroughly, other values lightly. CLI 0.30.0 adds HeyGen Video 1's (`heygen/heygen-video-1`) `--workflow text-to-video` (with `--aspect-ratio`) and `reference-to-video` (up to nine `--references`, three `--reference-videos`, of which it reads the first 5 s, and three `--audio-references`, named Image 1, Video 1, Audio 1 in the prompt; no `--reference`, `--end-reference` or `--middle-reference`), 1080p and 2K (16:9 or 9:16 from text or references), and `--seed`. From an image or text it runs to 30 whole seconds with `--prompt-expansion balanced` or `quality`, and every second past 15 costs more. For Gemini speech, `--prompt` is spoken verbatim and `--delivery` is a separate instruction. Music uses Lyria (`lyria-3.5`, the default) or Mureka 9.5; the Gemini TTS models are for speech.
66
66
 
67
67
  For ElevenLabs speech, choose `eleven_v4` or `eleven_v4_turbo`, pass an ElevenLabs voice ID with `--voice` (George is the default), and put audio tags in `--prompt` rather than using `--delivery`. For sound effects, use `--type sfx`; the only model is `eleven_text_to_sound_v2`. SFX supports `--seconds` from 0.5 to 30 (default 5), `--loop`, and `--prompt-influence` from 0 to 1 (default 0.3). These additions require CLI 0.5.0 or newer; check `catalog` before using them with an installed CLI.
68
68
 
69
+ CLI 0.36.0 adds Mureka 9.5 music on fal. `--model fal/mureka-9.5-song` sings `--lyrics` (up to 5,000 characters; tag sections `[Verse]`, `[Chorus]`) with `--vocals female|male`, and `--prompt` then sets the style (optional, up to 1,024 characters); without lyrics it writes the words from `--prompt` (up to 2,000 characters) in optional `--styles pop,rock,…` (`catalog --type music` lists them). `--seconds 120–300` asks for a length; otherwise Mureka chooses one, usually three to four minutes. A sung song costs 15 credits, one written from the prompt 50. `--model fal/mureka-9.5-instrumental` writes from `--prompt` alone (up to 1,024 characters, 15 credits). `--model fal/mureka-9.5-soundtrack --source SHA` scores a saved video (up to 100 MB), image or sprite art for 11 credits, with an optional mood `--prompt`; a video's soundtrack runs as long as the video, so score a finished cut, and an image gets a full-length track. Lyria takes none of these options and picks its own length. All of them return MP3.
70
+
71
+ Seedance on BytePlus (`byteplus/seedance-2.5`, `byteplus/seedance-2.0`, `byteplus/seedance-2.0-fast`, `byteplus/seedance-2.0-mini`) films from `--reference` (optionally ending on `--end-reference`; the clip keeps the image's shape), from text (`--workflow text-to-video --aspect-ratio …`) or from saved images and audio (`--workflow reference-to-video`, up to nine `--references` and three `--audio-references`, named Image 1 and Audio 1 in the prompt; all but 2.5 need an image beside audio). It runs 4–15 whole seconds (2.5 up to 30) at 480p or 720p (2.0 also 1080p) with its own sound, and takes no `--soundtrack`, `--seed`, `--prompt-expansion`, reference videos or extensions. It refuses images of real people's faces, so use illustrated or generated art. It is charged the tokens BytePlus counts, never more than the dry run's estimate.
72
+
73
+ HeyGen Voice (`heygen-voice-1`, or the faster and cheaper `heygen-voice-1-turbo`) speaks any of HeyGen's public voices: pass its ID with `--voice` (Nadine is the default; `catalog --type speech` lists `heygenVoices` to start from). It reads `--prompt` as written and detects the language, so it takes no `--delivery`; shape the read with punctuation and wording. It returns WAV and costs 1.5 credits per 1,000 characters, or 0.4 on Turbo.
74
+
69
75
  CLI 0.27.0 adds vectors: `--type vector` draws an editable SVG with Ideogram on fal (`fal/ideogram-vector`), for logos, icons, mascots and flat illustrations that must stay sharp at any size or move shape by shape. `--workflow text-to-vector` (default) draws `--prompt` at `--quality low|medium|high` (13, 16 or 20 credits; 32 at high with references), with `--aspect-ratio auto` (default) or 1:4–4:1, `--seed`, and up to five `--references` (this project's images or sprite art, the first leading, named Image 1… in the prompt). `--workflow image-to-vector --source IMAGE_SHA` traces a saved image or sprite for 10 credits, with `--shapes detailed|simple` and no `--prompt`; to vectorize a brand logo or a generated picture, save it as an image asset first. `--download` saves `NAME.svg`. Vectors can't be used as image or video references. Check `catalog --type vector` before using them with an installed CLI.
70
76
 
71
77
  ```sh
@@ -16,9 +16,9 @@ animaguru videos list --scope shared
16
16
  animaguru videos get VIDEO_ID
17
17
  ```
18
18
 
19
- Submissions default to private. `--share` is a comma-separated list of verified AnimaGuru account emails; selected viewers sign in to watch. `--visibility public` lists the animation at [Videos](https://animaguru.com/videos) and permits anyone to watch, download its export, and embed an HTML5 player. Choose the audience from the user's request; a request to make or export a film alone does not authorize sharing it. `--yes` acknowledges the upload and selected audience, and spends no generation credits.
19
+ Submissions default to private. `--share` is a comma-separated list of verified AnimaGuru account emails; AnimaGuru emails each selected viewer the watch link once the upload finishes, and they sign in to watch. `--visibility public` lists the animation at [Videos](https://animaguru.com/videos) and permits anyone to watch, download its export, and embed an HTML5 player. Choose the audience from the user's request; a request to make or export a film alone does not authorize sharing it. `--yes` acknowledges the upload and selected audience, and spends no generation credits.
20
20
 
21
- The JSON result returns the video ID and watch URL. Owners manage details and recipients on that page, or run `animaguru videos share VIDEO_ID --visibility private --share "reviewer@example.com" --yes`; this replaces the entire recipient list. Public sharing uses `--visibility public` without `--share`. Removing a recipient or making a public film private blocks previous playback URLs immediately. `animaguru videos poster VIDEO_ID --file production/exports/film.jpg --yes` replaces the poster of an uploaded video with a PNG, JPEG or WebP up to 2 MiB, such as the designed thumbnail the MP4 export saves. A public video's new poster goes back to staff review and the video is hidden from the public until it is approved, so tell the user before replacing it. `animaguru videos delete VIDEO_ID --yes` removes the hosted files.
21
+ The JSON result returns the video ID and watch URL. Owners manage details and recipients on that page, or run `animaguru videos share VIDEO_ID --visibility private --share "reviewer@example.com" --yes`; this replaces the entire recipient list, and AnimaGuru emails the link to each newly added recipient (once per video, so re-adding someone sends nothing). Public sharing uses `--visibility public` without `--share`. Removing a recipient or making a public film private blocks previous playback URLs immediately. `animaguru videos poster VIDEO_ID --file production/exports/film.jpg --yes` replaces the poster of an uploaded video with a PNG, JPEG or WebP up to 2 MiB, such as the designed thumbnail the MP4 export saves. A public video's new poster goes back to staff review and the video is hidden from the public until it is approved, so tell the user before replacing it. `animaguru videos delete VIDEO_ID --yes` removes the hosted files.
22
22
 
23
23
  `videos list` shows the selected workspace's library; add `--workspace personal` or `--workspace TEAM_ID` for another (CLI 0.20.0). When the user asks to move videos between their personal library and a team, run `animaguru videos move VIDEO_ID… --workspace TEAM_ID --yes` (or `--workspace personal`). Moving keeps each video's ID, links, subtitles, recipients and review, and every team member can watch it, so move only videos the user names. A video made from a project's animation stays with its project: the user transfers the project to the team on the website first. If one video can't be moved, the command stops and reports `moved`, `error` and `notMoved`; fix the cause, then rerun it with the same IDs, since a video already in the target library is left as it is.
24
24