@starreel/mcp 0.1.215 → 0.1.216
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 +4 -0
- package/dist/i18n/tools.en.json +3 -3
- package/dist/i18n/tools.zh-CN.json +3 -3
- package/dist/tools/produce.js +12 -5
- package/openapi.json +20 -5
- package/package.json +1 -1
- package/server.json +2 -2
package/SKILL.md
CHANGED
|
@@ -536,6 +536,10 @@ content that will be rejected.
|
|
|
536
536
|
really is broken). To fix individual seams: `chain_shot_from_prev` (free,
|
|
537
537
|
same-framing continuation) or
|
|
538
538
|
`quote_chain_shot_from` → `chain_shot_from` with `mode: "reframe"` (framing changes).
|
|
539
|
+
A shot whose first frame the customer uploaded or locked is refused by all three
|
|
540
|
+
(409 `reason: "user-locked-frame"`, nothing dispatched or billed, no quote issued):
|
|
541
|
+
tell the customer; only after they explicitly agree to replace it pass `force: true`
|
|
542
|
+
to both the quote and the call (it lifts the upload / lock protection).
|
|
539
543
|
If the previous shot's video is already done and the customer does not want to touch
|
|
540
544
|
this shot's first frame, `quote_align_prev_shot` → `align_prev_shot` regenerates the
|
|
541
545
|
**previous** shot's video so it ends on this shot's opening frame (one video).
|
package/dist/i18n/tools.en.json
CHANGED
|
@@ -208,9 +208,9 @@
|
|
|
208
208
|
"build_av_timing_contract": "★Run this first when an external agent assembles the cut itself, or to check why the final cut has the length it has — do not assemble by the seconds written in the storyboard. Free, zero charge (pure ffprobe + local activity detection; no vendor calls and no on-the-fly TTS synthesis). Returns the episode's A/V timing contract. Per shot: source.duration_ms (ffprobe-measured source length, not the storyboard seconds) and excess_over_declared_ms (extra tail the vendor delivered); trim.in_ms/out_ms (source in/out points used in the cut, auto head-trim and trim_shot included; untrimmed shots have full_length=true); action (effective action window and recommended trim window, reusing recommend_trim_window's activity detection); tail (freeze_pad_ms = frames the renderer clones to pad the shot, low_motion_in_cut_ms = low-motion tail still in the cut after the action ends); voice.in_final_cut (mixed_into_video = the voice is already mixed into the clip's audio, never dub it again; separate_track = separate dialogue track, dialogue_track gives its timeline interval; pending_synthesis/missing/unknown/double_voice — see instruction); timeline (start/end on the final-cut timeline, transition_in overlap, transition_out_overlap_ms, exclusive interval). The episode summary gives total duration, total transition overlap, per-track spans and tracks that run past the end of the picture. planned uses the same timeline build as compose_episode; final_cut reads the timeline the last final cut actually rendered and measures the final file (duration_check); drift_vs_planned lists shots that would change if you re-composed now. Async: this tool only starts the job; poll get_av_timing_contract until status=done. include_activity=false skips activity detection (faster, but no action window or low-motion tail).",
|
|
209
209
|
"get_av_timing_contract": "Check progress and results of build_av_timing_contract. Free. While status=running read progress (stage=build_timeline/activity/probe); when status=done, result.planned is the per-shot contract a re-compose would produce now, result.final_cut is the last final cut (contract = derived from the stored timeline, probed = measured final file, duration_check.matches = total duration agrees within 100 ms, drift_vs_planned = shots that differ; when timeline_association≠verified the stored timeline is no longer the one the final cut rendered, so contract is not provided). ★When assembling yourself, place shots by shots[].timeline and cut sources by trim.in_ms/out_ms; for voice.in_final_cut=mixed_into_video use the clip's own audio and never lay another voice on top. A non-empty result.synth_skipped_shot_ids means those shots have no synthesized voice yet (synthesized and billed at compose time), so their dialogue-track intervals are missing.",
|
|
210
210
|
"chain_frames": "Whole-episode first/last-frame relay chain: make each shot's first frame inherit the previous shot's last frame so inter-shot visuals are continuous (smoother than generating each shot independently). ★When to call: after first frames are done and any last frames required by tail_frame_plan are also filled, before review_frames / generate_videos. The platform only auto-runs this once when batch frame generation on the official site finishes; episodes generated shot by shot (generate_frames / generate_shot_frame) often have never been chained — get_storyboards seam_state=unchained means this kind of seam.\n★First use dry_run:true (free, does not write DB or generate images): returns planned_copy / planned_reframe / estimated_points / needs_last_frame. copy = directly replace this shot's first frame with the previous shot's last frame (free, but this shot's shot size becomes the same as the previous shot); reframe = use the previous shot's last frame as an anchor to regenerate this shot's first frame according to this shot's visual description (one image per seam, preserves shot size). Tell the client the plan and estimated_points; after confirmation, call again **without dry_run** to execute (postpaid by usage).\n★The platform decides which seams to chain: intentional cuts (scene/time jump/costume change/insert shot), shots with existing video, and already-chained seams are skipped — “already chained” = the first frame is the previous shot's last frame, or reframe is chained to the previous shot's **current** last frame, so repeated execution will not charge again. If the previous shot's last frame is later regenerated, that seam will reappear in the plan; that seam is indeed broken. To fill individual seams, use chain_shot_from_prev / chain_shot_from. Shots whose first frame is changed by execution and already have video will be marked pending regeneration. ★Execution only dispatches reframe and does not wait for image generation: use get_jobs to view first_frame generation rows for these shots; wait until all pending/processing are finished (for failed, check error_msg; for a single seam use chain_shot_from to reconnect; while the old first frame still exists, get_storyboards frame_status remains ready and failure is not visible), then use get_storyboards to verify seam_state and review_frames — auditing too early will audit the old first frame, and the token will be invalidated later.",
|
|
211
|
-
"chain_shot_from_prev": "(Free) Directly set the previous shot's last frame as this shot's first frame: visuals connect 100%, zero cost, no image generation. ★Use when: the two shots are a continuation from the same camera position and same shot size (seam_state=unchained/broken and this shot should already share the previous shot's composition). ★Do not use for seams with shot-size changes (wide → close-up, etc.): it will overwrite this shot's shot-size design, and later image generation may be judged “inconsistent with design” — for such seams use chain_shot_from with mode=reframe. If this shot already has video, it will be marked pending regeneration. If this shot's first frame
|
|
212
|
-
"quote_chain_shot_from": "(Free quote) chain_shot_from with mode=reframe deducts **one image** (regenerate this shot's first frame anchored on the source frame); quote before execution (quote confirmation follows execution mode: professional mode / unconfirmed plan / this step is customer-controlled → explain to the customer and proceed only after customer approval; do not decide for them; this step is autopiloted → do not ask the customer, execute per get_production_plan autopilot.default_decisions, and the platform records it in get_autopilot_log). Returns quote_id / estimated_points; quote_id is one-time and valid only for this shot. mode=copy needs no quote.",
|
|
213
|
-
"chain_shot_from": "Use the first or last frame of **any shot** in the same episode as this shot's first frame. Two modes:\n· mode=copy(default, free): directly replace this shot's first frame with the source frame, pixel-identical—good for “return to the exact same image” or continuing the same camera position.\n· mode=reframe(deducts one image, must include quote_id from quote_chain_shot_from): regenerate the first frame anchored on the source frame and based on this shot's visual description—character/clothing/prop/lighting/scene continuity, while preserving this shot's own shot size and composition. Use this when the seam must connect while shot size changes.\n★If the source is not the previous shot's last frame (bookend / return to a previous image), the platform records the seam between this shot and the previous shot as an “intentional cut”, and automatic frame chaining will no longer overwrite it. If this shot already has video it will be marked for regeneration; if its first frame is finalized it will be rejected—pass force:true only when overwriting it has explicit customer approval (required in every execution mode, including autopilot).",
|
|
211
|
+
"chain_shot_from_prev": "(Free) Directly set the previous shot's last frame as this shot's first frame: visuals connect 100%, zero cost, no image generation. ★Use when: the two shots are a continuation from the same camera position and same shot size (seam_state=unchained/broken and this shot should already share the previous shot's composition). ★Do not use for seams with shot-size changes (wide → close-up, etc.): it will overwrite this shot's shot-size design, and later image generation may be judged “inconsistent with design” — for such seams use chain_shot_from with mode=reframe. If this shot already has video, it will be marked pending regeneration. If this shot's first frame was uploaded by the client (first_frame_source=upload) or is client-locked (first_frame_pinned), the call is rejected (409 reason=user-locked-frame); pass force:true only to overwrite it (any execution mode requires explicit client consent, including managed mode). force releases the upload / lock protection, and the new frame needs client re-acceptance.",
|
|
212
|
+
"quote_chain_shot_from": "(Free quote) chain_shot_from with mode=reframe deducts **one image** (regenerate this shot's first frame anchored on the source frame); quote before execution (quote confirmation follows execution mode: professional mode / unconfirmed plan / this step is customer-controlled → explain to the customer and proceed only after customer approval; do not decide for them; this step is autopiloted → do not ask the customer, execute per get_production_plan autopilot.default_decisions, and the platform records it in get_autopilot_log). Returns quote_id / estimated_points; quote_id is one-time and valid only for this shot. mode=copy needs no quote. If this shot's first frame was uploaded by the client or is locked, no quote is issued without force (409 reason=user-locked-frame, not priced); after the client explicitly agrees to replace it, pass force:true to both the quote and the execution.",
|
|
213
|
+
"chain_shot_from": "Use the first or last frame of **any shot** in the same episode as this shot's first frame. Two modes:\n· mode=copy(default, free): directly replace this shot's first frame with the source frame, pixel-identical—good for “return to the exact same image” or continuing the same camera position.\n· mode=reframe(deducts one image, must include quote_id from quote_chain_shot_from): regenerate the first frame anchored on the source frame and based on this shot's visual description—character/clothing/prop/lighting/scene continuity, while preserving this shot's own shot size and composition. Use this when the seam must connect while shot size changes.\n★If the source is not the previous shot's last frame (bookend / return to a previous image), the platform records the seam between this shot and the previous shot as an “intentional cut”, and automatic frame chaining will no longer overwrite it. If this shot already has video it will be marked for regeneration; if its first frame was uploaded by the customer or is finalized it will be rejected (409 reason=user-locked-frame, no image dispatched, no charge)—pass force:true only when overwriting it has explicit customer approval (required in every execution mode, including autopilot). force releases the upload / finalized protection and the new frame needs customer re-acceptance; for mode=reframe the quote must also carry force.",
|
|
214
214
|
"quote_align_prev_shot": "(Free quote) align_prev_shot regenerates **the previous shot's video** (deducts one video); quote before execution (quote confirmation follows execution mode: professional mode / unconfirmed plan / this step is customer-controlled → explain to the customer and proceed only after customer approval; do not decide for them; this step is autopiloted → do not ask the customer, execute per get_production_plan autopilot.default_decisions, and the platform records it in get_autopilot_log). Returns quote_id / estimated_points / prev_storyboard_id(which shot will be regenerated); if first-time portrait verification fee applies, kyc_first_time_points is listed separately.",
|
|
215
215
|
"align_prev_shot": "Seam-crack repair “align to previous shot”: this shot's first frame **does not change**; use it as the ending image and regenerate **the previous shot's video** in first/last-frame mode (previous shot's first frame unchanged), so the previous shot truly ends on this shot's opening image. Deducts one video and must include quote_id from quote_align_prev_shot. ★Use when the customer changed this shot's first frame (e.g. uploaded or regenerated a better one), but the previous shot's video is already done and you don't want to alter this shot's first frame to accommodate it. Do not use when neither shot has video yet—changing the first frame (chain_shot_from_prev / chain_shot_from) is cheaper. Async: poll get_storyboards for the previous shot's video_status.",
|
|
216
216
|
"get_scene_group_plan": "Get the scene group plan for an episode (how shots are grouped for continuous long shots). Free.",
|
|
@@ -227,9 +227,9 @@
|
|
|
227
227
|
"audit_seam_directions": "出视频前的接缝方向对照(提示性,不拦任何步骤):对每对相邻镜拿「上一镜尾帧(没有就首帧)↔ 本镜首帧」看五件事——同一主体在画面左右跳边(视线也反了会一并写明)、运动方向反了、景别跳级(同一主体大远景↔特写)。单镜都对、拼起来跳,多半是这几维。视线单独反向、主光方向会被观察但不报:生产回放里这两维误报率太高(宁漏不扰)。与 audit_seams 互补:那个比身份/服装/道具/物体状态,不管方向和位置。★何时调:首帧(和要的尾帧)都出完、chain_frames 跑过之后,review_frames / generate_videos 之前。换场、声明跳切、插入镜、字卡黑场的接缝自动跳过。★先 dry_run(默认,免费):回待观察接缝与 estimated_points(上界)/ typical_points(通常花费),两个都告诉客户,按实际文本 token 扣费;客户同意后传 dry_run=false + confirm_usage_billing=true。执行是异步的,立即返回;过一两分钟用 get_seam_directions 读结论。已观察过且两侧帧没换的接缝不重复扣费。",
|
|
228
228
|
"get_seam_directions": "(免费)读 audit_seam_directions 的结论:issues 每条带接缝镜号、问题(主体跳边、运动反向、景别跳级)与 fixes 修复建议(chain_shot_from mode=reframe 以上一镜尾帧为锚重出本镜首帧 / update_shot 写明朝向后 generate_shot_frame / 上一镜已出视频时 align_prev_shot / split_shot 插过渡景别)。结论是提示性的:讲给客户,由客户挑要修的;有意的反打、转身、冲击剪辑可忽略。not_audited>0 = 还有接缝没观察或帧已换过;running=true = 还在跑。review_frames 的 seam_direction_advisory 是同一份结论的摘要。本工具只看出视频前的静帧;视频出完后查接缝用 preview_seams(免费短片预览)。",
|
|
229
229
|
"chain_frames": "整集首尾帧接力链:让每镜首帧承接上镜尾帧,镜间画面连续(比各镜独立出帧更顺)。★何时调:首帧出完、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。执行后改了首帧的镜若已有视频会被标为待重生。★执行只派发 reframe、不等出图:用 get_jobs 看这些镜的 first_frame 出图行,等 pending/processing 全部结束(failed 的看 error_msg,单道用 chain_shot_from 重接;旧首帧还在时 get_storyboards 的 frame_status 仍是 ready、看不出失败),再用 get_storyboards 核对 seam_state、review_frames——提前审会审到旧首帧,token 随后作废。",
|
|
230
|
-
"chain_shot_from_prev": "(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图。★适用:两镜是同一机位、同一景别的延续(seam_state=unchained/broken 且本镜本来就该和上镜一个构图)。★别用于景别有变化的缝(全景→近景等):那会把本镜的景别设计冲掉,且后续出图可能被判「与设计不符」——这种缝用 chain_shot_from 的 mode=reframe
|
|
231
|
-
"quote_chain_shot_from": "(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决定;本环节托管 → 不问客户,照 get_production_plan 的 autopilot.default_decisions 执行,平台记进 get_autopilot_log)。回 quote_id / estimated_points;quote_id 一次性、只对这一镜有效。mode=copy
|
|
232
|
-
"chain_shot_from": "把同一集**任一镜**的首帧或尾帧接为本镜首帧。两种落法:\n· mode=copy(默认,免费):本镜首帧直接换成源帧,画面逐像素相同——适合「回到一模一样的画面」或同机位延续。\n· mode=reframe(扣一张图,必须带 quote_chain_shot_from 的 quote_id):以源帧为锚、按本镜画面描述重生首帧——人物/服装/道具/光线/场景延续,但保留本镜自己的景别与构图。景别有变化的缝要接,用这个。\n★源不是上一镜尾帧时(首尾呼应/回到某个画面)
|
|
230
|
+
"chain_shot_from_prev": "(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图。★适用:两镜是同一机位、同一景别的延续(seam_state=unchained/broken 且本镜本来就该和上镜一个构图)。★别用于景别有变化的缝(全景→近景等):那会把本镜的景别设计冲掉,且后续出图可能被判「与设计不符」——这种缝用 chain_shot_from 的 mode=reframe。本镜已有视频的会被标为待重生。本镜首帧若是客户上传的(first_frame_source=upload)或已定稿(first_frame_pinned)会被拒(409 reason=user-locked-frame);覆盖它(任何执行模式都须客户明确同意,托管也不例外)才传 force:true(会解除上传 / 定稿保护,新图需客户重新验收)。",
|
|
231
|
+
"quote_chain_shot_from": "(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决定;本环节托管 → 不问客户,照 get_production_plan 的 autopilot.default_decisions 执行,平台记进 get_autopilot_log)。回 quote_id / estimated_points;quote_id 一次性、只对这一镜有效。mode=copy 不需要报价。本镜首帧是客户上传的或已定稿的:不带 force 不出报价(409 reason=user-locked-frame,不计价);客户明确同意替换后报价与执行都带 force:true。",
|
|
232
|
+
"chain_shot_from": "把同一集**任一镜**的首帧或尾帧接为本镜首帧。两种落法:\n· mode=copy(默认,免费):本镜首帧直接换成源帧,画面逐像素相同——适合「回到一模一样的画面」或同机位延续。\n· mode=reframe(扣一张图,必须带 quote_chain_shot_from 的 quote_id):以源帧为锚、按本镜画面描述重生首帧——人物/服装/道具/光线/场景延续,但保留本镜自己的景别与构图。景别有变化的缝要接,用这个。\n★源不是上一镜尾帧时(首尾呼应/回到某个画面),平台会把本镜与上一镜的缝记为「有意切换」,自动帧链不会再覆盖它。本镜已有视频的会被标为待重生;首帧是客户上传的或已定稿的会被拒(409 reason=user-locked-frame,不派图不扣费),覆盖它(任何执行模式都须客户明确同意,托管也不例外)才传 force:true(会解除上传 / 定稿保护,新图需客户重新验收;mode=reframe 的报价也要带 force)。",
|
|
233
233
|
"quote_align_prev_shot": "(免费报价)align_prev_shot 会重生**上一镜的视频**(扣一条视频),执行前先报价(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决定;本环节托管 → 不问客户,照 get_production_plan 的 autopilot.default_decisions 执行,平台记进 get_autopilot_log)。回 quote_id / estimated_points / prev_storyboard_id(被重生的是哪一镜);含首次人像核验费时另列 kyc_first_time_points。",
|
|
234
234
|
"align_prev_shot": "缝裂修复「对齐上一镜」:本镜首帧**不动**,以它为收尾画面、用首尾帧模式重生**上一镜的视频**(上一镜首帧不变),让上一镜真实收在本镜的开场画面上。扣一条视频,必须带 quote_align_prev_shot 的 quote_id。★适用:客户换过本镜首帧(比如上传或重生了一张更满意的),而上一镜的视频已经出好、不想改本镜首帧去迁就它。两镜都还没出视频时别用它——改首帧(chain_shot_from_prev / chain_shot_from)更便宜。异步:轮询 get_storyboards 看上一镜 video_status。",
|
|
235
235
|
"get_scene_group_plan": "查某一集的场景组规划(镜头如何归组做连续长镜)。免费。",
|
package/dist/tools/produce.js
CHANGED
|
@@ -2471,24 +2471,31 @@ export function registerProduceTools(server, client) {
|
|
|
2471
2471
|
'★适用:两镜是同一机位、同一景别的延续(seam_state=unchained/broken 且本镜本来就该和上镜一个构图)。' +
|
|
2472
2472
|
'★别用于景别有变化的缝(全景→近景等):那会把本镜的景别设计冲掉,且后续出图可能被判「与设计不符」——' +
|
|
2473
2473
|
'这种缝用 chain_shot_from 的 mode=reframe。本镜已有视频的会被标为待重生。' +
|
|
2474
|
-
'
|
|
2474
|
+
'本镜首帧若是客户上传的(first_frame_source=upload)或已定稿(first_frame_pinned)会被拒(409 reason=user-locked-frame);' +
|
|
2475
|
+
'覆盖它' + ALWAYS_ASK('') + '才传 force:true(会解除上传 / 定稿保护,新图需客户重新验收)。', {
|
|
2475
2476
|
storyboard_id: z.number().int().positive().describe('要改首帧的那一镜(缝的右侧)'),
|
|
2476
|
-
force: z.boolean().optional().describe('
|
|
2477
|
+
force: z.boolean().optional().describe('仅当客户明确同意覆盖其上传或已定稿的首帧时传 true'),
|
|
2477
2478
|
}, async ({ storyboard_id, force }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/chain-from-prev`, force ? { force: true } : {})));
|
|
2478
2479
|
server.tool('quote_chain_shot_from', '(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价' + MODE_DECIDES('报价确认') + '。' +
|
|
2479
|
-
'回 quote_id / estimated_points;quote_id 一次性、只对这一镜有效。mode=copy 不需要报价。'
|
|
2480
|
+
'回 quote_id / estimated_points;quote_id 一次性、只对这一镜有效。mode=copy 不需要报价。' +
|
|
2481
|
+
'本镜首帧是客户上传的或已定稿的:不带 force 不出报价(409 reason=user-locked-frame,不计价);' +
|
|
2482
|
+
'客户明确同意替换后报价与执行都带 force:true。', {
|
|
2483
|
+
storyboard_id: z.number().int().positive().describe('要重生首帧的那一镜'),
|
|
2484
|
+
force: z.boolean().optional().describe('仅当客户明确同意替换其上传或已定稿的首帧时传 true'),
|
|
2485
|
+
}, async ({ storyboard_id, force }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/chain-from/quote`, force ? { force: true } : {})));
|
|
2480
2486
|
server.tool('chain_shot_from', '把同一集**任一镜**的首帧或尾帧接为本镜首帧。两种落法:\n' +
|
|
2481
2487
|
'· mode=copy(默认,免费):本镜首帧直接换成源帧,画面逐像素相同——适合「回到一模一样的画面」或同机位延续。\n' +
|
|
2482
2488
|
'· mode=reframe(扣一张图,必须带 quote_chain_shot_from 的 quote_id):以源帧为锚、按本镜画面描述重生首帧——' +
|
|
2483
2489
|
'人物/服装/道具/光线/场景延续,但保留本镜自己的景别与构图。景别有变化的缝要接,用这个。\n' +
|
|
2484
2490
|
'★源不是上一镜尾帧时(首尾呼应/回到某个画面),平台会把本镜与上一镜的缝记为「有意切换」,自动帧链不会再覆盖它。' +
|
|
2485
|
-
'
|
|
2491
|
+
'本镜已有视频的会被标为待重生;首帧是客户上传的或已定稿的会被拒(409 reason=user-locked-frame,不派图不扣费),' +
|
|
2492
|
+
'覆盖它' + ALWAYS_ASK('') + '才传 force:true(会解除上传 / 定稿保护,新图需客户重新验收;mode=reframe 的报价也要带 force)。', {
|
|
2486
2493
|
storyboard_id: z.number().int().positive().describe('要改首帧的那一镜'),
|
|
2487
2494
|
source_storyboard_id: z.number().int().positive().describe('源镜 id(必须同一集);接上一镜就传上一镜的 id'),
|
|
2488
2495
|
source_frame: z.enum(['first', 'last']).optional().describe('取源镜的哪一帧,默认 last(尾帧)'),
|
|
2489
2496
|
mode: z.enum(['copy', 'reframe']).optional().describe('默认 copy(免费);reframe 需 quote_id'),
|
|
2490
2497
|
quote_id: z.string().optional().describe('mode=reframe 时必填,来自 quote_chain_shot_from'),
|
|
2491
|
-
force: z.boolean().optional().describe('
|
|
2498
|
+
force: z.boolean().optional().describe('仅当客户明确同意覆盖其上传或已定稿的首帧时传 true'),
|
|
2492
2499
|
}, async ({ storyboard_id, source_storyboard_id, source_frame, mode, quote_id, force }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/chain-from`, {
|
|
2493
2500
|
source_storyboard_id,
|
|
2494
2501
|
...(source_frame ? { source_frame } : {}),
|
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.216",
|
|
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.216 tool surface (operationIds match MCP tool names 1:1)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
|
9
9
|
{
|
|
@@ -13431,7 +13431,7 @@
|
|
|
13431
13431
|
"post": {
|
|
13432
13432
|
"operationId": "chain_shot_from",
|
|
13433
13433
|
"summary": "把同一集**任一镜**的首帧或尾帧接为本镜首帧",
|
|
13434
|
-
"description": "把同一集**任一镜**的首帧或尾帧接为本镜首帧。两种落法:\n· mode=copy(默认,免费):本镜首帧直接换成源帧,画面逐像素相同——适合「回到一模一样的画面」或同机位延续。\n· mode=reframe(扣一张图,必须带 quote_chain_shot_from 的 quote_id):以源帧为锚、按本镜画面描述重生首帧——人物/服装/道具/光线/场景延续,但保留本镜自己的景别与构图。景别有变化的缝要接,用这个。\n★源不是上一镜尾帧时(首尾呼应/回到某个画面)
|
|
13434
|
+
"description": "把同一集**任一镜**的首帧或尾帧接为本镜首帧。两种落法:\n· mode=copy(默认,免费):本镜首帧直接换成源帧,画面逐像素相同——适合「回到一模一样的画面」或同机位延续。\n· mode=reframe(扣一张图,必须带 quote_chain_shot_from 的 quote_id):以源帧为锚、按本镜画面描述重生首帧——人物/服装/道具/光线/场景延续,但保留本镜自己的景别与构图。景别有变化的缝要接,用这个。\n★源不是上一镜尾帧时(首尾呼应/回到某个画面),平台会把本镜与上一镜的缝记为「有意切换」,自动帧链不会再覆盖它。本镜已有视频的会被标为待重生;首帧是客户上传的或已定稿的会被拒(409 reason=user-locked-frame,不派图不扣费),覆盖它(任何执行模式都须客户明确同意,托管也不例外)才传 force:true(会解除上传 / 定稿保护,新图需客户重新验收;mode=reframe 的报价也要带 force)。",
|
|
13435
13435
|
"tags": [
|
|
13436
13436
|
"storyboards"
|
|
13437
13437
|
],
|
|
@@ -13519,7 +13519,7 @@
|
|
|
13519
13519
|
"post": {
|
|
13520
13520
|
"operationId": "chain_shot_from_prev",
|
|
13521
13521
|
"summary": "(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图",
|
|
13522
|
-
"description": "(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图。★适用:两镜是同一机位、同一景别的延续(seam_state=unchained/broken 且本镜本来就该和上镜一个构图)。★别用于景别有变化的缝(全景→近景等):那会把本镜的景别设计冲掉,且后续出图可能被判「与设计不符」——这种缝用 chain_shot_from 的 mode=reframe
|
|
13522
|
+
"description": "(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图。★适用:两镜是同一机位、同一景别的延续(seam_state=unchained/broken 且本镜本来就该和上镜一个构图)。★别用于景别有变化的缝(全景→近景等):那会把本镜的景别设计冲掉,且后续出图可能被判「与设计不符」——这种缝用 chain_shot_from 的 mode=reframe。本镜已有视频的会被标为待重生。本镜首帧若是客户上传的(first_frame_source=upload)或已定稿(first_frame_pinned)会被拒(409 reason=user-locked-frame);覆盖它(任何执行模式都须客户明确同意,托管也不例外)才传 force:true(会解除上传 / 定稿保护,新图需客户重新验收)。",
|
|
13523
13523
|
"tags": [
|
|
13524
13524
|
"storyboards"
|
|
13525
13525
|
],
|
|
@@ -13582,7 +13582,7 @@
|
|
|
13582
13582
|
"post": {
|
|
13583
13583
|
"operationId": "quote_chain_shot_from",
|
|
13584
13584
|
"summary": "(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决",
|
|
13585
|
-
"description": "(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决定;本环节托管 → 不问客户,照 get_production_plan 的 autopilot.default_decisions 执行,平台记进 get_autopilot_log)。回 quote_id / estimated_points;quote_id 一次性、只对这一镜有效。mode=copy
|
|
13585
|
+
"description": "(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决定;本环节托管 → 不问客户,照 get_production_plan 的 autopilot.default_decisions 执行,平台记进 get_autopilot_log)。回 quote_id / estimated_points;quote_id 一次性、只对这一镜有效。mode=copy 不需要报价。本镜首帧是客户上传的或已定稿的:不带 force 不出报价(409 reason=user-locked-frame,不计价);客户明确同意替换后报价与执行都带 force:true。",
|
|
13586
13586
|
"tags": [
|
|
13587
13587
|
"storyboards"
|
|
13588
13588
|
],
|
|
@@ -13598,6 +13598,21 @@
|
|
|
13598
13598
|
}
|
|
13599
13599
|
}
|
|
13600
13600
|
],
|
|
13601
|
+
"requestBody": {
|
|
13602
|
+
"required": false,
|
|
13603
|
+
"content": {
|
|
13604
|
+
"application/json": {
|
|
13605
|
+
"schema": {
|
|
13606
|
+
"type": "object",
|
|
13607
|
+
"properties": {
|
|
13608
|
+
"force": {
|
|
13609
|
+
"type": "boolean"
|
|
13610
|
+
}
|
|
13611
|
+
}
|
|
13612
|
+
}
|
|
13613
|
+
}
|
|
13614
|
+
}
|
|
13615
|
+
},
|
|
13601
13616
|
"responses": {
|
|
13602
13617
|
"200": {
|
|
13603
13618
|
"description": "StarReel envelope",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starreel/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.216",
|
|
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.216",
|
|
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.216",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
},
|