makaron-cli 0.13.7 → 0.13.9
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +26 -2
- package/bin/makaron.mjs +222 -29
- package/package.json +1 -1
- package/skills/makaron/SKILL.md +31 -3
package/README.md
CHANGED
|
@@ -140,6 +140,20 @@ npx makaron-cli chat --project auto --image selfie.jpg --skill <marketplace-id-o
|
|
|
140
140
|
|
|
141
141
|
`--skill` accepts an installed skill name, a marketplace UUID, or a unique marketplace label. If a marketplace skill is matched, the CLI installs or reuses it and sends `[Active skill: <installed-skill-name>]` to Makaron Agent. Ordinary users do not need admin commands, and the CLI intentionally does not expose skill deletion.
|
|
142
142
|
|
|
143
|
+
### Built-in production skills
|
|
144
|
+
|
|
145
|
+
Discover the available production workflows before choosing `--skill`:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx makaron-cli skills list --built-in
|
|
149
|
+
npx makaron-cli skills search "talking head captions" --built-in
|
|
150
|
+
npx makaron-cli skills show talking-head --built-in
|
|
151
|
+
npx makaron-cli chat --project auto --video talk.mp4 --skill talking-head -b "make a tight captioned edit"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The default list shows callable/discoverable skills with their purpose and input
|
|
155
|
+
requirements. Add `--all` to include internal adapters and helper skills.
|
|
156
|
+
|
|
143
157
|
### With additional images (existing project)
|
|
144
158
|
|
|
145
159
|
```bash
|
|
@@ -246,7 +260,7 @@ npx makaron-cli chat --project <id> --video party.mp4 --image kid.jpg -b "make t
|
|
|
246
260
|
npx makaron-cli chat --project <id> --video clip1.mp4 --video clip2.mp4 -b "splice these into one seamless video"
|
|
247
261
|
```
|
|
248
262
|
|
|
249
|
-
Video files are uploaded via signed URL. CLI local video uploads support `.mp4`, `.mov`, or `.webm`, max 50MB, max
|
|
263
|
+
Video files are uploaded via signed URL. CLI local video uploads support `.mp4`, `.mov`, or `.webm`, max 50MB, max 900s (15 minutes) with 1s metadata tolerance, and <=1080p / 2,086,876 frame pixels. The frontend can transcode larger videos before upload; the CLI uploads directly to Storage and rejects videos above those limits.
|
|
250
264
|
The agent understands video content natively — it can analyze scenes, edit, extend, and compose videos. Seedance video-reference editing is still limited to ~15s provider references, so longer uploaded videos should be split/prepared by the agent before model submission; Kling remains the base/direct edit path.
|
|
251
265
|
Use `chat --project <id|auto> --video ...` for any project/timeline video work. Direct `video create` is standalone and does not write timeline entries.
|
|
252
266
|
|
|
@@ -363,7 +377,7 @@ For project/timeline video editing, use:
|
|
|
363
377
|
npx makaron-cli chat --project <id|auto> --video input.mp4 -b "make it funny"
|
|
364
378
|
```
|
|
365
379
|
|
|
366
|
-
Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to the selected model limit), `--video <file|url>` and `--audio <file|url>` (repeatable where supported), `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3`, `--video-resolution auto|480p|720p|768p|1080p|2k|4k`. Default model is `seedance-fast`. SeeDance accepts native text-to-video with no image and integer output duration 4-15s (default 5s); `seedance-mini` supports 480p/720p and is best for cheaper drafts/multi-size tests; MiniMax H3 accepts native text-to-video, 4-15s output, public 768p/2k resolution, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. H3 defaults to 768p; request 2k explicitly for maximum/final quality. Kling supports 5-15s; Grok 1.5 supports 1-15s single-image-to-video only; Gemini Omni supports 3-10s fast 720p image/video generation and editing with native generated audio, including up to 6 image references when no video reference is provided. For `--video-model grok`, forced `--aspect` is ignored to avoid xAI stretching the source image; pad/create the image at the target shape first or use another model.
|
|
380
|
+
Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to the selected model limit), `--video <file|url>` and `--audio <file|url>` (repeatable where supported), `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3|sync-lipsync-v3`, `--video-resolution auto|480p|720p|768p|1080p|2k|4k`. Default model is `seedance-fast`. SeeDance accepts native text-to-video with no image and integer output duration 4-15s (default 5s); `seedance-mini` supports 480p/720p and is best for cheaper drafts/multi-size tests; MiniMax H3 accepts native text-to-video, 4-15s output, public 768p/2k resolution, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. `sync-lipsync-v3` requires exactly one video plus one MP3/WAV and preserves that replacement audio while aligning the mouth. H3 defaults to 768p; request 2k explicitly for maximum/final quality. Kling supports 5-15s; Grok 1.5 supports 1-15s single-image-to-video only; Gemini Omni supports 3-10s fast 720p image/video generation and editing with native generated audio, including up to 6 image references when no video reference is provided. For `--video-model grok`, forced `--aspect` is ignored to avoid xAI stretching the source image; pad/create the image at the target shape first or use another model.
|
|
367
381
|
|
|
368
382
|
Seedance 2.5: use `--video-model seedance-2.5` for 4-30 second output at 480p/720p. `--image` accepts local files or URLs (up to 30), while repeatable `--video` and `--audio` accept up to 10 each. Use `--video-operation generate|edit|extend`, `--extend-direction forward|backward`, `--output-format mp4|mov`, `--web-search`, `--generated-audio` / `--no-generated-audio`, and `--relaxed-content-filter`. Edit/extend require a video reference. The Evolink route does not currently expose 4K output.
|
|
369
383
|
|
|
@@ -414,6 +428,7 @@ type CompletionAction = {
|
|
|
414
428
|
3. Stop when `status` is `"completed"`, `"failed"`, or `"aborted"`
|
|
415
429
|
4. Top-level `status: "completed"` means ALL artifacts are ready (including rendered videos)
|
|
416
430
|
5. If an async video fails, top-level `status` is `"failed"` and the failed video may include `completion_actions` for a safe retry or diagnosis. Agents can surface these as the next user-confirmed step.
|
|
431
|
+
6. `responses get --wait` reconciles pending video output against completed Project Media with the same `snapshot_id` or `task_id`. A lagging Run row therefore does not block delivery after the durable project video is ready.
|
|
417
432
|
|
|
418
433
|
## Exit Codes
|
|
419
434
|
|
|
@@ -494,6 +509,15 @@ send_message "All done!"
|
|
|
494
509
|
|
|
495
510
|
Admin commands require an API key with admin privileges. Ask your admin to run `makaron admin set-admin <your-email>` to grant access.
|
|
496
511
|
|
|
512
|
+
### Add credits to a user
|
|
513
|
+
|
|
514
|
+
Use either the account email address or the Supabase user UUID. Credits must be a positive integer.
|
|
515
|
+
|
|
516
|
+
```bash
|
|
517
|
+
npx makaron-cli admin add-credits user@example.com 1000
|
|
518
|
+
npx makaron-cli admin add-credits <user-id> 1000 --json
|
|
519
|
+
```
|
|
520
|
+
|
|
497
521
|
### List all marketplace skills
|
|
498
522
|
|
|
499
523
|
```bash
|
package/bin/makaron.mjs
CHANGED
|
@@ -43,7 +43,7 @@ const SUPABASE_ANON_KEY = 'sb_publishable_FJFN2YYaWaQjABUKLqxQcA_fhxPLFDY';
|
|
|
43
43
|
|
|
44
44
|
const MAX_VIDEO_UPLOAD_FILE_SIZE_MB = 50;
|
|
45
45
|
const MAX_VIDEO_UPLOAD_FILE_SIZE = MAX_VIDEO_UPLOAD_FILE_SIZE_MB * 1024 * 1024;
|
|
46
|
-
const MAX_VIDEO_UPLOAD_DURATION =
|
|
46
|
+
const MAX_VIDEO_UPLOAD_DURATION = 900;
|
|
47
47
|
const MAX_VIDEO_UPLOAD_DURATION_TOLERANCE = 1;
|
|
48
48
|
const MAX_VIDEO_PROVIDER_REFERENCE_DURATION = 15;
|
|
49
49
|
const MAX_VIDEO_PROVIDER_REFERENCE_DURATION_TOLERANCE = 0.5;
|
|
@@ -328,6 +328,86 @@ function normalizeRunResponse(data) {
|
|
|
328
328
|
return data;
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
+
function projectMediaIdentity(item) {
|
|
332
|
+
const snapshotId = item?.snapshot_id || item?.snapshotId;
|
|
333
|
+
const taskId = item?.task_id || item?.taskId;
|
|
334
|
+
return {
|
|
335
|
+
snapshotId: typeof snapshotId === 'string' && snapshotId ? snapshotId : null,
|
|
336
|
+
taskId: typeof taskId === 'string' && taskId ? taskId : null,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function findMatchingCompletedProjectVideo(item, media) {
|
|
341
|
+
const identity = projectMediaIdentity(item);
|
|
342
|
+
if (!identity.snapshotId && !identity.taskId) return null;
|
|
343
|
+
return (media || []).find(candidate => {
|
|
344
|
+
if (candidate?.type !== 'video' || candidate?.status !== 'completed' || !candidate?.url) return false;
|
|
345
|
+
const candidateIdentity = projectMediaIdentity(candidate);
|
|
346
|
+
return (identity.snapshotId && candidateIdentity.snapshotId === identity.snapshotId)
|
|
347
|
+
|| (identity.taskId && candidateIdentity.taskId === identity.taskId);
|
|
348
|
+
}) || null;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async function reconcileRunWithProjectMedia(baseUrl, headers, data) {
|
|
352
|
+
normalizeRunResponse(data);
|
|
353
|
+
const output = Array.isArray(data.output) ? data.output : [];
|
|
354
|
+
const pendingVideos = output.filter(item =>
|
|
355
|
+
item?.type === 'video' && (item.status === 'queued' || item.status === 'rendering')
|
|
356
|
+
);
|
|
357
|
+
const agentDone = data.agent_status === 'completed'
|
|
358
|
+
|| (data.status === 'in_progress' && data.incomplete === true);
|
|
359
|
+
if (!agentDone || pendingVideos.length === 0 || !data.projectId) return data;
|
|
360
|
+
|
|
361
|
+
let projectMedia;
|
|
362
|
+
try {
|
|
363
|
+
const res = await fetch(`${baseUrl}/api/projects/${data.projectId}/media`, { headers });
|
|
364
|
+
if (!res.ok) return data;
|
|
365
|
+
projectMedia = await res.json();
|
|
366
|
+
} catch {
|
|
367
|
+
return data;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
let reconciled = false;
|
|
371
|
+
for (const item of pendingVideos) {
|
|
372
|
+
const completed = findMatchingCompletedProjectVideo(item, projectMedia.media);
|
|
373
|
+
if (!completed) continue;
|
|
374
|
+
const identity = projectMediaIdentity(completed);
|
|
375
|
+
item.status = 'completed';
|
|
376
|
+
item.url = completed.url;
|
|
377
|
+
if (identity.snapshotId) item.snapshot_id = identity.snapshotId;
|
|
378
|
+
if (identity.taskId) item.task_id = identity.taskId;
|
|
379
|
+
if (completed.posterUrl) item.poster_url = completed.posterUrl;
|
|
380
|
+
for (const field of ['duration', 'width', 'height']) {
|
|
381
|
+
if (typeof completed[field] === 'number') item[field] = completed[field];
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const legacyVideos = Array.isArray(data.result?.videos) ? data.result.videos : [];
|
|
385
|
+
const legacy = legacyVideos.find(video => {
|
|
386
|
+
const legacyIdentity = projectMediaIdentity(video);
|
|
387
|
+
return (identity.snapshotId && legacyIdentity.snapshotId === identity.snapshotId)
|
|
388
|
+
|| (identity.taskId && legacyIdentity.taskId === identity.taskId);
|
|
389
|
+
});
|
|
390
|
+
if (legacy) {
|
|
391
|
+
legacy.status = 'completed';
|
|
392
|
+
legacy.videoUrl = completed.url;
|
|
393
|
+
if (identity.snapshotId && !legacy.snapshotId) legacy.snapshotId = identity.snapshotId;
|
|
394
|
+
}
|
|
395
|
+
reconciled = true;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (!reconciled) return data;
|
|
399
|
+
const pendingArtifacts = output.some(item =>
|
|
400
|
+
(item?.type === 'video' || item?.type === 'music')
|
|
401
|
+
&& (item.status === 'queued' || item.status === 'rendering')
|
|
402
|
+
);
|
|
403
|
+
if (!pendingArtifacts) {
|
|
404
|
+
data.status = 'completed';
|
|
405
|
+
data.incomplete = false;
|
|
406
|
+
delete data.next_poll_after_ms;
|
|
407
|
+
}
|
|
408
|
+
return data;
|
|
409
|
+
}
|
|
410
|
+
|
|
331
411
|
function collectCompletionActions(data) {
|
|
332
412
|
const items = [];
|
|
333
413
|
const add = (action, source) => {
|
|
@@ -392,6 +472,11 @@ What you can ask:
|
|
|
392
472
|
Marketplace skill
|
|
393
473
|
makaron chat --project auto --image selfie.jpg --skill "Football Captain" "make this cinematic"
|
|
394
474
|
|
|
475
|
+
Built-in production skill
|
|
476
|
+
makaron skills list --built-in
|
|
477
|
+
makaron skills show talking-head --built-in
|
|
478
|
+
makaron chat --project auto --video talk.mp4 --skill talking-head "make a tight captioned edit"
|
|
479
|
+
|
|
395
480
|
Fix one video moment from a screenshot
|
|
396
481
|
makaron chat --project <id> --image screenshot.png "@4 this frame should be Paris; only fix this moment"
|
|
397
482
|
|
|
@@ -607,6 +692,7 @@ async function pollRun(baseUrl, headers, runId, opts = {}) {
|
|
|
607
692
|
continue;
|
|
608
693
|
}
|
|
609
694
|
data = await res.json();
|
|
695
|
+
data = await reconcileRunWithProjectMedia(baseUrl, headers, data);
|
|
610
696
|
} catch {
|
|
611
697
|
continue;
|
|
612
698
|
}
|
|
@@ -759,6 +845,7 @@ async function watchRun(baseUrl, headers, runId, opts = {}) {
|
|
|
759
845
|
continue;
|
|
760
846
|
}
|
|
761
847
|
data = await res.json();
|
|
848
|
+
data = await reconcileRunWithProjectMedia(baseUrl, headers, data);
|
|
762
849
|
} catch {
|
|
763
850
|
await new Promise(r => setTimeout(r, interval));
|
|
764
851
|
continue;
|
|
@@ -1174,12 +1261,29 @@ async function fetchBuiltInSkills(baseUrl) {
|
|
|
1174
1261
|
return (data.skills || []).filter(skill => skill.builtIn);
|
|
1175
1262
|
}
|
|
1176
1263
|
|
|
1177
|
-
function
|
|
1264
|
+
function isDiscoverableBuiltInSkill(skill) {
|
|
1265
|
+
return skill.userSelectable !== false || skill.manifestVisible === true;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
function builtInSkillSearchText(skill) {
|
|
1269
|
+
return [
|
|
1270
|
+
skill.name,
|
|
1271
|
+
skill.label,
|
|
1272
|
+
skill.description,
|
|
1273
|
+
skill.studioRunRecipe,
|
|
1274
|
+
skill.studioRunProfile,
|
|
1275
|
+
skill.canonicalSkill,
|
|
1276
|
+
...(Array.isArray(skill.tags) ? skill.tags : []),
|
|
1277
|
+
].filter(Boolean).join(' ').toLowerCase();
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
function printBuiltInSkills(skills, opts = {}) {
|
|
1178
1281
|
if (!skills.length) {
|
|
1179
1282
|
console.log('No built-in skills found.');
|
|
1180
1283
|
return;
|
|
1181
1284
|
}
|
|
1182
|
-
|
|
1285
|
+
const heading = opts.heading || 'Built-in skills';
|
|
1286
|
+
console.log(`${heading}: ${skills.length}\n`);
|
|
1183
1287
|
for (const skill of skills) {
|
|
1184
1288
|
const recipe = skill.studioRunRecipe ? ` [Studio Run: ${skill.studioRunRecipe}]` : '';
|
|
1185
1289
|
const source = skill.sourceMediaRequired ? ' [source media required]' : '';
|
|
@@ -1189,6 +1293,30 @@ function printBuiltInSkills(skills) {
|
|
|
1189
1293
|
console.log(` ${skill.name}${recipe}${source}${adapter}`);
|
|
1190
1294
|
if (skill.description) console.log(` ${String(skill.description).replace(/\s+/g, ' ').trim()}`);
|
|
1191
1295
|
}
|
|
1296
|
+
if (opts.hint !== false) {
|
|
1297
|
+
console.log('\nInspect and use a skill:');
|
|
1298
|
+
console.log(' makaron skills show <name> --built-in');
|
|
1299
|
+
console.log(' makaron chat --project auto --skill <name> "your request"');
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
function printBuiltInSkill(skill) {
|
|
1304
|
+
const description = String(skill.description || '').replace(/\s+/g, ' ').trim();
|
|
1305
|
+
console.log(`${skill.label || skill.name} (${skill.name})`);
|
|
1306
|
+
if (description) console.log(`\nPurpose:\n ${description}`);
|
|
1307
|
+
console.log('\nBest input:');
|
|
1308
|
+
console.log(` ${skill.inputHint || (skill.sourceMediaRequired ? 'Source media is required. Attach it with --video, --image, or --audio as appropriate.' : 'Start from a clear brief; attach source media when the request depends on existing footage or assets.')}`);
|
|
1309
|
+
if (skill.studioRunRecipe || skill.studioRunProfile) {
|
|
1310
|
+
console.log('\nWorkflow:');
|
|
1311
|
+
if (skill.studioRunRecipe) console.log(` Studio Run recipe: ${skill.studioRunRecipe}`);
|
|
1312
|
+
if (skill.studioRunProfile) console.log(` Profile: ${skill.studioRunProfile}`);
|
|
1313
|
+
}
|
|
1314
|
+
if (Array.isArray(skill.tags) && skill.tags.length) {
|
|
1315
|
+
console.log(`\nKeywords:\n ${skill.tags.join(', ')}`);
|
|
1316
|
+
}
|
|
1317
|
+
console.log('\nUse with chat:');
|
|
1318
|
+
const media = skill.sourceMediaRequired ? ' --video <file>' : '';
|
|
1319
|
+
console.log(` makaron chat --project auto${media} --skill ${skill.name} "describe the result you want"`);
|
|
1192
1320
|
}
|
|
1193
1321
|
|
|
1194
1322
|
function marketplaceSearchText(skill) {
|
|
@@ -1745,7 +1873,7 @@ Commands:
|
|
|
1745
1873
|
video script|create|status Video generation
|
|
1746
1874
|
music create|status Music generation
|
|
1747
1875
|
|
|
1748
|
-
admin Admin commands (skills, upload, set-admin)
|
|
1876
|
+
admin Admin commands (skills, credits, upload, set-admin)
|
|
1749
1877
|
|
|
1750
1878
|
Examples:
|
|
1751
1879
|
makaron chat --project auto "plan a launch poster"
|
|
@@ -1846,20 +1974,25 @@ function printHelp(topic, subtopic) {
|
|
|
1846
1974
|
} else if (topic === 'install-skill') {
|
|
1847
1975
|
console.log('Usage: makaron install-skill [--global] [--agent <agent>] [--yes]');
|
|
1848
1976
|
} else if (topic === 'skills') {
|
|
1849
|
-
if (subtopic === 'list') console.log('Usage: makaron skills list [--built-in] [--json]');
|
|
1850
|
-
else if (subtopic === 'search') console.log('Usage: makaron skills search <query> [--json]');
|
|
1851
|
-
else if (subtopic === 'show') console.log('Usage: makaron skills show <
|
|
1977
|
+
if (subtopic === 'list') console.log('Usage: makaron skills list [--built-in] [--all] [--json]');
|
|
1978
|
+
else if (subtopic === 'search') console.log('Usage: makaron skills search <query> [--built-in] [--all] [--json]');
|
|
1979
|
+
else if (subtopic === 'show') console.log('Usage: makaron skills show <id|label|name> [--built-in] [--json]');
|
|
1852
1980
|
else if (subtopic === 'install') console.log('Usage: makaron skills install <marketplace-id|label> [--json]');
|
|
1853
1981
|
else console.log(`Skill commands:
|
|
1854
|
-
skills list --built-in List
|
|
1982
|
+
skills list --built-in List user-facing built-in skills and what they do
|
|
1983
|
+
skills list --built-in --all Include internal/adapted helper skills
|
|
1855
1984
|
skills list List marketplace skills
|
|
1856
1985
|
skills search <query> Search marketplace skills
|
|
1986
|
+
skills search <query> --built-in Find a built-in skill by task or keyword
|
|
1857
1987
|
skills show <id|label> --built-in Show a built-in skill
|
|
1858
1988
|
skills show <id|label> Show a marketplace skill
|
|
1859
1989
|
skills install <id|label> Install a marketplace skill to your workspace
|
|
1860
1990
|
|
|
1861
1991
|
Use with chat:
|
|
1862
1992
|
makaron chat --project auto --skill <id|label> "your request"
|
|
1993
|
+
|
|
1994
|
+
Not sure which built-in skill to use? Start with:
|
|
1995
|
+
makaron skills list --built-in
|
|
1863
1996
|
`);
|
|
1864
1997
|
} else if (topic === 'materialize') {
|
|
1865
1998
|
console.log(`Usage: makaron materialize --project <id> (--media <N> | --snapshot <snapshotId> | --design-path <path> | --design-json <file|->) [--wait] [--publish|--no-publish] [--profile fast_720p|source] [--pick url|job_id|status]`);
|
|
@@ -1877,7 +2010,7 @@ Use with chat:
|
|
|
1877
2010
|
console.log('Usage: makaron analyze --video <file|url> ["question"]');
|
|
1878
2011
|
} else if (topic === 'video') {
|
|
1879
2012
|
if (subtopic === 'script') console.log('Usage: makaron video script --image <file> [--image <file>] [--lang en|zh] "direction"');
|
|
1880
|
-
else if (subtopic === 'create') console.log('Usage: makaron video create --script "..." [--image <url> ...] [--video <url> ...] [--audio <url> ...] [--duration 10] [--aspect 9:16] [--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3] [--operation generate|edit|extend] [--video-resolution auto|480p|720p|768p|1080p|2k|4k] [--keep-original-sound]');
|
|
2013
|
+
else if (subtopic === 'create') console.log('Usage: makaron video create --script "..." [--image <url> ...] [--video <url> ...] [--audio <url> ...] [--duration 10] [--aspect 9:16] [--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3|sync-lipsync-v3] [--operation generate|edit|extend] [--video-resolution auto|480p|720p|768p|1080p|2k|4k] [--keep-original-sound]');
|
|
1881
2014
|
else if (subtopic === 'status') console.log('Usage: makaron video status <taskId> | --snapshot <snapshotId> [--wait]');
|
|
1882
2015
|
else console.log(`Video commands:
|
|
1883
2016
|
video script --image <file> [--image <file>] "direction" Write video script
|
|
@@ -1885,6 +2018,7 @@ Use with chat:
|
|
|
1885
2018
|
video create --script "..." --video-model minimax-h3 MiniMax H3 text-to-video (default 768P)
|
|
1886
2019
|
video create --script "..." --image <url> [--duration 10] Submit video task
|
|
1887
2020
|
video create --script "..." --video <public-url> [--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|google-omni|minimax-h3] Edit/reference a video (Grok does not support video refs)
|
|
2021
|
+
video create --script "Use the supplied audio" --video <url> --audio <url> --video-model sync-lipsync-v3 Lip-sync exact replacement audio
|
|
1888
2022
|
video status <taskId> Check video status
|
|
1889
2023
|
video status --snapshot <snapshotId> [--wait] Check v2 video snapshot
|
|
1890
2024
|
`);
|
|
@@ -1900,6 +2034,7 @@ Use with chat:
|
|
|
1900
2034
|
else if (subtopic === 'skill-categories') console.log('Usage: makaron admin skill-categories [--json|add|update|delete] ...');
|
|
1901
2035
|
else if (subtopic === 'upload') console.log('Usage: makaron admin upload <local-file> <storage-path>');
|
|
1902
2036
|
else if (subtopic === 'fetch-skill') console.log('Usage: makaron admin fetch-skill <share-code|url>');
|
|
2037
|
+
else if (subtopic === 'add-credits') console.log('Usage: makaron admin add-credits <email-or-user-id> <credits> [--json]');
|
|
1903
2038
|
else if (subtopic === 'set-admin') console.log('Usage: makaron admin set-admin <email>');
|
|
1904
2039
|
else console.log(`Admin commands:
|
|
1905
2040
|
admin skills List all marketplace skills
|
|
@@ -1912,6 +2047,7 @@ Use with chat:
|
|
|
1912
2047
|
admin skill-categories delete <id> Delete a category
|
|
1913
2048
|
admin upload <file> <storage-path> Upload file to Storage
|
|
1914
2049
|
admin fetch-skill <code|url> Download skill from share link
|
|
2050
|
+
admin add-credits <user> <credits> Add credits by email or user ID
|
|
1915
2051
|
admin set-admin <email> Grant admin access to a user
|
|
1916
2052
|
`);
|
|
1917
2053
|
} else if (topic === 'register') {
|
|
@@ -2257,7 +2393,8 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2257
2393
|
uploadedTurnVideoCount += videoSnaps.length;
|
|
2258
2394
|
uploadedTurnMediaCount += videoSnaps.length;
|
|
2259
2395
|
} else {
|
|
2260
|
-
process.stderr.write(
|
|
2396
|
+
process.stderr.write(`❌ Failed to add videos to the project timeline: ${await res.text()}\n`);
|
|
2397
|
+
process.exit(1);
|
|
2261
2398
|
}
|
|
2262
2399
|
}
|
|
2263
2400
|
|
|
@@ -2346,7 +2483,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2346
2483
|
const res = await fetch(`${baseUrl}/api/agent/run/${runId}`, { headers });
|
|
2347
2484
|
if (!res.ok) { process.stderr.write(`Error ${res.status}: ${await res.text()}\n`); process.exit(1); }
|
|
2348
2485
|
let data = await res.json();
|
|
2349
|
-
|
|
2486
|
+
data = await reconcileRunWithProjectMedia(baseUrl, headers, data);
|
|
2350
2487
|
if (exportCompositions && data.status === 'completed') {
|
|
2351
2488
|
data = await exportAnimatedCompositionsFromRun(baseUrl, headers, data, { publish: publishExports, quiet: jsonOutput || !!pick });
|
|
2352
2489
|
}
|
|
@@ -2485,22 +2622,41 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2485
2622
|
|
|
2486
2623
|
if (sub === 'list') {
|
|
2487
2624
|
const builtIn = args.includes('--built-in');
|
|
2488
|
-
const
|
|
2625
|
+
const allBuiltIn = args.includes('--all');
|
|
2626
|
+
const fetchedSkills = builtIn ? await fetchBuiltInSkills(baseUrl) : await fetchMarketplaceSkills(baseUrl);
|
|
2627
|
+
const skills = builtIn && !allBuiltIn
|
|
2628
|
+
? fetchedSkills.filter(isDiscoverableBuiltInSkill)
|
|
2629
|
+
: fetchedSkills;
|
|
2489
2630
|
if (jsonOutput) console.log(JSON.stringify({ skills }, null, 2));
|
|
2490
|
-
else if (builtIn) printBuiltInSkills(skills
|
|
2631
|
+
else if (builtIn) printBuiltInSkills(skills, {
|
|
2632
|
+
heading: allBuiltIn ? 'All built-in skills' : 'Built-in skills available to use',
|
|
2633
|
+
});
|
|
2491
2634
|
else printMarketplaceSkills(skills);
|
|
2492
2635
|
} else if (sub === 'search') {
|
|
2493
|
-
const
|
|
2494
|
-
|
|
2636
|
+
const builtIn = args.includes('--built-in');
|
|
2637
|
+
const allBuiltIn = args.includes('--all');
|
|
2638
|
+
const query = args.filter((arg, index) => index > 1 && !['--json', '--built-in', '--all'].includes(arg)).join(' ').trim();
|
|
2639
|
+
if (!query) { console.error('Usage: makaron skills search <query> [--built-in] [--all] [--json]'); process.exit(1); }
|
|
2495
2640
|
const lowerQuery = query.toLowerCase();
|
|
2496
2641
|
const slugQuery = slugifySkill(query);
|
|
2497
|
-
const
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2642
|
+
const builtInQueryTokens = slugQuery.split('-').filter(Boolean);
|
|
2643
|
+
const skills = builtIn
|
|
2644
|
+
? (await fetchBuiltInSkills(baseUrl))
|
|
2645
|
+
.filter(skill => allBuiltIn || isDiscoverableBuiltInSkill(skill))
|
|
2646
|
+
.filter(skill => {
|
|
2647
|
+
const searchText = builtInSkillSearchText(skill);
|
|
2648
|
+
const slugText = slugifySkill(searchText);
|
|
2649
|
+
return searchText.includes(lowerQuery)
|
|
2650
|
+
|| (builtInQueryTokens.length > 0 && builtInQueryTokens.every(token => slugText.includes(token)));
|
|
2651
|
+
})
|
|
2652
|
+
: (await fetchMarketplaceSkills(baseUrl))
|
|
2653
|
+
.filter(skill => {
|
|
2654
|
+
const rawMatch = marketplaceSkillTokens(skill).some(token => token.includes(lowerQuery));
|
|
2655
|
+
const slugMatch = slugQuery ? marketplaceSearchText(skill).includes(slugQuery) : false;
|
|
2656
|
+
return rawMatch || slugMatch;
|
|
2657
|
+
});
|
|
2503
2658
|
if (jsonOutput) console.log(JSON.stringify({ skills }, null, 2));
|
|
2659
|
+
else if (builtIn) printBuiltInSkills(skills, { heading: `Built-in skill matches for "${query}"` });
|
|
2504
2660
|
else printMarketplaceSkills(skills);
|
|
2505
2661
|
} else if (sub === 'show') {
|
|
2506
2662
|
const identifier = args[2];
|
|
@@ -2512,7 +2668,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2512
2668
|
: findMarketplaceSkill(skills, identifier);
|
|
2513
2669
|
if (!skill) { console.error(`Skill not found: ${identifier}`); process.exit(1); }
|
|
2514
2670
|
if (jsonOutput) console.log(JSON.stringify(skill, null, 2));
|
|
2515
|
-
else if (builtIn)
|
|
2671
|
+
else if (builtIn) printBuiltInSkill(skill);
|
|
2516
2672
|
else printMarketplaceSkill(skill);
|
|
2517
2673
|
} else if (sub === 'install') {
|
|
2518
2674
|
const identifier = args[2];
|
|
@@ -2526,9 +2682,11 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2526
2682
|
else console.log(data.skillName);
|
|
2527
2683
|
} else {
|
|
2528
2684
|
console.log(`Skill commands:
|
|
2529
|
-
skills list --built-in List
|
|
2685
|
+
skills list --built-in List user-facing built-in skills and what they do
|
|
2686
|
+
skills list --built-in --all Include internal/adapted helper skills
|
|
2530
2687
|
skills list List marketplace skills
|
|
2531
2688
|
skills search <query> Search marketplace skills
|
|
2689
|
+
skills search <query> --built-in Find a built-in skill by task or keyword
|
|
2532
2690
|
skills show <id|label> --built-in Show a built-in skill
|
|
2533
2691
|
skills show <id|label> Show a marketplace skill
|
|
2534
2692
|
skills install <id|label> Install a marketplace skill to your workspace
|
|
@@ -2695,6 +2853,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2695
2853
|
const isSeedance25 = selectedVideoModel === 'seedance-2.5';
|
|
2696
2854
|
const isSeedanceModel = selectedVideoModel === 'seedance-fast' || selectedVideoModel === 'seedance-mini' || selectedVideoModel === 'seedance' || isSeedance25;
|
|
2697
2855
|
const isMinimaxH3 = selectedVideoModel === 'minimax-h3';
|
|
2856
|
+
const isSyncLipsync = selectedVideoModel === 'sync-lipsync-v3';
|
|
2698
2857
|
const supportsNativeTextToVideo = isSeedanceModel || isMinimaxH3;
|
|
2699
2858
|
if (!script || (!images.length && !videos.length && !audios.length && !supportsNativeTextToVideo)) {
|
|
2700
2859
|
console.error('Usage: makaron video create --script "..." [--image <url>] [--video <file|url>] [--audio <file|url>] [--duration 30] [--video-model seedance-2.5|minimax-h3]');
|
|
@@ -2706,6 +2865,10 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2706
2865
|
if (isMinimaxH3 && images.length > 9) { console.error('MiniMax H3 supports at most 9 image references.'); process.exit(1); }
|
|
2707
2866
|
if (isMinimaxH3 && videos.length > 3) { console.error('MiniMax H3 supports at most 3 video references.'); process.exit(1); }
|
|
2708
2867
|
if (isMinimaxH3 && audios.length > 3) { console.error('MiniMax H3 supports at most 3 audio references.'); process.exit(1); }
|
|
2868
|
+
if (isSyncLipsync && (images.length !== 0 || videos.length !== 1 || audios.length !== 1)) { console.error('Sync Lipsync v3 requires exactly one --video and one --audio, with no --image.'); process.exit(1); }
|
|
2869
|
+
if (isSyncLipsync && !/<<<audio_1>>>/i.test(script)) {
|
|
2870
|
+
script += '\nUse <<<audio_1>>> as the exact replacement soundtrack.';
|
|
2871
|
+
}
|
|
2709
2872
|
if (videoOperation && !['generate', 'edit', 'extend'].includes(videoOperation)) { console.error('--video-operation must be generate, edit, or extend.'); process.exit(1); }
|
|
2710
2873
|
if (extendDirection && !['forward', 'backward'].includes(extendDirection)) { console.error('--extend-direction must be forward or backward.'); process.exit(1); }
|
|
2711
2874
|
if (outputFormat && !['mp4', 'mov'].includes(outputFormat)) { console.error('--output-format must be mp4 or mov.'); process.exit(1); }
|
|
@@ -2715,8 +2878,9 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2715
2878
|
process.exit(1);
|
|
2716
2879
|
}
|
|
2717
2880
|
|
|
2718
|
-
|
|
2719
|
-
|
|
2881
|
+
let providerMaxDuration = isSeedance25 ? SEEDANCE25_MAX_VIDEO_REFERENCE_DURATION : MAX_VIDEO_PROVIDER_REFERENCE_DURATION;
|
|
2882
|
+
if (isSyncLipsync) providerMaxDuration = 60;
|
|
2883
|
+
const providerMaxPixels = isSyncLipsync || isMinimaxH3 ? Infinity : isSeedance25 ? SEEDANCE25_MAX_VIDEO_FRAME_PIXELS : MAX_VIDEO_FRAME_PIXELS;
|
|
2720
2884
|
const localImages = images.filter(image => !isHttpUrl(image));
|
|
2721
2885
|
if (localImages.length) {
|
|
2722
2886
|
const uploadedImages = await uploadImageFilesViaSignedUrl(baseUrl, headers, undefined, localImages);
|
|
@@ -2731,7 +2895,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2731
2895
|
maxDuration: providerMaxDuration,
|
|
2732
2896
|
durationTolerance: MAX_VIDEO_PROVIDER_REFERENCE_DURATION_TOLERANCE,
|
|
2733
2897
|
maxFramePixels: providerMaxPixels,
|
|
2734
|
-
maxFileSize: isSeedance25 ? 200 * 1024 * 1024 : MAX_VIDEO_UPLOAD_FILE_SIZE,
|
|
2898
|
+
maxFileSize: isSeedance25 || isSyncLipsync ? 200 * 1024 * 1024 : MAX_VIDEO_UPLOAD_FILE_SIZE,
|
|
2735
2899
|
...(selectedVideoModel === 'minimax-h3' ? {
|
|
2736
2900
|
allowedExtensions: ['mp4', 'mov'],
|
|
2737
2901
|
minSide: MINIMAX_H3_MIN_VIDEO_SIDE,
|
|
@@ -2757,7 +2921,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2757
2921
|
const audioUrls = [];
|
|
2758
2922
|
for (const audio of audios) {
|
|
2759
2923
|
if (isHttpUrl(audio)) { audioUrls.push(audio); continue; }
|
|
2760
|
-
const valid = validateAudioReferenceFile(audio, { maxDuration: isSeedance25 ? 30 : MAX_AUDIO_REFERENCE_DURATION });
|
|
2924
|
+
const valid = validateAudioReferenceFile(audio, { maxDuration: isSyncLipsync ? 60 : isSeedance25 ? 30 : MAX_AUDIO_REFERENCE_DURATION });
|
|
2761
2925
|
if (!valid.ok) { console.error(`❌ ${valid.error}`); process.exit(1); }
|
|
2762
2926
|
process.stderr.write(`🎵 Uploading ${path.basename(audio)}...\n`);
|
|
2763
2927
|
const uploaded = await uploadFileViaSignedUrl(baseUrl, headers, undefined, audio, valid.mime, { uploadKind: 'audio' });
|
|
@@ -2767,7 +2931,9 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2767
2931
|
// Standalone MCP tool (no project timeline write)
|
|
2768
2932
|
process.stderr.write('🎬 Submitting video...\n');
|
|
2769
2933
|
const resolvedOperation = videoOperation || (isSeedance25 && videoUrls.length ? 'edit' : 'generate');
|
|
2770
|
-
const vArgs =
|
|
2934
|
+
const vArgs = isSyncLipsync
|
|
2935
|
+
? { script, images, videoUrls, audioUrls, videoModel: selectedVideoModel, videoResolution }
|
|
2936
|
+
: isSeedance25
|
|
2771
2937
|
? { script, images, videoUrls, audioUrls, videoModel: selectedVideoModel, videoResolution, operation: resolvedOperation, extendDirection, outputFormat, generateAudio, contentFilter, webSearch }
|
|
2772
2938
|
: isMinimaxH3
|
|
2773
2939
|
? { script, images, videoUrls, audioUrls, videoModel: selectedVideoModel, videoResolution }
|
|
@@ -2778,7 +2944,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2778
2944
|
if (effectiveDuration) vArgs.duration = effectiveDuration;
|
|
2779
2945
|
if (aspectRatio) vArgs.aspectRatio = aspectRatio;
|
|
2780
2946
|
if (keepOriginalSound && videoUrls.length && !isSeedance25) vArgs.keepOriginalSound = true;
|
|
2781
|
-
const result = await callMcpTool(baseUrl, headers, videoUrls.length && !isSeedance25 && !isMinimaxH3 ? 'makaron_edit_video' : 'makaron_create_video', vArgs);
|
|
2947
|
+
const result = await callMcpTool(baseUrl, headers, videoUrls.length && !isSeedance25 && !isMinimaxH3 && !isSyncLipsync ? 'makaron_edit_video' : 'makaron_create_video', vArgs);
|
|
2782
2948
|
const text = result?.content?.find(c => c.type === 'text')?.text;
|
|
2783
2949
|
if (text) {
|
|
2784
2950
|
console.log(text);
|
|
@@ -2825,6 +2991,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2825
2991
|
video create --script "..." --video-model minimax-h3 MiniMax H3 text-to-video (default 768P)
|
|
2826
2992
|
video create --script "..." --image <url> [--duration 10] Submit video task
|
|
2827
2993
|
video create --script "..." --video <public-url> [--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|google-omni|minimax-h3] Edit/reference a video (Grok does not support video refs)
|
|
2994
|
+
video create --script "Use the supplied audio" --video <url> --audio <url> --video-model sync-lipsync-v3 Lip-sync exact replacement audio
|
|
2828
2995
|
video status <taskId> Check video status
|
|
2829
2996
|
video status --snapshot <snapshotId> [--wait] Check v2 video snapshot
|
|
2830
2997
|
`);
|
|
@@ -3030,6 +3197,31 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
3030
3197
|
if (!res.ok) { console.error(`Error ${res.status}:`, await res.text()); process.exit(1); }
|
|
3031
3198
|
console.log(`✅ ${email} is now admin`);
|
|
3032
3199
|
|
|
3200
|
+
} else if (sub === 'add-credits') {
|
|
3201
|
+
const user = args[2]?.trim();
|
|
3202
|
+
const credits = Number(args[3]);
|
|
3203
|
+
if (!user || !Number.isSafeInteger(credits) || credits <= 0) {
|
|
3204
|
+
console.error('Usage: makaron admin add-credits <email-or-user-id> <credits> [--json]');
|
|
3205
|
+
console.error('Credits must be a positive integer.');
|
|
3206
|
+
process.exit(1);
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
const res = await fetch(`${baseUrl}/api/admin/add-credits`, {
|
|
3210
|
+
method: 'POST',
|
|
3211
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
3212
|
+
body: JSON.stringify({ email: user, credits }),
|
|
3213
|
+
});
|
|
3214
|
+
const data = await res.json().catch(() => null);
|
|
3215
|
+
if (!res.ok) {
|
|
3216
|
+
console.error(`Error ${res.status}:`, data?.error || 'Failed to add credits');
|
|
3217
|
+
process.exit(1);
|
|
3218
|
+
}
|
|
3219
|
+
if (args.includes('--json')) {
|
|
3220
|
+
console.log(JSON.stringify(data));
|
|
3221
|
+
} else {
|
|
3222
|
+
console.log(`✅ Added ${credits} credits to ${user}. New balance: ${data.newBalance}`);
|
|
3223
|
+
}
|
|
3224
|
+
|
|
3033
3225
|
} else {
|
|
3034
3226
|
console.log(`Admin commands:
|
|
3035
3227
|
admin skills List all marketplace skills
|
|
@@ -3042,6 +3234,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
3042
3234
|
admin skill-categories delete <id> Delete a category
|
|
3043
3235
|
admin upload <file> <storage-path> Upload file to Storage
|
|
3044
3236
|
admin fetch-skill <code|url> Download skill from share link
|
|
3237
|
+
admin add-credits <user> <credits> Add credits by email or user ID
|
|
3045
3238
|
admin set-admin <email> Grant admin access to a user
|
|
3046
3239
|
`);
|
|
3047
3240
|
}
|
package/package.json
CHANGED
package/skills/makaron/SKILL.md
CHANGED
|
@@ -109,6 +109,33 @@ Returns immediately:
|
|
|
109
109
|
| Beat-sync video from audio | `npx makaron-cli chat --project auto --audio beat.mp3 "use Seedance Mini at 480p to make a beat-synced video"` |
|
|
110
110
|
| Create motion design | `npx makaron-cli chat --project <id> "make an animated Instagram story with this image"` |
|
|
111
111
|
|
|
112
|
+
### Built-in production skills
|
|
113
|
+
|
|
114
|
+
When the request names a production format or the correct workflow is unclear,
|
|
115
|
+
discover the current built-in skills before starting. Do not guess a skill slug
|
|
116
|
+
from memory: the server list is the source of truth.
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Short list of callable/discoverable production skills and their purpose
|
|
120
|
+
npx makaron-cli skills list --built-in
|
|
121
|
+
|
|
122
|
+
# Search by task, format, or keyword
|
|
123
|
+
npx makaron-cli skills search "talking head captions" --built-in
|
|
124
|
+
|
|
125
|
+
# Inspect input requirements, workflow, keywords, and exact invocation
|
|
126
|
+
npx makaron-cli skills show talking-head --built-in
|
|
127
|
+
|
|
128
|
+
# Use the exact slug returned by list/show
|
|
129
|
+
npx makaron-cli chat --project auto --video talk.mp4 \
|
|
130
|
+
--skill talking-head -b "remove false starts, add synced captions and useful B-roll"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Use `--all` only when debugging adapters or looking for an internal helper Skill.
|
|
134
|
+
For ordinary creative work, choose from the default built-in list. A named
|
|
135
|
+
destination takes priority over a generic source workflow: for example,
|
|
136
|
+
explicit TikTok/Douyin work uses `tiktok-video`; ordinary speech-led cleanup
|
|
137
|
+
uses `talking-head`; broader mixed-footage editing uses `source-video-studio`.
|
|
138
|
+
|
|
112
139
|
### Marketplace skills
|
|
113
140
|
|
|
114
141
|
Use marketplace skills when the user asks for a named Makaron effect, template, or skill such as "Football Captain", "足球队长", "World Cup MVP", or a marketplace UUID.
|
|
@@ -135,7 +162,7 @@ npx makaron-cli chat --project auto \
|
|
|
135
162
|
|
|
136
163
|
`--skill` accepts an installed skill name, a marketplace UUID, or a unique marketplace label. Marketplace search matches every localized title, every localized default prompt, and category ids. If a marketplace skill is matched, the CLI installs or reuses it and sends `[Active skill: <installed-skill-name>]` to Makaron Agent. Do not call admin skill commands for ordinary users. There is intentionally no user-facing CLI delete command for marketplace skills.
|
|
137
164
|
|
|
138
|
-
For an explicitly authorized
|
|
165
|
+
For an explicitly authorized administrator, `admin add-credits <email-or-user-id> <positive-integer> [--json]` adds credits to a user. Marketplace administrators can use `admin skills` to see category assignment and 4-locale title/prompt completeness, while `admin skill-categories` supports list/add/update/delete. New skills must include `en`, `zh`, `zh-Hant`, and `ja` in both `labels` and `prompts`, plus at least one existing `categories` id. Partial localized updates are safely merged server-side.
|
|
139
166
|
|
|
140
167
|
### With additional images (existing project)
|
|
141
168
|
|
|
@@ -184,7 +211,7 @@ npx makaron-cli chat --project <id> --video clip1.mp4 --video clip2.mp4 -b "comb
|
|
|
184
211
|
npx makaron-cli chat --project auto --video https://example.com/dance.mp4 -b "extend this to 15 seconds"
|
|
185
212
|
```
|
|
186
213
|
|
|
187
|
-
Supported formats: MP4, MOV, WebM. CLI local video uploads support max 50MB, max
|
|
214
|
+
Supported formats: MP4, MOV, WebM. CLI local video uploads support max 50MB, max 900s (15 minutes) with 1s metadata tolerance, and <=1080p / 2,086,876 frame pixels. The frontend can transcode larger videos before upload; the CLI uploads directly to Storage and rejects videos above those limits. Videos are uploaded to the project timeline. The Agent can analyze scenes, edit content, compose multiple clips, extend duration, and add effects — all via natural language. Seedance reference-video limits remain provider-specific, so longer uploaded videos should be split/prepared by the agent before model submission; Kling remains the base/direct edit path.
|
|
188
215
|
|
|
189
216
|
Use `chat --project <id|auto> --video ...` for any project/timeline video work. Direct video commands are standalone raw-tool calls.
|
|
190
217
|
|
|
@@ -300,7 +327,7 @@ npx makaron-cli video status <taskId>
|
|
|
300
327
|
npx makaron-cli chat --project <id|auto> --video input.mp4 -b "make it funny"
|
|
301
328
|
```
|
|
302
329
|
|
|
303
|
-
Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to the selected model limit), `--video <file|url>` and `--audio <file|url>` (repeatable where supported), `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3`, `--video-resolution auto|480p|720p|768p|1080p|2k|4k`. Default model is `seedance-fast`. SeeDance accepts native text-to-video with no image and integer output duration 4-15s (default 5s); `seedance-mini` supports 480p/720p and is best for cheaper drafts/multi-size tests; MiniMax H3 accepts native text-to-video, 4-15s output, public 768p/2k resolution, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. H3 defaults to 768p; request 2k explicitly for maximum/final quality. Kling supports 5-15s; Grok 1.5 supports 1-15s single-image-to-video only; Gemini Omni supports 3-10s fast 720p image/video generation and editing with native generated audio, including up to 6 image references when no video reference is provided. For `--video-model grok`, forced `--aspect` is ignored to avoid xAI stretching the source image; pad/create the image at the target shape first or use another model.
|
|
330
|
+
Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to the selected model limit), `--video <file|url>` and `--audio <file|url>` (repeatable where supported), `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3|sync-lipsync-v3`, `--video-resolution auto|480p|720p|768p|1080p|2k|4k`. Default model is `seedance-fast`. SeeDance accepts native text-to-video with no image and integer output duration 4-15s (default 5s); `seedance-mini` supports 480p/720p and is best for cheaper drafts/multi-size tests; MiniMax H3 accepts native text-to-video, 4-15s output, public 768p/2k resolution, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. `sync-lipsync-v3` requires exactly one video plus one MP3/WAV and preserves that replacement audio while aligning the mouth. H3 defaults to 768p; request 2k explicitly for maximum/final quality. Kling supports 5-15s; Grok 1.5 supports 1-15s single-image-to-video only; Gemini Omni supports 3-10s fast 720p image/video generation and editing with native generated audio, including up to 6 image references when no video reference is provided. For `--video-model grok`, forced `--aspect` is ignored to avoid xAI stretching the source image; pad/create the image at the target shape first or use another model.
|
|
304
331
|
|
|
305
332
|
Seedance 2.5 uses `--video-model seedance-2.5` and supports 4-30s at 480p/720p, up to 30 images + 10 videos + 10 audios, repeatable local/URL references, `--video-operation generate|edit|extend`, `--extend-direction`, `--output-format mp4|mov`, and `--web-search`. The Evolink route does not currently expose 4K output.
|
|
306
333
|
|
|
@@ -351,6 +378,7 @@ type CompletionAction = {
|
|
|
351
378
|
3. Stop when `status` is `"completed"`, `"failed"`, or `"aborted"`
|
|
352
379
|
4. Top-level `status: "completed"` means ALL artifacts are ready (including rendered videos)
|
|
353
380
|
5. If an async video fails, top-level `status` is `"failed"` and the failed video may include `completion_actions` for a safe retry or diagnosis. Agents can surface these as the next user-confirmed step.
|
|
381
|
+
6. `responses get --wait` reconciles pending video output against completed Project Media with the same `snapshot_id` or `task_id`. A lagging Run row therefore does not block delivery after the durable project video is ready.
|
|
354
382
|
|
|
355
383
|
## Exit Codes
|
|
356
384
|
|