@starreel/mcp 0.1.97 → 0.1.99
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/SKILL.md +47 -3
- package/dist/tools/guide-data.js +8 -2
- package/dist/tools/produce.js +73 -4
- package/openapi.json +336 -7
- package/package.json +1 -1
- package/server.json +2 -2
package/SKILL.md
CHANGED
|
@@ -39,7 +39,9 @@ create_drama → set_script(raw) → rewrite_script(AI draft, user may edit)
|
|
|
39
39
|
→ scene-images(empty-set plates = the background anchor — every shot in a scene
|
|
40
40
|
anchors on its plate; skip it and each scene's FIRST shot has no background
|
|
41
41
|
anchor at all, and the backdrop drifts from shot to shot)
|
|
42
|
-
→ frames
|
|
42
|
+
→ frames(first frames → tail_frame_plan → tail frames)
|
|
43
|
+
→ seams(chain_frames dry_run → confirm → run; per-shot fixes via chain_shot_from*)
|
|
44
|
+
→ [review_frames] → videos → generate_tts(voiceover) → compose_episode → final cut (.mp4 link)
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
The three `[review_*]` steps are free and **enforced** — see discipline 11.
|
|
@@ -293,6 +295,36 @@ content that will be rejected.
|
|
|
293
295
|
**9.4%** of the time versus **40.2%** with one. `generate_shot_frame` does accept
|
|
294
296
|
`allow_missing_terminal: true` for the rare shot that genuinely should barely change,
|
|
295
297
|
but reach for the text fix first.
|
|
298
|
+
**Then join the seams, before `review_frames`.** Each shot's first frame should pick
|
|
299
|
+
up where the previous shot's last frame left off; otherwise the cut is a visible jump.
|
|
300
|
+
The platform joins them automatically only when a batch runs from the website —
|
|
301
|
+
frames generated through this API (`generate_frames` / `generate_shot_frame`) do not
|
|
302
|
+
trigger it, so an API-driven episode has usually never been joined.
|
|
303
|
+
`get_storyboards` reports every shot's `seam_state` (the seam between it and the shot
|
|
304
|
+
before it): act on `unchained` (marked continuous, never joined) and `broken` (joined,
|
|
305
|
+
but the platform's continuity check says it doesn't hold — `seam_failed_dims` names
|
|
306
|
+
which of characters / wardrobe / props / lighting / scene broke). Leave `intended`
|
|
307
|
+
(hard cut, scene or time change, big shot-size jump, insert shot, customer upload) and
|
|
308
|
+
`unknown` (never evaluated — not a defect) alone.
|
|
309
|
+
Whole episode: `chain_frames` with `dry_run: true` first (free — no writes, no images)
|
|
310
|
+
returns `planned_copy` / `planned_reframe` / `estimated_points`. *copy* makes the
|
|
311
|
+
shot's first frame the previous shot's last frame (free, but the shot inherits the
|
|
312
|
+
previous shot's framing); *reframe* regenerates the first frame anchored on that last
|
|
313
|
+
frame (one image per seam, keeps the shot's own framing). Tell the customer, then run
|
|
314
|
+
it without `dry_run`. Seams that are already joined — the first frame *is* the
|
|
315
|
+
previous last frame, or a reframe landed on the previous shot's **current** last
|
|
316
|
+
frame — are left out of the plan, so running it again does not re-bill them; a seam
|
|
317
|
+
reappears only when the previous shot's last frame was regenerated afterwards (then it
|
|
318
|
+
really is broken). To fix individual seams: `chain_shot_from_prev` (free,
|
|
319
|
+
same-framing continuation) or
|
|
320
|
+
`quote_chain_shot_from` → `chain_shot_from` with `mode: "reframe"` (framing changes).
|
|
321
|
+
If the previous shot's video is already done and the customer does not want to touch
|
|
322
|
+
this shot's first frame, `quote_align_prev_shot` → `align_prev_shot` regenerates the
|
|
323
|
+
**previous** shot's video so it ends on this shot's opening frame (one video).
|
|
324
|
+
Any shot whose first frame changes gets its video marked for regeneration.
|
|
325
|
+
`review_frames` flags the two actionable states as `seam_unchained` / `seam_broken`
|
|
326
|
+
(warnings — they do not block `generate_videos`, but this is the cheapest point to fix
|
|
327
|
+
them: the video is generated from the first frame).
|
|
296
328
|
**Image model**: images use a drama-level model (default **ChatGPT Image 2.5
|
|
297
329
|
Flare** = `gpt-image-2.5-flare`), set via `create_drama` /
|
|
298
330
|
`update_project_settings` field `image_model` for one consistent look across
|
|
@@ -790,6 +822,11 @@ Four distinct causes; they need **opposite** fixes, so identify the family first
|
|
|
790
822
|
|
|
791
823
|
### "切太快" / "一个镜头里画面跳来跳去"
|
|
792
824
|
|
|
825
|
+
If the jump is *between* two shots (the picture changes abruptly at the cut), look at
|
|
826
|
+
`seam_state` in `get_storyboards` first — `unchained` / `broken` on that shot means the
|
|
827
|
+
two frames were never joined, and the fix is in the frames (see the seam step under the
|
|
828
|
+
disciplines), not in the edit.
|
|
829
|
+
|
|
793
830
|
Run **`scan_intra_shot_cuts`** (free) before touching anything. What a viewer
|
|
794
831
|
perceives as cutting speed is *shot seams + cuts the vendor made inside a single
|
|
795
832
|
shot*, and the second half is invisible in the shot list, in the timeline, and
|
|
@@ -973,7 +1010,9 @@ to close") tells the vendor to fit that entire sequence into each 3-second shot.
|
|
|
973
1010
|
or `enabled: false` means the user has to switch it on in the drama settings.
|
|
974
1011
|
- **Shots → video**: `quote/generate_storyboards`, `get_storyboards`,
|
|
975
1012
|
`quote/generate_frames`, `tail_frame_plan` (free — which shots need their own
|
|
976
|
-
last frame), `chain_frames
|
|
1013
|
+
last frame), `chain_frames` (`dry_run: true` first), `chain_shot_from_prev` (free),
|
|
1014
|
+
`quote_chain_shot_from` / `chain_shot_from`, `quote_align_prev_shot` / `align_prev_shot`,
|
|
1015
|
+
`quote/generate_videos`
|
|
977
1016
|
- **Audio**: `generate_tts` (required before final cut), `clone_voice`,
|
|
978
1017
|
`design_voice` → `get_voice_design` → `save_designed_voice` (no sample needed),
|
|
979
1018
|
`speak_with_voice`, `set_character_voice`, `list_voices`, `delete_voice`,
|
|
@@ -989,7 +1028,12 @@ to close") tells the vendor to fit that entire sequence into each 3-second shot.
|
|
|
989
1028
|
separate hold). `rework.video` = second-and-later successful videos of the
|
|
990
1029
|
same shot. `account_level` = voice clones / designs / auditions that belong to
|
|
991
1030
|
no drama — listed separately, **not** in the drama's total. Build a cost
|
|
992
|
-
write-up from this, not from your own tally.
|
|
1031
|
+
write-up from this, not from your own tally. `get_cost_estimate` adds what is
|
|
1032
|
+
still to be made: its `already_spent_points` is the same ledger number, split
|
|
1033
|
+
across `breakdown[].done_points` (text spend is one combined `text_spent` row —
|
|
1034
|
+
the ledger can't tell rewrite from storyboarding). If `spent_source` is
|
|
1035
|
+
`usage_mirror` (also on `get_budget_status`), the ledger was unreachable and the
|
|
1036
|
+
number is a low fallback without text/music — say so, or retry later.
|
|
993
1037
|
- **Every platform cut is versioned automatically.** Each `compose_episode` /
|
|
994
1038
|
`rerender_episode` / multi-aspect render registers a `source=platform` entry in
|
|
995
1039
|
`list_deliveries`: file sha256, and a manifest of what that render actually
|
package/dist/tools/guide-data.js
CHANGED
|
@@ -217,7 +217,7 @@ export const PIPELINE = [
|
|
|
217
217
|
},
|
|
218
218
|
{
|
|
219
219
|
step: '7 出帧(镜头图)',
|
|
220
|
-
tools: ['run_precheck(免费,揪出必被厂商拒的镜)', 'quote_frames', 'generate_frames', 'tail_frame_plan(免费,首帧出完必调)', 'quote_shot_frame', 'generate_shot_frame(单镜重生)', 'chain_frames', 'upload_shot_frame'],
|
|
220
|
+
tools: ['run_precheck(免费,揪出必被厂商拒的镜)', 'quote_frames', 'generate_frames', 'tail_frame_plan(免费,首帧出完必调)', 'quote_shot_frame', 'generate_shot_frame(单镜重生)', 'chain_frames(先 dry_run:true 看计划与预估)', 'chain_shot_from_prev(免费,单道接缝)', 'quote_chain_shot_from', 'chain_shot_from', 'quote_align_prev_shot', 'align_prev_shot', 'upload_shot_frame'],
|
|
221
221
|
billing: '报价确认后扣点',
|
|
222
222
|
gate: 'review_frames(镜头图审查;免费;generate_videos 前必过)',
|
|
223
223
|
note: '★出帧是**两趟**:generate_frames 默认只出首帧,首帧出完必须调一次免费的 `tail_frame_plan` ' +
|
|
@@ -225,7 +225,12 @@ export const PIPELINE = [
|
|
|
225
225
|
'生产实测 32 集里 30 集整集只出了首帧,其中 23 集一路出完了视频;那些镜出视频时只有首帧一个锚,末态由模型自由发挥。' +
|
|
226
226
|
'pending=还在生成,别重复调 `generate_frames`(重复扣费)。' +
|
|
227
227
|
'★开跑前用 `get_pipeline_status` 核对 generate_scene_images 的 completed/total——缺基板照样能出帧,' +
|
|
228
|
-
'但背景从每个场景的首镜起就开始漂;`review_storyboards` 也会把缺口报成 scene_plate_missing。'
|
|
228
|
+
'但背景从每个场景的首镜起就开始漂;`review_storyboards` 也会把缺口报成 scene_plate_missing。' +
|
|
229
|
+
'★首尾帧补齐后、出视频前**接缝**:逐镜出帧不会触发平台的自动帧链,镜与镜之间多半没接过。' +
|
|
230
|
+
'`get_storyboards` 看每镜 seam_state(unchained=标了连续却没接、broken=接过没接上),' +
|
|
231
|
+
'整集用 `chain_frames` 先 dry_run:true 报计划与预估(copy 免费、reframe 每道一张图)、客户确认后执行——' +
|
|
232
|
+
'已接好的缝不进计划,重复执行不重复扣费;只补个别缝用 `chain_shot_from_prev`(免费,同景别延续)' +
|
|
233
|
+
'或 `chain_shot_from` mode=reframe(报价后执行,保景别)。`review_frames` 会把两类缝报成 seam_unchained / seam_broken。',
|
|
229
234
|
},
|
|
230
235
|
{
|
|
231
236
|
step: '8 出视频',
|
|
@@ -315,6 +320,7 @@ export const COMMON_REQUESTS = [
|
|
|
315
320
|
{ customer_says: '换了定妆图 / 换脸后镜头没变', do: '`set_character_portrait` 响应里的 stale_frames 逐镜 `generate_shot_frame`,再重生视频。' },
|
|
316
321
|
{ customer_says: '图片一直没出来', do: '`get_storyboards` 看 frame_status:pending=在生成(每张几十秒到数分钟、整集十几分钟),别重复调 `generate_frames`;failed 才是失败,读 fail_reason / fail_hint。' },
|
|
317
322
|
{ customer_says: '预算多少 / 怎么更便宜', do: '各步 quote_* + `get_cost_estimate`;降本:hailuo-3(约 1/3)或 wan3.0(约 4 折,仅风格化/空镜/产品镜,写实真人绝不选)+ 草稿期低分辨率。' },
|
|
323
|
+
{ customer_says: '镜头之间接不上 / 画面跳 / 衔接不顺', do: '`get_storyboards` 看 seam_state:unchained / broken 才要修(unknown 是系统没判、intended 是有意切换,都别动)。还没出视频:整集 `chain_frames`(先 dry_run),单道同景别 `chain_shot_from_prev`(免费)、景别有变化 `quote_chain_shot_from` → `chain_shot_from` mode=reframe。上一镜视频已出好、不想动本镜首帧:`quote_align_prev_shot` → `align_prev_shot`(重生上一镜视频)。改了首帧的镜视频要重生。' },
|
|
318
324
|
{ customer_says: '成片里话没说完 / 切太快', do: '先 `scan_dialogue_coverage` / `scan_intra_shot_cuts` 定病因,再按 qa_tools 的 then 修;别默认去加长镜头。' },
|
|
319
325
|
{ customer_says: '我想自己剪', do: '`export_handoff_pack` + `get_handoff_toolchain`,不走 `compose_episode`。' },
|
|
320
326
|
{ customer_says: '要配音 / 不要视频原声', do: '`update_project_settings` use_clip_audio=false → `assign_voices` → `generate_tts` → `compose_episode`。' },
|
package/dist/tools/produce.js
CHANGED
|
@@ -544,7 +544,14 @@ export function registerProduceTools(server, client) {
|
|
|
544
544
|
'(presence=on_screen 在画面 / voice_only 只有声音、不进画面)、scene_id、prop_ids、active_wardrobe_id。' +
|
|
545
545
|
'出图注入谁的定妆图/哪张场景图/哪些道具图由这几项决定;角色名对照 get_characters、道具名对照 get_props。' +
|
|
546
546
|
'改绑用 update_shot 的 character_ids(★全量覆盖,先从这里读现值再改,漏传即解绑)与 character_presence;' +
|
|
547
|
-
'改完再读一次本工具核对。character_bindings 缺席 = 这次没读到(不是没绑),空数组才是没绑。'
|
|
547
|
+
'改完再读一次本工具核对。character_bindings 缺席 = 这次没读到(不是没绑),空数组才是没绑。' +
|
|
548
|
+
'★每镜带 **seam_state**(本镜与上一镜的镜间接缝,与官网帧时间线同一判据):' +
|
|
549
|
+
'ok=已续接(首帧就是上镜尾帧,或平台做过首尾帧衔接) / unchained=标了连续却从没接过 / ' +
|
|
550
|
+
'broken=接过但没接上(seam_failed_dims 给出哪几维不连续:characters/wardrobe/props/lighting/scene) / ' +
|
|
551
|
+
'intended=有意切换(硬切/换场/时间跳跃/景别大跳/插入镜/外部上传帧),不用管 / missing=两侧帧没齐 / ' +
|
|
552
|
+
'unknown=没标意图也没接过(系统没判,不是有问题) / na=首镜或旁白卡。' +
|
|
553
|
+
'seam_audit_status=pending 表示已接、平台的衔接审计还没出结论(若本镜 frame_status=failed,说明衔接那次重生没出成,缝其实没接上)。' +
|
|
554
|
+
'出视频前只需处理 unchained 与 broken:整集用 chain_frames(先 dry_run),单道用 chain_shot_from_prev / chain_shot_from。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/storyboards`)));
|
|
548
555
|
// ---------- 在途运行状态(免费):区分「还在跑」和「已经死了」----------
|
|
549
556
|
server.tool('get_run_status', '(★免费·长耗时操作后必用)查这一集当前有没有 agent 正在跑。' +
|
|
550
557
|
'rewrite_script / extract_assets / generate_storyboards 都是**分钟级**后台任务,' +
|
|
@@ -645,7 +652,10 @@ export function registerProduceTools(server, client) {
|
|
|
645
652
|
server.tool('review_frames', '【第③道硬闸·免费】审查镜头图片层:角色身份锚覆盖(缺定妆图的角色在镜头里必漂)、出图失败率、' +
|
|
646
653
|
'孤儿角色变体、场景图被人物污染。★generate_videos 之前必须先跑本工具——出视频是全链最贵的一步,' +
|
|
647
654
|
'拿着漂移的首帧整集出视频是最典型的废片形态。按 findings.action 修完(多为 generate_character_portraits / ' +
|
|
648
|
-
'generate_shot_frame 单镜重生)再复审。'
|
|
655
|
+
'generate_shot_frame 单镜重生)再复审。' +
|
|
656
|
+
'★还会报**镜间接缝**(warning,不拦):code=seam_unchained(标了连续却从没做过首尾帧衔接)/' +
|
|
657
|
+
'seam_broken(接过但没接上),shots 是「与上一镜的缝有问题」的那一镜。出视频前修最便宜——视频按首帧生成,' +
|
|
658
|
+
'首帧与上镜尾帧对不上,成片就是一次跳切。修法看 action(整集 chain_frames 先 dry_run;单道 chain_shot_from_prev / chain_shot_from)。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/frames`)));
|
|
649
659
|
server.tool('review_all', '(推荐·免费)三层一次跑完的整体体检:剧本+分镜+镜头图片。开工前摸底、交付前复查用。' +
|
|
650
660
|
'★它**不发 review_token** —— 进收费步前仍需对应层的 review_script / review_storyboards / review_frames 各跑一次' +
|
|
651
661
|
'(闸认的是「针对当前产出物刚审过」,不是「审过一次」)。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/all`)));
|
|
@@ -1409,7 +1419,13 @@ export function registerProduceTools(server, client) {
|
|
|
1409
1419
|
'\n· rework.video:同一镜第 2 次起的成功出片(返工);出图不计(首帧/尾帧/best-of-N 候选本来就是同镜多张)。' +
|
|
1410
1420
|
'\n· account_level:音色库克隆/设计/试听等**不属于任何一部剧**的语音扣费,单列、counted_in_drama=false,不计入本剧。' +
|
|
1411
1421
|
'\n· available=false:账本暂时不可达,不给数字(不拿估算冒充),稍后重试。', { drama_id: z.number().int().positive() }, async ({ drama_id }) => jsonResult(await client.produceGet(`/dramas/${drama_id}/bill`)));
|
|
1412
|
-
server.tool('get_cost_estimate', '
|
|
1422
|
+
server.tool('get_cost_estimate', '查一部剧的整体成本(点数):已花费 + 还没做的部分的待花费区间 + 分类明细。免费。' +
|
|
1423
|
+
'already_spent_points 与 get_budget_status 的 spent、网页「本剧已花费」同源(平台扣费账本净额,已减退款),是同一个数。' +
|
|
1424
|
+
'spent_source=usage_mirror 表示账本暂不可达、回退到本地镜像(偏少,不含文本/配乐),向客户报数时须注明,稍后重试即恢复;spent_note 是口径说明。' +
|
|
1425
|
+
'breakdown 各行 done_points 之和 = already_spent_points:账本分不出文本用在改写/拆镜/补全/提取哪一步,' +
|
|
1426
|
+
'文本已花费合计只在 kind=text_spent 一行(text / text_rewrite 行的 done_points 恒为 0,别报成「文本没花钱」;回退时没有 text_spent 行);' +
|
|
1427
|
+
'配乐、声音克隆等没有单列预估的类别在 other_spent(note 列出构成)。total = 已花费 + 待花费。' +
|
|
1428
|
+
'★同样不含账号级语音(音色库克隆/设计/试听),核账用 get_drama_bill。', { drama_id: z.number().int().positive() }, async ({ drama_id }) => jsonResult(await client.produceGet(`/dramas/${drama_id}/cost-estimate`)));
|
|
1413
1429
|
server.tool('get_budget_status', '查一部剧的预算状态(预算/已花费/剩余)。免费。' +
|
|
1414
1430
|
'spent 与网页「本剧已花费」同源(平台扣费账本净额,已减退款),by_kind 为按类分项(ai_image/ai_video/ai_text/ai_music/tts_local…)。' +
|
|
1415
1431
|
'spent_source=usage_mirror 表示账本暂不可达、回退到本地镜像(偏少,不含文本/配乐),向客户报数时须注明。' +
|
|
@@ -1550,7 +1566,60 @@ export function registerProduceTools(server, client) {
|
|
|
1550
1566
|
server.tool('get_color_scripts', '读该剧已生成的色彩脚本(全片配色情绪)。generate_color_script 生成、此工具读取。免费。', { drama_id: z.number().int().positive() }, async ({ drama_id }) => jsonResult(await client.produceGet(`/dramas/${drama_id}/color-scripts`)));
|
|
1551
1567
|
server.tool('get_motion_templates', '读该剧已有的动作模板(运镜/动作预设)。generate_motion_templates 生成、此工具读取。免费。', { drama_id: z.number().int().positive() }, async ({ drama_id }) => jsonResult(await client.produceGet(`/dramas/${drama_id}/motion-templates`)));
|
|
1552
1568
|
// ========== P2 · 连续性 / 场景组 / 多画幅 ==========
|
|
1553
|
-
server.tool('chain_frames', '整集首尾帧接力链:让每镜首帧承接上镜尾帧,镜间画面连续(比各镜独立出帧更顺)
|
|
1569
|
+
server.tool('chain_frames', '整集首尾帧接力链:让每镜首帧承接上镜尾帧,镜间画面连续(比各镜独立出帧更顺)。' +
|
|
1570
|
+
'★何时调:首帧出完、tail_frame_plan 要的尾帧也补完之后,review_frames / generate_videos 之前。' +
|
|
1571
|
+
'平台只在官网批量出帧结束时自动跑一次;逐镜出帧(generate_frames / generate_shot_frame)的集多半从没接过——' +
|
|
1572
|
+
'get_storyboards 的 seam_state=unchained 就是这种缝。\n' +
|
|
1573
|
+
'★先 dry_run:true(免费,不写库不出图):回 planned_copy / planned_reframe / estimated_points / needs_last_frame。' +
|
|
1574
|
+
'copy=本镜首帧直接换成上镜尾帧(免费,但本镜景别会变成和上镜一样);reframe=以上镜尾帧为锚按本镜画面描述重生首帧' +
|
|
1575
|
+
'(每道一张图,保景别)。把计划和 estimated_points 告诉客户,确认后**不带 dry_run** 再调一次执行(按用量后付)。\n' +
|
|
1576
|
+
'★平台自己判哪道缝该接:有意切换(换场/时间跳跃/换装/插入镜)、已出视频的镜、已经接好的缝都会跳过——' +
|
|
1577
|
+
'「已接好」= 首帧就是上镜尾帧,或 reframe 接在上镜**当前**尾帧上,所以重复执行不会重复扣费。' +
|
|
1578
|
+
'上镜尾帧后来被重生过的缝会重新出现在计划里,那道缝确实断了。只补个别缝用 chain_shot_from_prev / chain_shot_from。' +
|
|
1579
|
+
'执行后改了首帧的镜若已有视频会被标为待重生。执行完用 get_storyboards 核对 seam_state。', {
|
|
1580
|
+
episode_id: z.number().int().positive(),
|
|
1581
|
+
dry_run: z.boolean().optional().describe('true=只看计划与预估(免费,推荐先调一次);不传=真执行'),
|
|
1582
|
+
}, async ({ episode_id, dry_run }) => jsonResult(await client.producePost(`/episodes/${episode_id}/chain-frames`, dry_run ? { dry_run: true } : {})));
|
|
1583
|
+
// ---------- 单道接缝修复(帧时间线「接上一镜」「对齐上一镜」的门面版) ----------
|
|
1584
|
+
server.tool('chain_shot_from_prev', '(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图。' +
|
|
1585
|
+
'★适用:两镜是同一机位、同一景别的延续(seam_state=unchained/broken 且本镜本来就该和上镜一个构图)。' +
|
|
1586
|
+
'★别用于景别有变化的缝(全景→近景等):那会把本镜的景别设计冲掉,且后续出图可能被判「与设计不符」——' +
|
|
1587
|
+
'这种缝用 chain_shot_from 的 mode=reframe。本镜已有视频的会被标为待重生。' +
|
|
1588
|
+
'本镜首帧若已被客户定稿(first_frame_pinned)会被拒;客户明确同意覆盖才传 force:true。', {
|
|
1589
|
+
storyboard_id: z.number().int().positive().describe('要改首帧的那一镜(缝的右侧)'),
|
|
1590
|
+
force: z.boolean().optional().describe('仅当客户明确同意覆盖已定稿的首帧时传 true'),
|
|
1591
|
+
}, async ({ storyboard_id, force }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/chain-from-prev`, force ? { force: true } : {})));
|
|
1592
|
+
server.tool('quote_chain_shot_from', '(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价、经客户确认。' +
|
|
1593
|
+
'回 quote_id / estimated_points;quote_id 一次性、只对这一镜有效。mode=copy 不需要报价。', { storyboard_id: z.number().int().positive().describe('要重生首帧的那一镜') }, async ({ storyboard_id }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/chain-from/quote`)));
|
|
1594
|
+
server.tool('chain_shot_from', '把同一集**任一镜**的首帧或尾帧接为本镜首帧。两种落法:\n' +
|
|
1595
|
+
'· mode=copy(默认,免费):本镜首帧直接换成源帧,画面逐像素相同——适合「回到一模一样的画面」或同机位延续。\n' +
|
|
1596
|
+
'· mode=reframe(扣一张图,必须带 quote_chain_shot_from 的 quote_id):以源帧为锚、按本镜画面描述重生首帧——' +
|
|
1597
|
+
'人物/服装/道具/光线/场景延续,但保留本镜自己的景别与构图。景别有变化的缝要接,用这个。\n' +
|
|
1598
|
+
'★源不是上一镜尾帧时(首尾呼应/回到某个画面),平台会把本镜与上一镜的缝记为「有意切换」,自动帧链不会再覆盖它。' +
|
|
1599
|
+
'本镜已有视频的会被标为待重生;首帧已定稿的会被拒,客户同意覆盖才传 force:true。', {
|
|
1600
|
+
storyboard_id: z.number().int().positive().describe('要改首帧的那一镜'),
|
|
1601
|
+
source_storyboard_id: z.number().int().positive().describe('源镜 id(必须同一集);接上一镜就传上一镜的 id'),
|
|
1602
|
+
source_frame: z.enum(['first', 'last']).optional().describe('取源镜的哪一帧,默认 last(尾帧)'),
|
|
1603
|
+
mode: z.enum(['copy', 'reframe']).optional().describe('默认 copy(免费);reframe 需 quote_id'),
|
|
1604
|
+
quote_id: z.string().optional().describe('mode=reframe 时必填,来自 quote_chain_shot_from'),
|
|
1605
|
+
force: z.boolean().optional().describe('仅当客户明确同意覆盖已定稿的首帧时传 true'),
|
|
1606
|
+
}, async ({ storyboard_id, source_storyboard_id, source_frame, mode, quote_id, force }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/chain-from`, {
|
|
1607
|
+
source_storyboard_id,
|
|
1608
|
+
...(source_frame ? { source_frame } : {}),
|
|
1609
|
+
...(mode ? { mode } : {}),
|
|
1610
|
+
...(quote_id ? { quote_id } : {}),
|
|
1611
|
+
...(force ? { force: true } : {}),
|
|
1612
|
+
})));
|
|
1613
|
+
server.tool('quote_align_prev_shot', '(免费报价)align_prev_shot 会重生**上一镜的视频**(扣一条视频),执行前先报价、经客户确认。' +
|
|
1614
|
+
'回 quote_id / estimated_points / prev_storyboard_id(被重生的是哪一镜);含首次人像核验费时另列 kyc_first_time_points。', { storyboard_id: z.number().int().positive().describe('缝右侧那一镜(它的首帧将作为上一镜视频的收尾画面)') }, async ({ storyboard_id }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/align-prev/quote`)));
|
|
1615
|
+
server.tool('align_prev_shot', '缝裂修复「对齐上一镜」:本镜首帧**不动**,以它为收尾画面、用首尾帧模式重生**上一镜的视频**(上一镜首帧不变),' +
|
|
1616
|
+
'让上一镜真实收在本镜的开场画面上。扣一条视频,必须带 quote_align_prev_shot 的 quote_id。' +
|
|
1617
|
+
'★适用:客户换过本镜首帧(比如上传或重生了一张更满意的),而上一镜的视频已经出好、不想改本镜首帧去迁就它。' +
|
|
1618
|
+
'两镜都还没出视频时别用它——改首帧(chain_shot_from_prev / chain_shot_from)更便宜。' +
|
|
1619
|
+
'异步:轮询 get_storyboards 看上一镜 video_status。', {
|
|
1620
|
+
storyboard_id: z.number().int().positive().describe('缝右侧那一镜'),
|
|
1621
|
+
quote_id: z.string().describe('来自 quote_align_prev_shot'),
|
|
1622
|
+
}, async ({ storyboard_id, quote_id }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/align-prev`, { quote_id })));
|
|
1554
1623
|
server.tool('get_scene_group_plan', '查某一集的场景组规划(镜头如何归组做连续长镜)。免费。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/scene-group-plan`)));
|
|
1555
1624
|
server.tool('generate_scene_groups', '生成场景组(把连续镜头归组,连续长镜/批量出图的地基)。后台异步。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/scene-groups`)));
|
|
1556
1625
|
server.tool('render_multi_aspect', '把成片按多个画幅(竖/横/方)重渲一版,便于多平台分发。免费(纯 ffmpeg),后台异步。', {
|
package/openapi.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "StarReel Production API",
|
|
5
|
-
"version": "0.1.
|
|
6
|
-
"description": "Turn a script into a finished, downloadable short-drama episode over REST.\n\nPipeline: script → AI rewrite → cast/scenes/props extraction → storyboards → portraits & sheets + scene plates → keyframes → video shots → TTS → final cut (.mp4).\n\n**Billing is prepaid and agent-safe**: big-ticket stages are quote-then-generate (`quote_*` returns a `quote_id`). For video, quote == actual charge. For images the quote is a *range* — models billed per reference image are priced before those are assembled, so `estimated_points` is the upper bound (size the balance by it and a run never dies half-way) and `typical_points` is the usual cost; fixed-price models return the two equal. Insufficient balance returns 402 — nothing half-runs and the account never goes negative.\n\nAuth: exchange your API key at `POST /v1/agent/token` for a 15-minute bearer token.\n\nGenerated from the @starreel/mcp v0.1.
|
|
5
|
+
"version": "0.1.99",
|
|
6
|
+
"description": "Turn a script into a finished, downloadable short-drama episode over REST.\n\nPipeline: script → AI rewrite → cast/scenes/props extraction → storyboards → portraits & sheets + scene plates → keyframes → video shots → TTS → final cut (.mp4).\n\n**Billing is prepaid and agent-safe**: big-ticket stages are quote-then-generate (`quote_*` returns a `quote_id`). For video, quote == actual charge. For images the quote is a *range* — models billed per reference image are priced before those are assembled, so `estimated_points` is the upper bound (size the balance by it and a run never dies half-way) and `typical_points` is the usual cost; fixed-price models return the two equal. Insufficient balance returns 402 — nothing half-runs and the account never goes negative.\n\nAuth: exchange your API key at `POST /v1/agent/token` for a 15-minute bearer token.\n\nGenerated from the @starreel/mcp v0.1.99 tool surface (operationIds match MCP tool names 1:1)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
|
9
9
|
{
|
|
@@ -1508,8 +1508,8 @@
|
|
|
1508
1508
|
"/dramas/{drama_id}/cost-estimate": {
|
|
1509
1509
|
"get": {
|
|
1510
1510
|
"operationId": "get_cost_estimate",
|
|
1511
|
-
"summary": "
|
|
1512
|
-
"description": "
|
|
1511
|
+
"summary": "查一部剧的整体成本(点数):已花费 + 还没做的部分的待花费区间 + 分类明细",
|
|
1512
|
+
"description": "查一部剧的整体成本(点数):已花费 + 还没做的部分的待花费区间 + 分类明细。免费。already_spent_points 与 get_budget_status 的 spent、网页「本剧已花费」同源(平台扣费账本净额,已减退款),是同一个数。spent_source=usage_mirror 表示账本暂不可达、回退到本地镜像(偏少,不含文本/配乐),向客户报数时须注明,稍后重试即恢复;spent_note 是口径说明。breakdown 各行 done_points 之和 = already_spent_points:账本分不出文本用在改写/拆镜/补全/提取哪一步,文本已花费合计只在 kind=text_spent 一行(text / text_rewrite 行的 done_points 恒为 0,别报成「文本没花钱」;回退时没有 text_spent 行);配乐、声音克隆等没有单列预估的类别在 other_spent(note 列出构成)。total = 已花费 + 待花费。★同样不含账号级语音(音色库克隆/设计/试听),核账用 get_drama_bill。",
|
|
1513
1513
|
"tags": [
|
|
1514
1514
|
"dramas"
|
|
1515
1515
|
],
|
|
@@ -3171,7 +3171,7 @@
|
|
|
3171
3171
|
"post": {
|
|
3172
3172
|
"operationId": "chain_frames",
|
|
3173
3173
|
"summary": "整集首尾帧接力链:让每镜首帧承接上镜尾帧,镜间画面连续(比各镜独立出帧更顺)",
|
|
3174
|
-
"description": "整集首尾帧接力链:让每镜首帧承接上镜尾帧,镜间画面连续(比各镜独立出帧更顺)
|
|
3174
|
+
"description": "整集首尾帧接力链:让每镜首帧承接上镜尾帧,镜间画面连续(比各镜独立出帧更顺)。★何时调:首帧出完、tail_frame_plan 要的尾帧也补完之后,review_frames / generate_videos 之前。平台只在官网批量出帧结束时自动跑一次;逐镜出帧(generate_frames / generate_shot_frame)的集多半从没接过——get_storyboards 的 seam_state=unchained 就是这种缝。\n★先 dry_run:true(免费,不写库不出图):回 planned_copy / planned_reframe / estimated_points / needs_last_frame。copy=本镜首帧直接换成上镜尾帧(免费,但本镜景别会变成和上镜一样);reframe=以上镜尾帧为锚按本镜画面描述重生首帧(每道一张图,保景别)。把计划和 estimated_points 告诉客户,确认后**不带 dry_run** 再调一次执行(按用量后付)。\n★平台自己判哪道缝该接:有意切换(换场/时间跳跃/换装/插入镜)、已出视频的镜、已经接好的缝都会跳过——「已接好」= 首帧就是上镜尾帧,或 reframe 接在上镜**当前**尾帧上,所以重复执行不会重复扣费。上镜尾帧后来被重生过的缝会重新出现在计划里,那道缝确实断了。只补个别缝用 chain_shot_from_prev / chain_shot_from。执行后改了首帧的镜若已有视频会被标为待重生。执行完用 get_storyboards 核对 seam_state。",
|
|
3175
3175
|
"tags": [
|
|
3176
3176
|
"episodes"
|
|
3177
3177
|
],
|
|
@@ -3186,6 +3186,21 @@
|
|
|
3186
3186
|
}
|
|
3187
3187
|
}
|
|
3188
3188
|
],
|
|
3189
|
+
"requestBody": {
|
|
3190
|
+
"required": false,
|
|
3191
|
+
"content": {
|
|
3192
|
+
"application/json": {
|
|
3193
|
+
"schema": {
|
|
3194
|
+
"type": "object",
|
|
3195
|
+
"properties": {
|
|
3196
|
+
"dry_run": {
|
|
3197
|
+
"type": "boolean"
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
},
|
|
3189
3204
|
"responses": {
|
|
3190
3205
|
"200": {
|
|
3191
3206
|
"description": "StarReel envelope",
|
|
@@ -5532,7 +5547,7 @@
|
|
|
5532
5547
|
"post": {
|
|
5533
5548
|
"operationId": "review_frames",
|
|
5534
5549
|
"summary": "【第③道硬闸·免费】审查镜头图片层:角色身份锚覆盖(缺定妆图的角色在镜头里必漂)、出图失败率、孤儿角色变体、场景图被人物污染",
|
|
5535
|
-
"description": "【第③道硬闸·免费】审查镜头图片层:角色身份锚覆盖(缺定妆图的角色在镜头里必漂)、出图失败率、孤儿角色变体、场景图被人物污染。★generate_videos 之前必须先跑本工具——出视频是全链最贵的一步,拿着漂移的首帧整集出视频是最典型的废片形态。按 findings.action 修完(多为 generate_character_portraits / generate_shot_frame 单镜重生)
|
|
5550
|
+
"description": "【第③道硬闸·免费】审查镜头图片层:角色身份锚覆盖(缺定妆图的角色在镜头里必漂)、出图失败率、孤儿角色变体、场景图被人物污染。★generate_videos 之前必须先跑本工具——出视频是全链最贵的一步,拿着漂移的首帧整集出视频是最典型的废片形态。按 findings.action 修完(多为 generate_character_portraits / generate_shot_frame 单镜重生)再复审。★还会报**镜间接缝**(warning,不拦):code=seam_unchained(标了连续却从没做过首尾帧衔接)/seam_broken(接过但没接上),shots 是「与上一镜的缝有问题」的那一镜。出视频前修最便宜——视频按首帧生成,首帧与上镜尾帧对不上,成片就是一次跳切。修法看 action(整集 chain_frames 先 dry_run;单道 chain_shot_from_prev / chain_shot_from)。",
|
|
5536
5551
|
"tags": [
|
|
5537
5552
|
"episodes"
|
|
5538
5553
|
],
|
|
@@ -6248,7 +6263,7 @@
|
|
|
6248
6263
|
"get": {
|
|
6249
6264
|
"operationId": "get_storyboards",
|
|
6250
6265
|
"summary": "读某一集的分镜列表(供审阅/查进度)",
|
|
6251
|
-
"description": "读某一集的分镜列表(供审阅/查进度)。含每镜首帧(first_frame_image)与视频(video_url)是否就绪。★每镜带**台词与说话人**:dialogue(原文,无台词为 null)、dialogue_lines([{speaker,text}] 逐行,与字幕/配音同一个解析器拆的——这里的 speaker 就是成片里被配音的那个;舞台提示已剥),以及 is_key_moment(1=关键镜,走高端图模)与 emotion_intensity(1-10)。核对「台词有没有丢/谁说的/关键镜是哪几镜/情绪曲线」用这一次调用即可,不用逐镜拉;update_shot 改完台词也在这里核对。画面/视频/首尾帧提示词仍只在 get_shot_prompts 逐镜读。★每镜还带**结构化状态**:frame_status/video_status(ready/pending/authorizing/rejected/failed/none/not_required)、★not_required=旁白/片尾卡镜:帧与视频由成片层渲染,本镜不需要生成——数补齐进度时把它当已完成,别重试。fail_reason(sensitive/text_sensitive/copyright/face_mismatch/account_overdue/quota_full/authorizing/insufficient_credits/transient/repeat_rejected/pair_collateral)、retryable(true=可重试;false=改内容换图,重试无效)、fail_hint(人读文案)。照 retryable 判该重试还是该改内容,别解析中文。★pair_collateral=同镜另一帧未通过、本帧随批结束——**本帧自身没被判不合格,别去改它**:有 reopen_pair_id 就用它只重掷有过错的一侧,否则直接重生本镜。★若某镜带 degraded_frames:[{frame_type,reason,reason_label,since,hint}],表示该帧是系统在同因连拒熔断后**放行**的(判据照记未拒),URL 上与干净帧无区别但需人工复核;不满意按 hint 修正输入后 generate_shot_frame 重生该帧。★terminal_desc_missing=true:该镜标为「状态改变」却三处都没说结束时什么样——**出尾帧前**就能看出来,现在整集一次拿到(此前只有 get_shot_prompts 能逐镜问,一集几十次没人会去问)。先 update_shot 把结束状态写进 last_frame_prompt 再出尾帧:照现状硬出的历史成功率 9.4%,写了终态的 40.2%,而每次被拒都照常扣费。确实该「几乎不变」的镜才用 generate_shot_frame 的 allow_missing_terminal 放行。★first_frame_source/last_frame_source='upload' 表示该帧是**外部上传图**(绕开了身份锚/画风锚/best-of-N/帧审计整条质量链路)——人物·服装·画风漂移排查先看这些镜;外部图导致的漂移不是平台生成质量问题,修复正路是删掉外部图改走 generate_shot_frame 平台重生。★若某镜带 reopen_pair_id:该镜首尾帧同时生成时只有一侧真的有问题、另一侧是无辜陪拒,原样传给 generate_shot_frame 的 reopen_pair_id 参数可以只重掷有问题的那一侧(省一半算力/费用,不会拿去生成一张这次根本没打算重做的图)。没有这个字段就按 fail_reason/retryable 走常规重试。免费。★每镜还带**绑定**(只有 ID):character_ids(本镜绑定的角色)、character_bindings[{character_id,presence}](presence=on_screen 在画面 / voice_only 只有声音、不进画面)、scene_id、prop_ids、active_wardrobe_id。出图注入谁的定妆图/哪张场景图/哪些道具图由这几项决定;角色名对照 get_characters、道具名对照 get_props。改绑用 update_shot 的 character_ids(★全量覆盖,先从这里读现值再改,漏传即解绑)与 character_presence;改完再读一次本工具核对。character_bindings 缺席 = 这次没读到(不是没绑)
|
|
6266
|
+
"description": "读某一集的分镜列表(供审阅/查进度)。含每镜首帧(first_frame_image)与视频(video_url)是否就绪。★每镜带**台词与说话人**:dialogue(原文,无台词为 null)、dialogue_lines([{speaker,text}] 逐行,与字幕/配音同一个解析器拆的——这里的 speaker 就是成片里被配音的那个;舞台提示已剥),以及 is_key_moment(1=关键镜,走高端图模)与 emotion_intensity(1-10)。核对「台词有没有丢/谁说的/关键镜是哪几镜/情绪曲线」用这一次调用即可,不用逐镜拉;update_shot 改完台词也在这里核对。画面/视频/首尾帧提示词仍只在 get_shot_prompts 逐镜读。★每镜还带**结构化状态**:frame_status/video_status(ready/pending/authorizing/rejected/failed/none/not_required)、★not_required=旁白/片尾卡镜:帧与视频由成片层渲染,本镜不需要生成——数补齐进度时把它当已完成,别重试。fail_reason(sensitive/text_sensitive/copyright/face_mismatch/account_overdue/quota_full/authorizing/insufficient_credits/transient/repeat_rejected/pair_collateral)、retryable(true=可重试;false=改内容换图,重试无效)、fail_hint(人读文案)。照 retryable 判该重试还是该改内容,别解析中文。★pair_collateral=同镜另一帧未通过、本帧随批结束——**本帧自身没被判不合格,别去改它**:有 reopen_pair_id 就用它只重掷有过错的一侧,否则直接重生本镜。★若某镜带 degraded_frames:[{frame_type,reason,reason_label,since,hint}],表示该帧是系统在同因连拒熔断后**放行**的(判据照记未拒),URL 上与干净帧无区别但需人工复核;不满意按 hint 修正输入后 generate_shot_frame 重生该帧。★terminal_desc_missing=true:该镜标为「状态改变」却三处都没说结束时什么样——**出尾帧前**就能看出来,现在整集一次拿到(此前只有 get_shot_prompts 能逐镜问,一集几十次没人会去问)。先 update_shot 把结束状态写进 last_frame_prompt 再出尾帧:照现状硬出的历史成功率 9.4%,写了终态的 40.2%,而每次被拒都照常扣费。确实该「几乎不变」的镜才用 generate_shot_frame 的 allow_missing_terminal 放行。★first_frame_source/last_frame_source='upload' 表示该帧是**外部上传图**(绕开了身份锚/画风锚/best-of-N/帧审计整条质量链路)——人物·服装·画风漂移排查先看这些镜;外部图导致的漂移不是平台生成质量问题,修复正路是删掉外部图改走 generate_shot_frame 平台重生。★若某镜带 reopen_pair_id:该镜首尾帧同时生成时只有一侧真的有问题、另一侧是无辜陪拒,原样传给 generate_shot_frame 的 reopen_pair_id 参数可以只重掷有问题的那一侧(省一半算力/费用,不会拿去生成一张这次根本没打算重做的图)。没有这个字段就按 fail_reason/retryable 走常规重试。免费。★每镜还带**绑定**(只有 ID):character_ids(本镜绑定的角色)、character_bindings[{character_id,presence}](presence=on_screen 在画面 / voice_only 只有声音、不进画面)、scene_id、prop_ids、active_wardrobe_id。出图注入谁的定妆图/哪张场景图/哪些道具图由这几项决定;角色名对照 get_characters、道具名对照 get_props。改绑用 update_shot 的 character_ids(★全量覆盖,先从这里读现值再改,漏传即解绑)与 character_presence;改完再读一次本工具核对。character_bindings 缺席 = 这次没读到(不是没绑),空数组才是没绑。★每镜带 **seam_state**(本镜与上一镜的镜间接缝,与官网帧时间线同一判据):ok=已续接(首帧就是上镜尾帧,或平台做过首尾帧衔接) / unchained=标了连续却从没接过 / broken=接过但没接上(seam_failed_dims 给出哪几维不连续:characters/wardrobe/props/lighting/scene) / intended=有意切换(硬切/换场/时间跳跃/景别大跳/插入镜/外部上传帧),不用管 / missing=两侧帧没齐 / unknown=没标意图也没接过(系统没判,不是有问题) / na=首镜或旁白卡。seam_audit_status=pending 表示已接、平台的衔接审计还没出结论(若本镜 frame_status=failed,说明衔接那次重生没出成,缝其实没接上)。出视频前只需处理 unchained 与 broken:整集用 chain_frames(先 dry_run),单道用 chain_shot_from_prev / chain_shot_from。",
|
|
6252
6267
|
"tags": [
|
|
6253
6268
|
"episodes"
|
|
6254
6269
|
],
|
|
@@ -8828,6 +8843,320 @@
|
|
|
8828
8843
|
}
|
|
8829
8844
|
}
|
|
8830
8845
|
},
|
|
8846
|
+
"/storyboards/{storyboard_id}/align-prev": {
|
|
8847
|
+
"post": {
|
|
8848
|
+
"operationId": "align_prev_shot",
|
|
8849
|
+
"summary": "缝裂修复「对齐上一镜」:本镜首帧**不动**,以它为收尾画面、用首尾帧模式重生**上一镜的视频**(上一镜首帧不变),让上一镜真实收在本镜的开场画面上",
|
|
8850
|
+
"description": "缝裂修复「对齐上一镜」:本镜首帧**不动**,以它为收尾画面、用首尾帧模式重生**上一镜的视频**(上一镜首帧不变),让上一镜真实收在本镜的开场画面上。扣一条视频,必须带 quote_align_prev_shot 的 quote_id。★适用:客户换过本镜首帧(比如上传或重生了一张更满意的),而上一镜的视频已经出好、不想改本镜首帧去迁就它。两镜都还没出视频时别用它——改首帧(chain_shot_from_prev / chain_shot_from)更便宜。异步:轮询 get_storyboards 看上一镜 video_status。",
|
|
8851
|
+
"tags": [
|
|
8852
|
+
"storyboards"
|
|
8853
|
+
],
|
|
8854
|
+
"parameters": [
|
|
8855
|
+
{
|
|
8856
|
+
"name": "storyboard_id",
|
|
8857
|
+
"in": "path",
|
|
8858
|
+
"required": true,
|
|
8859
|
+
"schema": {
|
|
8860
|
+
"type": "integer",
|
|
8861
|
+
"exclusiveMinimum": 0,
|
|
8862
|
+
"description": "缝右侧那一镜"
|
|
8863
|
+
}
|
|
8864
|
+
}
|
|
8865
|
+
],
|
|
8866
|
+
"requestBody": {
|
|
8867
|
+
"required": true,
|
|
8868
|
+
"content": {
|
|
8869
|
+
"application/json": {
|
|
8870
|
+
"schema": {
|
|
8871
|
+
"type": "object",
|
|
8872
|
+
"properties": {
|
|
8873
|
+
"quote_id": {
|
|
8874
|
+
"type": "string",
|
|
8875
|
+
"description": "来自 quote_align_prev_shot"
|
|
8876
|
+
}
|
|
8877
|
+
},
|
|
8878
|
+
"required": [
|
|
8879
|
+
"quote_id"
|
|
8880
|
+
]
|
|
8881
|
+
}
|
|
8882
|
+
}
|
|
8883
|
+
}
|
|
8884
|
+
},
|
|
8885
|
+
"responses": {
|
|
8886
|
+
"200": {
|
|
8887
|
+
"description": "StarReel envelope",
|
|
8888
|
+
"content": {
|
|
8889
|
+
"application/json": {
|
|
8890
|
+
"schema": {
|
|
8891
|
+
"type": "object",
|
|
8892
|
+
"properties": {
|
|
8893
|
+
"code": {
|
|
8894
|
+
"type": "integer"
|
|
8895
|
+
},
|
|
8896
|
+
"message": {
|
|
8897
|
+
"type": "string"
|
|
8898
|
+
},
|
|
8899
|
+
"data": {
|
|
8900
|
+
"description": "Operation result payload"
|
|
8901
|
+
}
|
|
8902
|
+
}
|
|
8903
|
+
}
|
|
8904
|
+
}
|
|
8905
|
+
}
|
|
8906
|
+
},
|
|
8907
|
+
"402": {
|
|
8908
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
8909
|
+
}
|
|
8910
|
+
}
|
|
8911
|
+
}
|
|
8912
|
+
},
|
|
8913
|
+
"/storyboards/{storyboard_id}/align-prev/quote": {
|
|
8914
|
+
"post": {
|
|
8915
|
+
"operationId": "quote_align_prev_shot",
|
|
8916
|
+
"summary": "(免费报价)align_prev_shot 会重生**上一镜的视频**(扣一条视频),执行前先报价、经客户确认",
|
|
8917
|
+
"description": "(免费报价)align_prev_shot 会重生**上一镜的视频**(扣一条视频),执行前先报价、经客户确认。回 quote_id / estimated_points / prev_storyboard_id(被重生的是哪一镜);含首次人像核验费时另列 kyc_first_time_points。",
|
|
8918
|
+
"tags": [
|
|
8919
|
+
"storyboards"
|
|
8920
|
+
],
|
|
8921
|
+
"parameters": [
|
|
8922
|
+
{
|
|
8923
|
+
"name": "storyboard_id",
|
|
8924
|
+
"in": "path",
|
|
8925
|
+
"required": true,
|
|
8926
|
+
"schema": {
|
|
8927
|
+
"type": "integer",
|
|
8928
|
+
"exclusiveMinimum": 0,
|
|
8929
|
+
"description": "缝右侧那一镜(它的首帧将作为上一镜视频的收尾画面)"
|
|
8930
|
+
}
|
|
8931
|
+
}
|
|
8932
|
+
],
|
|
8933
|
+
"responses": {
|
|
8934
|
+
"200": {
|
|
8935
|
+
"description": "StarReel envelope",
|
|
8936
|
+
"content": {
|
|
8937
|
+
"application/json": {
|
|
8938
|
+
"schema": {
|
|
8939
|
+
"type": "object",
|
|
8940
|
+
"properties": {
|
|
8941
|
+
"code": {
|
|
8942
|
+
"type": "integer"
|
|
8943
|
+
},
|
|
8944
|
+
"message": {
|
|
8945
|
+
"type": "string"
|
|
8946
|
+
},
|
|
8947
|
+
"data": {
|
|
8948
|
+
"description": "Operation result payload"
|
|
8949
|
+
}
|
|
8950
|
+
}
|
|
8951
|
+
}
|
|
8952
|
+
}
|
|
8953
|
+
}
|
|
8954
|
+
},
|
|
8955
|
+
"402": {
|
|
8956
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
8957
|
+
}
|
|
8958
|
+
}
|
|
8959
|
+
}
|
|
8960
|
+
},
|
|
8961
|
+
"/storyboards/{storyboard_id}/chain-from": {
|
|
8962
|
+
"post": {
|
|
8963
|
+
"operationId": "chain_shot_from",
|
|
8964
|
+
"summary": "把同一集**任一镜**的首帧或尾帧接为本镜首帧",
|
|
8965
|
+
"description": "把同一集**任一镜**的首帧或尾帧接为本镜首帧。两种落法:\n· mode=copy(默认,免费):本镜首帧直接换成源帧,画面逐像素相同——适合「回到一模一样的画面」或同机位延续。\n· mode=reframe(扣一张图,必须带 quote_chain_shot_from 的 quote_id):以源帧为锚、按本镜画面描述重生首帧——人物/服装/道具/光线/场景延续,但保留本镜自己的景别与构图。景别有变化的缝要接,用这个。\n★源不是上一镜尾帧时(首尾呼应/回到某个画面),平台会把本镜与上一镜的缝记为「有意切换」,自动帧链不会再覆盖它。本镜已有视频的会被标为待重生;首帧已定稿的会被拒,客户同意覆盖才传 force:true。",
|
|
8966
|
+
"tags": [
|
|
8967
|
+
"storyboards"
|
|
8968
|
+
],
|
|
8969
|
+
"parameters": [
|
|
8970
|
+
{
|
|
8971
|
+
"name": "storyboard_id",
|
|
8972
|
+
"in": "path",
|
|
8973
|
+
"required": true,
|
|
8974
|
+
"schema": {
|
|
8975
|
+
"type": "integer",
|
|
8976
|
+
"exclusiveMinimum": 0,
|
|
8977
|
+
"description": "要改首帧的那一镜"
|
|
8978
|
+
}
|
|
8979
|
+
}
|
|
8980
|
+
],
|
|
8981
|
+
"requestBody": {
|
|
8982
|
+
"required": true,
|
|
8983
|
+
"content": {
|
|
8984
|
+
"application/json": {
|
|
8985
|
+
"schema": {
|
|
8986
|
+
"type": "object",
|
|
8987
|
+
"properties": {
|
|
8988
|
+
"source_storyboard_id": {
|
|
8989
|
+
"type": "integer",
|
|
8990
|
+
"exclusiveMinimum": 0,
|
|
8991
|
+
"description": "源镜 id(必须同一集);接上一镜就传上一镜的 id"
|
|
8992
|
+
},
|
|
8993
|
+
"source_frame": {
|
|
8994
|
+
"type": "string",
|
|
8995
|
+
"enum": [
|
|
8996
|
+
"first",
|
|
8997
|
+
"last"
|
|
8998
|
+
]
|
|
8999
|
+
},
|
|
9000
|
+
"mode": {
|
|
9001
|
+
"type": "string",
|
|
9002
|
+
"enum": [
|
|
9003
|
+
"copy",
|
|
9004
|
+
"reframe"
|
|
9005
|
+
]
|
|
9006
|
+
},
|
|
9007
|
+
"quote_id": {
|
|
9008
|
+
"type": "string"
|
|
9009
|
+
},
|
|
9010
|
+
"force": {
|
|
9011
|
+
"type": "boolean"
|
|
9012
|
+
}
|
|
9013
|
+
},
|
|
9014
|
+
"required": [
|
|
9015
|
+
"source_storyboard_id"
|
|
9016
|
+
]
|
|
9017
|
+
}
|
|
9018
|
+
}
|
|
9019
|
+
}
|
|
9020
|
+
},
|
|
9021
|
+
"responses": {
|
|
9022
|
+
"200": {
|
|
9023
|
+
"description": "StarReel envelope",
|
|
9024
|
+
"content": {
|
|
9025
|
+
"application/json": {
|
|
9026
|
+
"schema": {
|
|
9027
|
+
"type": "object",
|
|
9028
|
+
"properties": {
|
|
9029
|
+
"code": {
|
|
9030
|
+
"type": "integer"
|
|
9031
|
+
},
|
|
9032
|
+
"message": {
|
|
9033
|
+
"type": "string"
|
|
9034
|
+
},
|
|
9035
|
+
"data": {
|
|
9036
|
+
"description": "Operation result payload"
|
|
9037
|
+
}
|
|
9038
|
+
}
|
|
9039
|
+
}
|
|
9040
|
+
}
|
|
9041
|
+
}
|
|
9042
|
+
},
|
|
9043
|
+
"402": {
|
|
9044
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
9045
|
+
}
|
|
9046
|
+
}
|
|
9047
|
+
}
|
|
9048
|
+
},
|
|
9049
|
+
"/storyboards/{storyboard_id}/chain-from-prev": {
|
|
9050
|
+
"post": {
|
|
9051
|
+
"operationId": "chain_shot_from_prev",
|
|
9052
|
+
"summary": "(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图",
|
|
9053
|
+
"description": "(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图。★适用:两镜是同一机位、同一景别的延续(seam_state=unchained/broken 且本镜本来就该和上镜一个构图)。★别用于景别有变化的缝(全景→近景等):那会把本镜的景别设计冲掉,且后续出图可能被判「与设计不符」——这种缝用 chain_shot_from 的 mode=reframe。本镜已有视频的会被标为待重生。本镜首帧若已被客户定稿(first_frame_pinned)会被拒;客户明确同意覆盖才传 force:true。",
|
|
9054
|
+
"tags": [
|
|
9055
|
+
"storyboards"
|
|
9056
|
+
],
|
|
9057
|
+
"parameters": [
|
|
9058
|
+
{
|
|
9059
|
+
"name": "storyboard_id",
|
|
9060
|
+
"in": "path",
|
|
9061
|
+
"required": true,
|
|
9062
|
+
"schema": {
|
|
9063
|
+
"type": "integer",
|
|
9064
|
+
"exclusiveMinimum": 0,
|
|
9065
|
+
"description": "要改首帧的那一镜(缝的右侧)"
|
|
9066
|
+
}
|
|
9067
|
+
}
|
|
9068
|
+
],
|
|
9069
|
+
"requestBody": {
|
|
9070
|
+
"required": false,
|
|
9071
|
+
"content": {
|
|
9072
|
+
"application/json": {
|
|
9073
|
+
"schema": {
|
|
9074
|
+
"type": "object",
|
|
9075
|
+
"properties": {
|
|
9076
|
+
"force": {
|
|
9077
|
+
"type": "boolean"
|
|
9078
|
+
}
|
|
9079
|
+
}
|
|
9080
|
+
}
|
|
9081
|
+
}
|
|
9082
|
+
}
|
|
9083
|
+
},
|
|
9084
|
+
"responses": {
|
|
9085
|
+
"200": {
|
|
9086
|
+
"description": "StarReel envelope",
|
|
9087
|
+
"content": {
|
|
9088
|
+
"application/json": {
|
|
9089
|
+
"schema": {
|
|
9090
|
+
"type": "object",
|
|
9091
|
+
"properties": {
|
|
9092
|
+
"code": {
|
|
9093
|
+
"type": "integer"
|
|
9094
|
+
},
|
|
9095
|
+
"message": {
|
|
9096
|
+
"type": "string"
|
|
9097
|
+
},
|
|
9098
|
+
"data": {
|
|
9099
|
+
"description": "Operation result payload"
|
|
9100
|
+
}
|
|
9101
|
+
}
|
|
9102
|
+
}
|
|
9103
|
+
}
|
|
9104
|
+
}
|
|
9105
|
+
},
|
|
9106
|
+
"402": {
|
|
9107
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
9108
|
+
}
|
|
9109
|
+
}
|
|
9110
|
+
}
|
|
9111
|
+
},
|
|
9112
|
+
"/storyboards/{storyboard_id}/chain-from/quote": {
|
|
9113
|
+
"post": {
|
|
9114
|
+
"operationId": "quote_chain_shot_from",
|
|
9115
|
+
"summary": "(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价、经客户确认",
|
|
9116
|
+
"description": "(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价、经客户确认。回 quote_id / estimated_points;quote_id 一次性、只对这一镜有效。mode=copy 不需要报价。",
|
|
9117
|
+
"tags": [
|
|
9118
|
+
"storyboards"
|
|
9119
|
+
],
|
|
9120
|
+
"parameters": [
|
|
9121
|
+
{
|
|
9122
|
+
"name": "storyboard_id",
|
|
9123
|
+
"in": "path",
|
|
9124
|
+
"required": true,
|
|
9125
|
+
"schema": {
|
|
9126
|
+
"type": "integer",
|
|
9127
|
+
"exclusiveMinimum": 0,
|
|
9128
|
+
"description": "要重生首帧的那一镜"
|
|
9129
|
+
}
|
|
9130
|
+
}
|
|
9131
|
+
],
|
|
9132
|
+
"responses": {
|
|
9133
|
+
"200": {
|
|
9134
|
+
"description": "StarReel envelope",
|
|
9135
|
+
"content": {
|
|
9136
|
+
"application/json": {
|
|
9137
|
+
"schema": {
|
|
9138
|
+
"type": "object",
|
|
9139
|
+
"properties": {
|
|
9140
|
+
"code": {
|
|
9141
|
+
"type": "integer"
|
|
9142
|
+
},
|
|
9143
|
+
"message": {
|
|
9144
|
+
"type": "string"
|
|
9145
|
+
},
|
|
9146
|
+
"data": {
|
|
9147
|
+
"description": "Operation result payload"
|
|
9148
|
+
}
|
|
9149
|
+
}
|
|
9150
|
+
}
|
|
9151
|
+
}
|
|
9152
|
+
}
|
|
9153
|
+
},
|
|
9154
|
+
"402": {
|
|
9155
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
9156
|
+
}
|
|
9157
|
+
}
|
|
9158
|
+
}
|
|
9159
|
+
},
|
|
8831
9160
|
"/storyboards/{storyboard_id}/dialogue-replace": {
|
|
8832
9161
|
"post": {
|
|
8833
9162
|
"operationId": "replace_shot_dialogue",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starreel/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.99",
|
|
4
4
|
"mcpName": "ai.starreel/starreel",
|
|
5
5
|
"description": "StarReel MCP server — drive the AI short-drama production pipeline (script → storyboards → frames → video → final cut) from Claude, Cursor, or any MCP client",
|
|
6
6
|
"license": "MIT",
|
package/server.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
|
|
3
3
|
"name": "ai.starreel/starreel",
|
|
4
4
|
"description": "Turn a script into a finished, downloadable short-drama episode — via MCP or REST.",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.99",
|
|
6
6
|
"websiteUrl": "https://starreel.ai",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "@starreel/mcp",
|
|
11
|
-
"version": "0.1.
|
|
11
|
+
"version": "0.1.99",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
},
|