@starreel/mcp 0.1.96 → 0.1.98
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 +58 -5
- package/dist/tools/guide-data.js +8 -2
- package/dist/tools/produce.js +95 -12
- package/openapi.json +362 -9
- 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.
|
|
@@ -180,7 +182,13 @@ content that will be rejected.
|
|
|
180
182
|
and `typical_points` is what it usually costs. Give the user both — the upper
|
|
181
183
|
bound alone reads as far more expensive than the job really is, and the
|
|
182
184
|
typical figure alone under-funds the run. Fixed-price models (the Nano Banana
|
|
183
|
-
family) return the two equal.
|
|
185
|
+
family) return the two equal. **Storyboards** are a range for the same
|
|
186
|
+
reason: the AI decides how many shots the script needs, so the shot count
|
|
187
|
+
(`estimated_shots`) is an estimate. The storyboard quote also includes the
|
|
188
|
+
work that runs **automatically** right after breaking (filling empty shot
|
|
189
|
+
fields, one call per shot; a wardrobe timeline when the drama has wardrobe
|
|
190
|
+
assets) — see `price_breakdown`; it is billed together with the breakdown,
|
|
191
|
+
so quote the user the total. Other AI-generation steps (TTS, posters, sheets,
|
|
184
192
|
style locks, MV story/script …) have no quote and bill by usage — still tell
|
|
185
193
|
the user before running them. Never auto-approve large spends for the user.
|
|
186
194
|
|
|
@@ -287,6 +295,36 @@ content that will be rejected.
|
|
|
287
295
|
**9.4%** of the time versus **40.2%** with one. `generate_shot_frame` does accept
|
|
288
296
|
`allow_missing_terminal: true` for the rare shot that genuinely should barely change,
|
|
289
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).
|
|
290
328
|
**Image model**: images use a drama-level model (default **ChatGPT Image 2.5
|
|
291
329
|
Flare** = `gpt-image-2.5-flare`), set via `create_drama` /
|
|
292
330
|
`update_project_settings` field `image_model` for one consistent look across
|
|
@@ -570,8 +608,16 @@ When the frame or the motion is off in a way the business text cannot express,
|
|
|
570
608
|
edit the shot's prompt bodies directly: `get_shot_prompts` reads the current
|
|
571
609
|
`image_prompt` / `video_prompt` for one shot, `update_shot` writes them back.
|
|
572
610
|
Keep the `@char:N` / `@scene:M` markers the response lists under `asset_tokens`
|
|
573
|
-
|
|
574
|
-
|
|
611
|
+
as they are — but know what they do. They are a supplementary reference channel
|
|
612
|
+
for frame rendering only. Which characters' portraits and which scene plate are
|
|
613
|
+
injected is decided by the shot's bindings, `character_ids` and `scene_id`, which
|
|
614
|
+
`get_storyboards` returns per shot (with `character_bindings`, `prop_ids`,
|
|
615
|
+
`active_wardrobe_id`). Dropping a marker does not take a bound character out of
|
|
616
|
+
the frame; writing a marker for an unbound character pulls that character's image
|
|
617
|
+
in; a `#variant` marker is the only source of that variant image. To take someone
|
|
618
|
+
out of a shot, change `character_ids` (it is a full overwrite — read the current
|
|
619
|
+
list first). If they only speak off-screen, keep them bound and mark them
|
|
620
|
+
`voice_only` through `update_shot`'s `character_presence`. The prompt body
|
|
575
621
|
is only the part you write: the platform still layers identity anchors and
|
|
576
622
|
consistency constraints on top at generation time. Editing a prompt does not
|
|
577
623
|
re-generate anything — regenerate the shot afterwards.
|
|
@@ -776,6 +822,11 @@ Four distinct causes; they need **opposite** fixes, so identify the family first
|
|
|
776
822
|
|
|
777
823
|
### "切太快" / "一个镜头里画面跳来跳去"
|
|
778
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
|
+
|
|
779
830
|
Run **`scan_intra_shot_cuts`** (free) before touching anything. What a viewer
|
|
780
831
|
perceives as cutting speed is *shot seams + cuts the vendor made inside a single
|
|
781
832
|
shot*, and the second half is invisible in the shot list, in the timeline, and
|
|
@@ -959,7 +1010,9 @@ to close") tells the vendor to fit that entire sequence into each 3-second shot.
|
|
|
959
1010
|
or `enabled: false` means the user has to switch it on in the drama settings.
|
|
960
1011
|
- **Shots → video**: `quote/generate_storyboards`, `get_storyboards`,
|
|
961
1012
|
`quote/generate_frames`, `tail_frame_plan` (free — which shots need their own
|
|
962
|
-
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`
|
|
963
1016
|
- **Audio**: `generate_tts` (required before final cut), `clone_voice`,
|
|
964
1017
|
`design_voice` → `get_voice_design` → `save_designed_voice` (no sample needed),
|
|
965
1018
|
`speak_with_voice`, `set_character_voice`, `list_voices`, `delete_voice`,
|
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
|
@@ -497,8 +497,11 @@ export function registerProduceTools(server, client) {
|
|
|
497
497
|
'定妆图齐了再调一次即批量出设定图。避免只出定妆图导致镜头漂移。图片步,按用量后付不欠费。' +
|
|
498
498
|
'轮询 get_characters 看 image/sheet_url 就绪;每调一次推进一步。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/portraits-and-sheets`)));
|
|
499
499
|
// ---------- 拆镜(storyboards) ----------
|
|
500
|
-
server.tool('quote_storyboards', '报价:把某一集的剧本拆成分镜(storyboards)
|
|
501
|
-
'
|
|
500
|
+
server.tool('quote_storyboards', '报价:把某一集的剧本拆成分镜(storyboards)要多少点。零扣费。返回 quote_id 与一个**区间**:' +
|
|
501
|
+
'estimated_points=预算上沿(按它备余额,拆到一半不会 402)、typical_points=通常花费——两个都告诉用户,' +
|
|
502
|
+
'只报上沿显得贵得离谱,只报典型又会让余额备不够。拆出几镜由 AI 按剧本决定(estimated_shots 是估算),故无法精确到点。' +
|
|
503
|
+
'★price_breakdown 里除「拆镜」外还有拆完**自动**触发的补全(每镜补空字段;有服装资产时排服装时间线)——' +
|
|
504
|
+
'它们随拆镜一起发生、会一起扣费,告诉用户总数时要含在内。拿到后征求同意,再用 quote_id 调 generate_storyboards。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/storyboards/quote`)));
|
|
502
505
|
server.tool('generate_storyboards', '确认后拆镜:后台跑(分钟级),立即返回 status:generating。用 get_storyboards 轮询。' +
|
|
503
506
|
'★注意:拆镜会**替换整集所有已有分镜**(已调好/已出图的全丢、要重花钱重来)。每镜 5-7 秒是对 AI 出视频' +
|
|
504
507
|
'优化的**正常**时长,别因「一镜偏长」觉得有问题就重拆。已有分镜时后端会拦,确认重拆才带 confirm_replace=true。' +
|
|
@@ -536,7 +539,19 @@ export function registerProduceTools(server, client) {
|
|
|
536
539
|
'修复正路是删掉外部图改走 generate_shot_frame 平台重生。' +
|
|
537
540
|
'★若某镜带 reopen_pair_id:该镜首尾帧同时生成时只有一侧真的有问题、另一侧是无辜陪拒,' +
|
|
538
541
|
'原样传给 generate_shot_frame 的 reopen_pair_id 参数可以只重掷有问题的那一侧(省一半算力/费用,' +
|
|
539
|
-
'不会拿去生成一张这次根本没打算重做的图)。没有这个字段就按 fail_reason/retryable 走常规重试。免费。'
|
|
542
|
+
'不会拿去生成一张这次根本没打算重做的图)。没有这个字段就按 fail_reason/retryable 走常规重试。免费。' +
|
|
543
|
+
'★每镜还带**绑定**(只有 ID):character_ids(本镜绑定的角色)、character_bindings[{character_id,presence}]' +
|
|
544
|
+
'(presence=on_screen 在画面 / voice_only 只有声音、不进画面)、scene_id、prop_ids、active_wardrobe_id。' +
|
|
545
|
+
'出图注入谁的定妆图/哪张场景图/哪些道具图由这几项决定;角色名对照 get_characters、道具名对照 get_props。' +
|
|
546
|
+
'改绑用 update_shot 的 character_ids(★全量覆盖,先从这里读现值再改,漏传即解绑)与 character_presence;' +
|
|
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`)));
|
|
540
555
|
// ---------- 在途运行状态(免费):区分「还在跑」和「已经死了」----------
|
|
541
556
|
server.tool('get_run_status', '(★免费·长耗时操作后必用)查这一集当前有没有 agent 正在跑。' +
|
|
542
557
|
'rewrite_script / extract_assets / generate_storyboards 都是**分钟级**后台任务,' +
|
|
@@ -637,7 +652,10 @@ export function registerProduceTools(server, client) {
|
|
|
637
652
|
server.tool('review_frames', '【第③道硬闸·免费】审查镜头图片层:角色身份锚覆盖(缺定妆图的角色在镜头里必漂)、出图失败率、' +
|
|
638
653
|
'孤儿角色变体、场景图被人物污染。★generate_videos 之前必须先跑本工具——出视频是全链最贵的一步,' +
|
|
639
654
|
'拿着漂移的首帧整集出视频是最典型的废片形态。按 findings.action 修完(多为 generate_character_portraits / ' +
|
|
640
|
-
'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`)));
|
|
641
659
|
server.tool('review_all', '(推荐·免费)三层一次跑完的整体体检:剧本+分镜+镜头图片。开工前摸底、交付前复查用。' +
|
|
642
660
|
'★它**不发 review_token** —— 进收费步前仍需对应层的 review_script / review_storyboards / review_frames 各跑一次' +
|
|
643
661
|
'(闸认的是「针对当前产出物刚审过」,不是「审过一次」)。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/all`)));
|
|
@@ -1215,15 +1233,18 @@ export function registerProduceTools(server, client) {
|
|
|
1215
1233
|
const suffix = qs.toString() ? `?${qs.toString()}` : '';
|
|
1216
1234
|
return jsonResult(await client.produceGet(`/episodes/${episode_id}/dialogue-coverage${suffix}`));
|
|
1217
1235
|
});
|
|
1218
|
-
server.tool('update_shot', '逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、时长(duration)、成片变速(speed_factor)
|
|
1236
|
+
server.tool('update_shot', '逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、时长(duration)、成片变速(speed_factor)、角色绑定(character_ids)与画外音标记(character_presence)。只传要改的字段、其余不动。' +
|
|
1219
1237
|
'**免费**(纯文本写库)。★改 dialogue 会自动失效本镜已生成的 TTS 配音与字幕(需重出 tts);' +
|
|
1220
|
-
'改文本不会自动重出图/视频,如需让画面跟上文本改动,改完再 regen 对应镜。用 get_storyboards
|
|
1238
|
+
'改文本不会自动重出图/视频,如需让画面跟上文本改动,改完再 regen 对应镜。用 get_storyboards 查改后结果(每镜带 character_ids / character_bindings / scene_id / prop_ids)。' +
|
|
1221
1239
|
'★★原声镜(厂商原生音频)改 dialogue 后,本镜视频会被标记「待重生」——因为台词是**烤进视频人声**的,' +
|
|
1222
1240
|
'不重生就终拼,成片里念的仍是改动前的台词(典型现象:台词像是跑到了别的镜头上)。' +
|
|
1223
1241
|
'compose_episode 会以 advisory `stale_video_after_edit` 列出这些镜;正确处置是先 regenerate_shot_video 再终拼。' +
|
|
1224
1242
|
'★也可直接改本镜的四条提示词正文(image_prompt/video_prompt/first_frame_prompt/last_frame_prompt):' +
|
|
1225
1243
|
'改前先用 get_shot_prompts 读现值,' +
|
|
1226
|
-
'别凭空覆盖——正文里的 @char:N / @scene:M
|
|
1244
|
+
'别凭空覆盖——正文里的 @char:N / @scene:M 是出图时的补充参考标记,照原样保留即可。' +
|
|
1245
|
+
'★注入谁的定妆图由 character_ids 决定、背景由 scene_id 决定:删标记不会让已绑定的人从画面消失,' +
|
|
1246
|
+
'要让某人不出现就改 character_ids,他只有声音(画外音)就用 character_presence 标 voice_only;' +
|
|
1247
|
+
'反过来别给未绑定的角色写 @char 标记——会把他的图注入进来。' +
|
|
1227
1248
|
'★★【出尾帧被拦下就是来改这里】出尾帧若报「此镜标为状态改变,但没有任何地方说明结束时是什么样子」' +
|
|
1228
1249
|
'(TERMINAL_DESC_GATE),修法是把**结束时画面是什么样**写进本镜 last_frame_prompt,然后重新出尾帧。' +
|
|
1229
1250
|
'别去重试出图——这类镜(action_motion_class=state_change 却没写终态)的尾帧历史成功率 9.4%,' +
|
|
@@ -1232,6 +1253,14 @@ export function registerProduceTools(server, client) {
|
|
|
1232
1253
|
storyboard_id: z.number().int().positive(),
|
|
1233
1254
|
character_ids: z.array(z.number().int().positive()).optional()
|
|
1234
1255
|
.describe('本镜出场角色 ID 列表(★全量覆盖式,非增量,漏传的角色会被解绑)。决定出图时注入哪些角色的定妆图/设定图——非人角色(动物/生物)也必须绑定,否则形象会漂移。id 必须来自当前集已关联角色'),
|
|
1256
|
+
character_presence: z.array(z.object({
|
|
1257
|
+
character_id: z.number().int().positive(),
|
|
1258
|
+
presence: z.enum(['on_screen', 'voice_only']),
|
|
1259
|
+
})).optional()
|
|
1260
|
+
.describe('画外音标记:[{character_id, presence}]。voice_only = 这一镜他只有声音、人不在画面(画外音/门外说话/电话那头)——' +
|
|
1261
|
+
'出图时他的定妆图、人脸锁、站位、主体脸锚全部跳过,台词与配音不受影响;on_screen = 恢复在画面。' +
|
|
1262
|
+
'角色必须在本镜绑定里(可与 character_ids 同一请求,先改绑再标)。只列要改的角色,没列的不动。' +
|
|
1263
|
+
'★完全没出现在画面、台词也不是他说的 → 直接从 character_ids 去掉,不用标 voice_only'),
|
|
1235
1264
|
title: z.string().optional().describe('镜头标题'),
|
|
1236
1265
|
description: z.string().optional().describe('画面描述'),
|
|
1237
1266
|
shot_type: z.string().optional().describe('景别(如 特写/中景/全景/远景)'),
|
|
@@ -1246,7 +1275,7 @@ export function registerProduceTools(server, client) {
|
|
|
1246
1275
|
shot_intent: z.string().optional().describe('这镜为什么存在(叙事意图)'),
|
|
1247
1276
|
duration: z.number().positive().optional().describe('本镜时长(秒,可带小数如 2.5)。上限=本剧视频引擎的单镜上限,超出直接拒并告知上限(更长内容用 split_shot 拆镜)。有台词时平台按语速律只抬不降,抬了会在回执 speech_duration_note 里说。★改时长不会自动重出视频:已有视频仍是旧长度,要厂商按新时长出就 regenerate_shot_video(报价按新时长算)。★别拿加长治「动作太慢」——同样的动作摊到更长时间里只会更慢,见 qa_tools「动作太慢」'),
|
|
1248
1277
|
speed_factor: z.number().positive().nullable().optional().describe('成片变速:<1 慢镜、>1 快放、null 清除(0.5–2.0,越界被钳到范围内)。只在终拼/剪映导出时变速播放(画面 setpts + 声音 atempo,音高不变),**不重出视频、不扣费**,但会改变本镜在成片里占的时长。适合做慢镜/升格氛围;治不了「动作没演出来」——那是视频内容本身,要改 video_prompt 重出;也治不了一镜塞太多动作(action_overload)——那要拆镜重出。有台词的镜慎用(人声也跟着变快变慢)'),
|
|
1249
|
-
image_prompt: z.string().optional().describe('首帧画面提示词**正文**(全量覆盖本镜现值)。★先 get_shot_prompts 读现值再改;★原样保留其中的 @char:N / @scene:M
|
|
1278
|
+
image_prompt: z.string().optional().describe('首帧画面提示词**正文**(全量覆盖本镜现值)。★先 get_shot_prompts 读现值再改;★原样保留其中的 @char:N / @scene:M 补充参考标记(注入谁由 character_ids / scene_id 决定,删标记不会让已绑定的人消失)。出图时平台会在正文之上再拼身份锚与一致性约束,不必你写。★写法坑:别写「no X / without X / 不要 X / 没有 X」这类否定式约束——图像模型把名词当正向线索,反而把 X 画出来;要正向写出那块画面该有什么(材质/形状/颜色/远近)。保存响应带 image_prompt_negation_advisory 即命中,按其 note 改写'),
|
|
1250
1279
|
video_prompt: z.string().optional().describe('视频(动态/运镜/表演)提示词**正文**(全量覆盖本镜现值)。★同 image_prompt:先读现值、保留 @char/@scene 标记'),
|
|
1251
1280
|
first_frame_prompt: z.string().optional().describe('本镜**开始时**画面是什么样(首帧目标状态正文,全量覆盖现值)。送达提示词里作为 [START FRAME] 段排在最前,优先级高于 image_prompt——所以 image_prompt 改了不生效时,往往是这条在压着它。★同 image_prompt:先 get_shot_prompts 读现值、原样保留 @char/@scene 标记'),
|
|
1252
1281
|
last_frame_prompt: z.string().optional().describe('本镜**结束时**画面是什么样(尾帧目标状态正文,全量覆盖现值)。送达提示词里作为 [END FRAME] 段。★★出尾帧被 TERMINAL_DESC_GATE 拦下时就是补这一条:写清结束时的状态(什么变了/变成什么样),再重新出尾帧。不补而直接重试必然重复被拒且照常扣费。get_shot_prompts 的 terminal_desc_missing=true 即本镜需要它'),
|
|
@@ -1258,9 +1287,10 @@ export function registerProduceTools(server, client) {
|
|
|
1258
1287
|
'first_frame_prompt=开始时什么样 / last_frame_prompt=结束时什么样),供直接微调后用 update_shot 写回。免费。' +
|
|
1259
1288
|
'★回执里的 terminal_desc_missing=true 表示本镜标为「状态改变」却三处都没说终态——' +
|
|
1260
1289
|
'出尾帧会被前置闸拦下,修法是把结束状态写进 last_frame_prompt(别重试出图,重试必然重复被拒且照常扣费)。' +
|
|
1261
|
-
'★逐镜按需:改哪镜读哪镜(整集列表 get_storyboards
|
|
1262
|
-
'★返回的 asset_tokens
|
|
1263
|
-
'
|
|
1290
|
+
'★逐镜按需:改哪镜读哪镜(整集列表 get_storyboards 不含提示词)。' +
|
|
1291
|
+
'★返回的 asset_tokens 是正文里的补充参考标记(@char:N / @scene:M),改写时原样保留即可:' +
|
|
1292
|
+
'本镜注入谁的定妆图由绑定决定(get_storyboards 的 character_ids / scene_id),删标记不会让已绑定的人消失;' +
|
|
1293
|
+
'带 #变体 的标记是那张变体图的唯一来源;给未绑定的角色写标记会把他的图注入进来。' +
|
|
1264
1294
|
'★这是分镜表里的正文层;出图/出视频时平台还会在其上拼身份锚、一致性约束与参考图指令(不在此处,也无需你写)。' +
|
|
1265
1295
|
'改完提示词不会自动重出图/视频,要让画面跟上得再 regen 对应镜。', { storyboard_id: z.number().int().positive() }, async ({ storyboard_id }) => jsonResult(await client.produceGet(`/storyboards/${storyboard_id}/prompts`)));
|
|
1266
1296
|
server.tool('rerender_episode', '按当前 timeline 重拼成片(改完镜/裁剪后用)。**免费**(纯 ffmpeg+COS),后台异步。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/re-render`)));
|
|
@@ -1530,7 +1560,60 @@ export function registerProduceTools(server, client) {
|
|
|
1530
1560
|
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`)));
|
|
1531
1561
|
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`)));
|
|
1532
1562
|
// ========== P2 · 连续性 / 场景组 / 多画幅 ==========
|
|
1533
|
-
server.tool('chain_frames', '整集首尾帧接力链:让每镜首帧承接上镜尾帧,镜间画面连续(比各镜独立出帧更顺)
|
|
1563
|
+
server.tool('chain_frames', '整集首尾帧接力链:让每镜首帧承接上镜尾帧,镜间画面连续(比各镜独立出帧更顺)。' +
|
|
1564
|
+
'★何时调:首帧出完、tail_frame_plan 要的尾帧也补完之后,review_frames / generate_videos 之前。' +
|
|
1565
|
+
'平台只在官网批量出帧结束时自动跑一次;逐镜出帧(generate_frames / generate_shot_frame)的集多半从没接过——' +
|
|
1566
|
+
'get_storyboards 的 seam_state=unchained 就是这种缝。\n' +
|
|
1567
|
+
'★先 dry_run:true(免费,不写库不出图):回 planned_copy / planned_reframe / estimated_points / needs_last_frame。' +
|
|
1568
|
+
'copy=本镜首帧直接换成上镜尾帧(免费,但本镜景别会变成和上镜一样);reframe=以上镜尾帧为锚按本镜画面描述重生首帧' +
|
|
1569
|
+
'(每道一张图,保景别)。把计划和 estimated_points 告诉客户,确认后**不带 dry_run** 再调一次执行(按用量后付)。\n' +
|
|
1570
|
+
'★平台自己判哪道缝该接:有意切换(换场/时间跳跃/换装/插入镜)、已出视频的镜、已经接好的缝都会跳过——' +
|
|
1571
|
+
'「已接好」= 首帧就是上镜尾帧,或 reframe 接在上镜**当前**尾帧上,所以重复执行不会重复扣费。' +
|
|
1572
|
+
'上镜尾帧后来被重生过的缝会重新出现在计划里,那道缝确实断了。只补个别缝用 chain_shot_from_prev / chain_shot_from。' +
|
|
1573
|
+
'执行后改了首帧的镜若已有视频会被标为待重生。执行完用 get_storyboards 核对 seam_state。', {
|
|
1574
|
+
episode_id: z.number().int().positive(),
|
|
1575
|
+
dry_run: z.boolean().optional().describe('true=只看计划与预估(免费,推荐先调一次);不传=真执行'),
|
|
1576
|
+
}, async ({ episode_id, dry_run }) => jsonResult(await client.producePost(`/episodes/${episode_id}/chain-frames`, dry_run ? { dry_run: true } : {})));
|
|
1577
|
+
// ---------- 单道接缝修复(帧时间线「接上一镜」「对齐上一镜」的门面版) ----------
|
|
1578
|
+
server.tool('chain_shot_from_prev', '(免费)把上一镜的尾帧**直接**设为本镜首帧:画面 100% 接上,零成本、不出图。' +
|
|
1579
|
+
'★适用:两镜是同一机位、同一景别的延续(seam_state=unchained/broken 且本镜本来就该和上镜一个构图)。' +
|
|
1580
|
+
'★别用于景别有变化的缝(全景→近景等):那会把本镜的景别设计冲掉,且后续出图可能被判「与设计不符」——' +
|
|
1581
|
+
'这种缝用 chain_shot_from 的 mode=reframe。本镜已有视频的会被标为待重生。' +
|
|
1582
|
+
'本镜首帧若已被客户定稿(first_frame_pinned)会被拒;客户明确同意覆盖才传 force:true。', {
|
|
1583
|
+
storyboard_id: z.number().int().positive().describe('要改首帧的那一镜(缝的右侧)'),
|
|
1584
|
+
force: z.boolean().optional().describe('仅当客户明确同意覆盖已定稿的首帧时传 true'),
|
|
1585
|
+
}, async ({ storyboard_id, force }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/chain-from-prev`, force ? { force: true } : {})));
|
|
1586
|
+
server.tool('quote_chain_shot_from', '(免费报价)chain_shot_from 的 mode=reframe 要扣**一张图**(以源帧为锚重生本镜首帧),执行前先报价、经客户确认。' +
|
|
1587
|
+
'回 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`)));
|
|
1588
|
+
server.tool('chain_shot_from', '把同一集**任一镜**的首帧或尾帧接为本镜首帧。两种落法:\n' +
|
|
1589
|
+
'· mode=copy(默认,免费):本镜首帧直接换成源帧,画面逐像素相同——适合「回到一模一样的画面」或同机位延续。\n' +
|
|
1590
|
+
'· mode=reframe(扣一张图,必须带 quote_chain_shot_from 的 quote_id):以源帧为锚、按本镜画面描述重生首帧——' +
|
|
1591
|
+
'人物/服装/道具/光线/场景延续,但保留本镜自己的景别与构图。景别有变化的缝要接,用这个。\n' +
|
|
1592
|
+
'★源不是上一镜尾帧时(首尾呼应/回到某个画面),平台会把本镜与上一镜的缝记为「有意切换」,自动帧链不会再覆盖它。' +
|
|
1593
|
+
'本镜已有视频的会被标为待重生;首帧已定稿的会被拒,客户同意覆盖才传 force:true。', {
|
|
1594
|
+
storyboard_id: z.number().int().positive().describe('要改首帧的那一镜'),
|
|
1595
|
+
source_storyboard_id: z.number().int().positive().describe('源镜 id(必须同一集);接上一镜就传上一镜的 id'),
|
|
1596
|
+
source_frame: z.enum(['first', 'last']).optional().describe('取源镜的哪一帧,默认 last(尾帧)'),
|
|
1597
|
+
mode: z.enum(['copy', 'reframe']).optional().describe('默认 copy(免费);reframe 需 quote_id'),
|
|
1598
|
+
quote_id: z.string().optional().describe('mode=reframe 时必填,来自 quote_chain_shot_from'),
|
|
1599
|
+
force: z.boolean().optional().describe('仅当客户明确同意覆盖已定稿的首帧时传 true'),
|
|
1600
|
+
}, async ({ storyboard_id, source_storyboard_id, source_frame, mode, quote_id, force }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/chain-from`, {
|
|
1601
|
+
source_storyboard_id,
|
|
1602
|
+
...(source_frame ? { source_frame } : {}),
|
|
1603
|
+
...(mode ? { mode } : {}),
|
|
1604
|
+
...(quote_id ? { quote_id } : {}),
|
|
1605
|
+
...(force ? { force: true } : {}),
|
|
1606
|
+
})));
|
|
1607
|
+
server.tool('quote_align_prev_shot', '(免费报价)align_prev_shot 会重生**上一镜的视频**(扣一条视频),执行前先报价、经客户确认。' +
|
|
1608
|
+
'回 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`)));
|
|
1609
|
+
server.tool('align_prev_shot', '缝裂修复「对齐上一镜」:本镜首帧**不动**,以它为收尾画面、用首尾帧模式重生**上一镜的视频**(上一镜首帧不变),' +
|
|
1610
|
+
'让上一镜真实收在本镜的开场画面上。扣一条视频,必须带 quote_align_prev_shot 的 quote_id。' +
|
|
1611
|
+
'★适用:客户换过本镜首帧(比如上传或重生了一张更满意的),而上一镜的视频已经出好、不想改本镜首帧去迁就它。' +
|
|
1612
|
+
'两镜都还没出视频时别用它——改首帧(chain_shot_from_prev / chain_shot_from)更便宜。' +
|
|
1613
|
+
'异步:轮询 get_storyboards 看上一镜 video_status。', {
|
|
1614
|
+
storyboard_id: z.number().int().positive().describe('缝右侧那一镜'),
|
|
1615
|
+
quote_id: z.string().describe('来自 quote_align_prev_shot'),
|
|
1616
|
+
}, async ({ storyboard_id, quote_id }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/align-prev`, { quote_id })));
|
|
1534
1617
|
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`)));
|
|
1535
1618
|
server.tool('generate_scene_groups', '生成场景组(把连续镜头归组,连续长镜/批量出图的地基)。后台异步。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/scene-groups`)));
|
|
1536
1619
|
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.98",
|
|
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.98 tool surface (operationIds match MCP tool names 1:1)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
|
9
9
|
{
|
|
@@ -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
|
|
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
|
],
|
|
@@ -6664,7 +6679,7 @@
|
|
|
6664
6679
|
"post": {
|
|
6665
6680
|
"operationId": "quote_storyboards",
|
|
6666
6681
|
"summary": "报价:把某一集的剧本拆成分镜(storyboards)要多少点",
|
|
6667
|
-
"description": "报价:把某一集的剧本拆成分镜(storyboards)
|
|
6682
|
+
"description": "报价:把某一集的剧本拆成分镜(storyboards)要多少点。零扣费。返回 quote_id 与一个**区间**:estimated_points=预算上沿(按它备余额,拆到一半不会 402)、typical_points=通常花费——两个都告诉用户,只报上沿显得贵得离谱,只报典型又会让余额备不够。拆出几镜由 AI 按剧本决定(estimated_shots 是估算),故无法精确到点。★price_breakdown 里除「拆镜」外还有拆完**自动**触发的补全(每镜补空字段;有服装资产时排服装时间线)——它们随拆镜一起发生、会一起扣费,告诉用户总数时要含在内。拿到后征求同意,再用 quote_id 调 generate_storyboards。",
|
|
6668
6683
|
"tags": [
|
|
6669
6684
|
"episodes"
|
|
6670
6685
|
],
|
|
@@ -8685,8 +8700,8 @@
|
|
|
8685
8700
|
"/storyboards/{storyboard_id}": {
|
|
8686
8701
|
"put": {
|
|
8687
8702
|
"operationId": "update_shot",
|
|
8688
|
-
"summary": "逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、时长(duration)、成片变速(speed_factor)
|
|
8689
|
-
"description": "逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、时长(duration)、成片变速(speed_factor)
|
|
8703
|
+
"summary": "逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、时长(duration)、成片变速(speed_factor)、角色绑定(character_ids)与画外音标记(character_presence)",
|
|
8704
|
+
"description": "逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、时长(duration)、成片变速(speed_factor)、角色绑定(character_ids)与画外音标记(character_presence)。只传要改的字段、其余不动。**免费**(纯文本写库)。★改 dialogue 会自动失效本镜已生成的 TTS 配音与字幕(需重出 tts);改文本不会自动重出图/视频,如需让画面跟上文本改动,改完再 regen 对应镜。用 get_storyboards 查改后结果(每镜带 character_ids / character_bindings / scene_id / prop_ids)。★★原声镜(厂商原生音频)改 dialogue 后,本镜视频会被标记「待重生」——因为台词是**烤进视频人声**的,不重生就终拼,成片里念的仍是改动前的台词(典型现象:台词像是跑到了别的镜头上)。compose_episode 会以 advisory `stale_video_after_edit` 列出这些镜;正确处置是先 regenerate_shot_video 再终拼。★也可直接改本镜的四条提示词正文(image_prompt/video_prompt/first_frame_prompt/last_frame_prompt):改前先用 get_shot_prompts 读现值,别凭空覆盖——正文里的 @char:N / @scene:M 是出图时的补充参考标记,照原样保留即可。★注入谁的定妆图由 character_ids 决定、背景由 scene_id 决定:删标记不会让已绑定的人从画面消失,要让某人不出现就改 character_ids,他只有声音(画外音)就用 character_presence 标 voice_only;反过来别给未绑定的角色写 @char 标记——会把他的图注入进来。★★【出尾帧被拦下就是来改这里】出尾帧若报「此镜标为状态改变,但没有任何地方说明结束时是什么样子」(TERMINAL_DESC_GATE),修法是把**结束时画面是什么样**写进本镜 last_frame_prompt,然后重新出尾帧。别去重试出图——这类镜(action_motion_class=state_change 却没写终态)的尾帧历史成功率 9.4%,有终态描述的是 40.2%;不补描述就重生,送厂商的提示词里根本没有终态段,画出来仍和首帧一样、还是会被拒,而每次重生都照常扣费。get_shot_prompts 的 terminal_desc_missing=true 就是这个信号。",
|
|
8690
8705
|
"tags": [
|
|
8691
8706
|
"storyboards"
|
|
8692
8707
|
],
|
|
@@ -8715,6 +8730,30 @@
|
|
|
8715
8730
|
"exclusiveMinimum": 0
|
|
8716
8731
|
}
|
|
8717
8732
|
},
|
|
8733
|
+
"character_presence": {
|
|
8734
|
+
"type": "array",
|
|
8735
|
+
"items": {
|
|
8736
|
+
"type": "object",
|
|
8737
|
+
"properties": {
|
|
8738
|
+
"character_id": {
|
|
8739
|
+
"type": "integer",
|
|
8740
|
+
"exclusiveMinimum": 0
|
|
8741
|
+
},
|
|
8742
|
+
"presence": {
|
|
8743
|
+
"type": "string",
|
|
8744
|
+
"enum": [
|
|
8745
|
+
"on_screen",
|
|
8746
|
+
"voice_only"
|
|
8747
|
+
]
|
|
8748
|
+
}
|
|
8749
|
+
},
|
|
8750
|
+
"required": [
|
|
8751
|
+
"character_id",
|
|
8752
|
+
"presence"
|
|
8753
|
+
],
|
|
8754
|
+
"additionalProperties": false
|
|
8755
|
+
}
|
|
8756
|
+
},
|
|
8718
8757
|
"title": {
|
|
8719
8758
|
"type": "string"
|
|
8720
8759
|
},
|
|
@@ -8804,6 +8843,320 @@
|
|
|
8804
8843
|
}
|
|
8805
8844
|
}
|
|
8806
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
|
+
},
|
|
8807
9160
|
"/storyboards/{storyboard_id}/dialogue-replace": {
|
|
8808
9161
|
"post": {
|
|
8809
9162
|
"operationId": "replace_shot_dialogue",
|
|
@@ -9406,7 +9759,7 @@
|
|
|
9406
9759
|
"get": {
|
|
9407
9760
|
"operationId": "get_shot_prompts",
|
|
9408
9761
|
"summary": "读某一镜的四条提示词**正文**(image_prompt=首帧画面 / video_prompt=动态表演 / first_frame_prompt=开始时什么样 / last_frame_prompt=结束时什么样),供直接微调后用 u",
|
|
9409
|
-
"description": "读某一镜的四条提示词**正文**(image_prompt=首帧画面 / video_prompt=动态表演 / first_frame_prompt=开始时什么样 / last_frame_prompt=结束时什么样),供直接微调后用 update_shot 写回。免费。★回执里的 terminal_desc_missing=true 表示本镜标为「状态改变」却三处都没说终态——出尾帧会被前置闸拦下,修法是把结束状态写进 last_frame_prompt(别重试出图,重试必然重复被拒且照常扣费)。★逐镜按需:改哪镜读哪镜(整集列表 get_storyboards
|
|
9762
|
+
"description": "读某一镜的四条提示词**正文**(image_prompt=首帧画面 / video_prompt=动态表演 / first_frame_prompt=开始时什么样 / last_frame_prompt=结束时什么样),供直接微调后用 update_shot 写回。免费。★回执里的 terminal_desc_missing=true 表示本镜标为「状态改变」却三处都没说终态——出尾帧会被前置闸拦下,修法是把结束状态写进 last_frame_prompt(别重试出图,重试必然重复被拒且照常扣费)。★逐镜按需:改哪镜读哪镜(整集列表 get_storyboards 不含提示词)。★返回的 asset_tokens 是正文里的补充参考标记(@char:N / @scene:M),改写时原样保留即可:本镜注入谁的定妆图由绑定决定(get_storyboards 的 character_ids / scene_id),删标记不会让已绑定的人消失;带 #变体 的标记是那张变体图的唯一来源;给未绑定的角色写标记会把他的图注入进来。★这是分镜表里的正文层;出图/出视频时平台还会在其上拼身份锚、一致性约束与参考图指令(不在此处,也无需你写)。改完提示词不会自动重出图/视频,要让画面跟上得再 regen 对应镜。",
|
|
9410
9763
|
"tags": [
|
|
9411
9764
|
"storyboards"
|
|
9412
9765
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starreel/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.98",
|
|
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.98",
|
|
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.98",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
},
|