@starreel/mcp 0.1.240 → 0.1.242
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 +13 -0
- package/dist/i18n/tools.en.json +5 -1
- package/dist/i18n/tools.zh-CN.json +5 -1
- package/dist/tools/guide-data.js +1 -1
- package/dist/tools/produce.js +43 -3
- package/openapi.json +308 -5
- package/package.json +1 -1
- package/server.json +2 -2
package/SKILL.md
CHANGED
|
@@ -451,6 +451,9 @@ content that will be rejected.
|
|
|
451
451
|
To stop that run, call `cancel_videos` only when the customer asks: shots
|
|
452
452
|
already sent to the vendor still finish and are still charged; the rest are
|
|
453
453
|
not dispatched (re-quote later to continue).
|
|
454
|
+
To stop a batch image job (frames, frame chain, portraits, sheets, scene
|
|
455
|
+
images…), call `cancel_images` only when the customer asks: images already
|
|
456
|
+
sent to the vendor still finish and are still charged; the rest are not sent.
|
|
454
457
|
When a native-audio project
|
|
455
458
|
needs one seed shot per speaking character before locking voices, render those
|
|
456
459
|
seeds with the single-shot tools `quote_regenerate_shot_video` →
|
|
@@ -1187,6 +1190,16 @@ shot whose voice drifted despite the anchor. Check them in this order:
|
|
|
1187
1190
|
per episode) then `get_voice_consistency`: `summary.voice_mismatch` are shots
|
|
1188
1191
|
whose voice does not sound like the character's anchor. `uncertain` means the
|
|
1189
1192
|
spoken part was too short to judge — not a defect.
|
|
1193
|
+
3. **If regenerating would lose the first/last frames** (the vendor cannot take
|
|
1194
|
+
first/last frames and a reference voice in the same request, so frame-locked
|
|
1195
|
+
shots are voiced freely), unify the voice after the fact instead:
|
|
1196
|
+
`quote_voice_unify` → tell the customer `estimated_points` and `typical_points`
|
|
1197
|
+
→ `unify_voices(quote_id)` → `get_voice_unify_status`. It converts only the
|
|
1198
|
+
drifted speaker's lines into the anchor's timbre (per-line duration change
|
|
1199
|
+
≤0.05 s, so lip-sync and picture stay), skips shots that already carry the
|
|
1200
|
+
current anchor and match it, and keeps the original audio when QC fails.
|
|
1201
|
+
`preview_voice_unify` lets the customer listen to one shot first (free).
|
|
1202
|
+
Recompose (`rerender_episode`) for `applied` shots to reach the final cut.
|
|
1190
1203
|
|
|
1191
1204
|
### "话没说完就切" / a line gets cut off mid-word
|
|
1192
1205
|
|
package/dist/i18n/tools.en.json
CHANGED
|
@@ -136,7 +136,11 @@
|
|
|
136
136
|
"scan_burned_subtitles": "★For original-voice dramas (video has built-in human speech), recommend running once before final assembly; when the customer reports \"the final cut has two subtitle layers / an extra line of text in the image\", run this first. Video vendors sometimes ignore \"no subtitles\" constraints and burn dialogue into the image—small text, usually appearing only for one or two seconds while the line is spoken. The platform final cut then overlays another subtitle layer, creating double subtitles. Reassembling cannot remove it; only regenerate_shot_video for that shot can. Samples 12 frames per shot, one vision audit, **usage-based billing** (one small vision call per shot). Returns flagged[{shot, texts, matches_dialogue, frames}] / clean / errors. matches_dialogue=true means the recognized text is this shot's dialogue, essentially confirming vendor subtitles; text naturally present in signs, book pages, screens, etc. does not count. dry_run=true reports only and does not write back; otherwise writes back, and compose_episode final-assembly precheck will list these shots as vendor_burned_text.",
|
|
137
137
|
"scan_wardrobe_consistency": "★Run this when the customer reports \"the same character changed clothes / clothing color or style is wrong\"; also recommended before final assembly. For each shot, compare the used first frame and one mid-video frame against each character's design image in that shot (or character sheet if none) for clothing style and color. A common cause is distant small characters being drawn by the image model in different clothes—even when reference images and prompts are correct. Overall color cast from night scenes/warm lighting does not count as inconsistency. One vision audit per shot, **usage-based billing**. Returns flagged[{shot, characters:[{name, differences}]}] / clean / errors. dry_run=true reports only and does not write back; otherwise writes back, and compose_episode final-assembly precheck will list these shots as wardrobe_mismatch. Remedy: regenerate this shot's first frame (generate_shot_frame), then regenerate_shot_video; reassembling cannot remove it.",
|
|
138
138
|
"scan_voice_consistency": "★For original-voice dramas (video has built-in human speech), run this when the customer reports \"the same character's voice differs across shots / voice drifted\". Free (local inference, no vendor call). For each shot with dialogue, listens to vendor-generated human speech: whether the dialogue was fully spoken, and whether the voice resembles the timbre anchor bound to that character. **Async**: returns immediately; background full-episode scan takes about 10 minutes. Only one scan per episode can run at the same time (repeat calls return started=false). By default skips shots already scanned for the current video; rescan=true rescans all. Use get_voice_consistency to check progress and per-shot results.",
|
|
139
|
-
"get_voice_consistency": "Check progress and per-shot results of the voice consistency scan (started by scan_voice_consistency). Free. summary.voice_mismatch = shot numbers whose voice does not resemble the character timbre anchor (focus on these); dialogue_issues = shots where dialogue was incomplete/wrong/extra speech appeared; not_scanned_or_stale = not scanned yet or video changed and needs rescan. speaker_verdict=uncertain means the human speech is too short to judge; it is not an issue. For shots with inconsistent voice: first use get_pipeline_status native_voice_anchor to confirm the character has a bound voice, then regenerate_shot_video.",
|
|
139
|
+
"get_voice_consistency": "Check progress and per-shot results of the voice consistency scan (started by scan_voice_consistency). Free. summary.voice_mismatch = shot numbers whose voice does not resemble the character timbre anchor (focus on these); dialogue_issues = shots where dialogue was incomplete/wrong/extra speech appeared; not_scanned_or_stale = not scanned yet or video changed and needs rescan. speaker_verdict=uncertain means the human speech is too short to judge; it is not an issue. For shots with inconsistent voice: first use get_pipeline_status native_voice_anchor to confirm the character has a bound voice, then regenerate_shot_video. To keep first/last frames (regenerating loses composition) use quote_voice_unify → unify_voices: post-hoc conversion of vocals to the voice anchor's timbre without regenerating video. Shots that went through voice unification carry voice_unify: similarity / coverage / loudness_db are all before→after; summary.voice_unified = shots already in the final cut.",
|
|
140
|
+
"quote_voice_unify": "★Use for native-audio dramas (vendor-voiced video) when \"the same character's voice differs across shots\" but you don't want to regenerate video for voice and lose first/last-frame composition. Free quote, read-only. Lists, for every dialogue shot in the episode, whether it needs post-hoc voice unification and why: to_process = no voice anchor was sent at generation / an old anchor was sent, always processed; conditional = the current anchor was sent, voiceprint is measured at execution and the shot is skipped free of charge if it matches; skipped = untouched (locked shot, real footage, existing track-replacement product, character has no voice anchor, etc.; see reason_text). Multi-speaker shots are judged per speaker; only the lines of the speaker that needs it are changed. Billed by seconds of converted speech: estimated_points is the upper bound, typical_points the usual cost—tell the customer both; after they agree call unify_voices with quote_id. Characters without a voice anchor: set_character_voice or set_voice_anchor_from_shot first (pick the shot whose voice is right as the reference). Per-drama gray release; returns 403 if not enabled.",
|
|
141
|
+
"unify_voices": "Run post-hoc voice unification (quote_voice_unify first; call with quote_id after the customer agrees). Only runs the shots in the quote, serially in the background (~1-2 min per shot). Per shot: separate vocals → locate that character's lines by dialogue and voiceprint → convert each line into the voice anchor's timbre (each line's duration changes by ≤0.05s; lip-sync and picture untouched, no video regeneration) → splice back, ambience and SFX kept as-is. If any QC check fails (transcript coverage drops / duration diff >0.1s / similarity to anchor not improved / loudness diff >1dB) the original audio is kept and that shot's charge is refunded. Use get_voice_unify_status for progress and per-shot before/after; shots with status=applied take effect after recomposing (rerender_episode).",
|
|
142
|
+
"get_voice_unify_status": "Check voice-unification progress and per-shot results (free). summary: applied = unified (effective after recomposing the final cut) / kept_original = QC failed, original audio kept, charge refunded (reason says which check failed) / skipped = voiceprint already matched or no speech found for the character / errors = failed (charge refunded) / superseded = the shot was regenerated, switched or locked while processing; result discarded, not written back (charge refunded). Each shot carries similarity (before→after, to the voice anchor), coverage, loudness_db, points; stale = video or product changed since, result outdated.",
|
|
143
|
+
"preview_voice_unify": "Preview voice unification on a single shot (free, not written back, not charged). Asynchronous: start=true launches it (~1-2 min); call again without start to get the result. productUrl in the result is the processed video (listen directly); checks are the four QC verdicts. By default the character's voice anchor is the target timbre; with reference_storyboard_id = the shot in the same episode whose voice is right, that shot's vocals become the target (useful before the character has an anchor; speaker selects which character to convert).",
|
|
140
144
|
"scan_dialogue_coverage": "★When the customer reports \"cut before the line finished / only half the dialogue was spoken\", run this first. Default **free, zero charge** (read-only access to persisted transcription audit results). Compares each original-voice shot's video audio track against the dialogue at word level, and reports conclusions by family: truncated (stops halfway through the line) / off_script (most spoken content is not the dialogue: improvising, repeating previous shot, only ambience) / extra_speech (dialogue is fully spoken but extra speech is added) / minor_gap (sporadic missing words, transcription error, ignore) / ok. ★Interpretation: the three reportable families have **different remedies**; do not simply lengthen every shot—measurements show 21% of shots with sufficient length still fail to finish the line, so \"too short\" is rarely the real cause (the platform already auto-raises duration by dialogue when saving storyboards). The correct fix for truncated/off_script is regenerate_shot_video (how much the vendor says is random each time; rerolling often gets the full line); if the same drama repeatedly has off_script, switch engine. ★never_audited is the most important section of this report: those shots have never been checked; \"not checked\" does not mean \"no issue\". rescan=true will run ASR comparison for them (compute-intensive, not instant; limit controls per-run cap), default does not run. TTS-dubbed shots are out of scope (TTS necessarily reads the full line; low coverage can only be transcription error). If the same episode also has \"cuts too fast\", that is a separate issue; run scan_intra_shot_cuts.",
|
|
141
145
|
"update_shot": "Shot-by-shot edit: change a single storyboard shot's text content (shot size/action/dialogue/visual description/camera movement, etc.), facial expression (expression_hint), duration (duration), final cut speed (speed_factor), character binding (character_ids), prop binding (prop_ids; full overwrite, [] clears—use it to fix a prop missed at import instead of re-importing the whole episode; edits do not auto-regenerate frames/video), voice-over marker (character_presence), and wardrobe binding (active_wardrobe_id / appearance_wardrobes); read back shot size / angle / camera movement / edit intent and prompt text per shot with get_shot_prompts. Send only fields to change; all others stay unchanged. ★Any shot edit (accepted or rejected) invalidates unconsumed quotes covering this shot; generation then returns 409 QUOTE_INVALIDATED—edit first, read back to verify, then quote. **Free** (pure text DB write). ★Changing dialogue automatically invalidates generated TTS voice-over and subtitles for this shot (tts must be regenerated); text edits do not auto-regenerate images/video. To make visuals follow text changes, edit then regen the corresponding shot. Use get_storyboards to inspect results (each shot includes character_ids / character_bindings / scene_id / prop_ids / active_wardrobe_id / appearance_wardrobes). ★★【Change clothes here, not in text】What appears in image generation is determined by **wardrobe binding**: single-character shots use active_wardrobe_id (one outfit for the whole shot); multi-character shots use appearance_wardrobes (per character). Writing \"wearing X clothes\" in description/action will not change clothes. Use list_wardrobe for wardrobe id; edits do not auto-regenerate images. To update visuals, regenerate this shot's first frame then video. ★★For native-audio shots (vendor-native audio), after changing dialogue the shot video is marked \"needs regeneration\"—because spoken lines are **baked into the video audio**. If you final-compose without regeneration, the final cut still speaks the old line (typical symptom: dialogue seems to have moved to another shot). compose_episode lists these shots under advisory `stale_video_after_edit`; correct handling is regenerate_shot_video before final compose. ★You may also directly edit this shot's four prompt bodies (image_prompt/video_prompt/first_frame_prompt/last_frame_prompt): read current values with get_shot_prompts first; do not overwrite from scratch. @char:N / @scene:M in the body are supplemental reference markers for image generation; keep them unchanged. ★Which character sheet is injected is determined by character_ids, and background by scene_id: deleting markers will not remove already-bound people from the image. To make someone not appear, edit character_ids; if they are voice-only, set character_presence to voice_only. Conversely, do not write @char markers for unbound characters—this will inject their image. ★★【If last-frame generation is blocked, edit here】If last-frame generation reports \"this shot is marked as a state change, but nowhere describes what it looks like at the end\" (TERMINAL_DESC_GATE), fix by writing **what the final image should look like** into this shot's last_frame_prompt, then regenerate the last frame. Do not retry image generation—shots of this type (action_motion_class=state_change without terminal state) historically succeed at 9.4%, versus 40.2% with terminal-state description; without adding the description, the vendor prompt has no terminal-state section, so it still draws the same as the first frame, is rejected again, and each regeneration still charges normally. terminal_desc_missing=true from get_shot_prompts is this signal.",
|
|
142
146
|
"rederive_shot_contract": "Using this shot's **current** prompt body and character binding, let the platform re-derive the composition contract (how many visible people, whether the subject is a person or a partial/object, shot size). The contract itself is internal: cannot be read or edited directly. This tool only returns outcome: updated (changed and effective) / unchanged (derived result same as current) / rejected (derived result self-contradictory, not adopted, original contract kept) / no_candidate (no usable result, original contract kept) / stale (shot changed during derivation, result not written; call again after edits), plus note for next step. Insufficient credits returns 402. ★When to use: image generation/precheck/review repeatedly says the number of people is wrong, or a partial shot (hand/prop close-up) is treated as a full-person shot in generation or review, and you have already edited text or bindings—the autofiller only fills blanks and does not overwrite existing contracts; without this tool, edits will not enter the contract. ★Correct order: first update_shot to make the image text correct (who is visible, who is voice-only via character_presence voice_only, unbind anyone who should not appear from character_ids), then call this tool; calling without text edits usually returns unchanged. ★One text AI call, postpaid by token (same chain as autofill_storyboards); inform the customer before calling. ★Only changes this one contract field; does not touch dialogue/prompts/other specialized fields. Generated first/last frames are not auto-regenerated; to update visuals, regenerate frames for this shot (quote first). ★updated invalidates unconsumed frame/video quotes for this shot and the same episode; quote again afterward.",
|
|
@@ -140,7 +140,11 @@
|
|
|
140
140
|
"scan_burned_subtitles": "★原声剧(视频自带人声)终拼前建议跑一次;客户报「成片里有两层字幕 / 画面里多出一行字」时先跑这个。视频厂商有时会无视「不要字幕」的约束,把台词烧进画面——字小、通常只在说出那句台词的一两秒内出现,而平台成片还会再叠一层字幕,于是变成双字幕。重新拼接去不掉它,只能 regenerate_shot_video 重出该镜。每镜抽 12 帧、一次视觉审计,**按用量计费**(每镜一次小额 vision 调用)。返回 flagged[{shot, texts, matches_dialogue, frames}] / clean / errors。matches_dialogue=true 表示读出来的字就是本镜台词,基本可确认是厂商字幕;招牌、书页、屏幕等画面里本来就有的字不算。dry_run=true 只报告不写回;否则结果写回,compose_episode 的终拼预检会以 vendor_burned_text 列出这些镜。",
|
|
141
141
|
"scan_wardrobe_consistency": "★客户报「同一个角色前后换了衣服 / 衣服颜色款式不对」时跑这个;终拼前也建议跑一次。逐镜把采用的首帧和视频中段一帧,与本镜每个角色的设定图(没有则用定妆图)比对衣服的款式与颜色。常见成因是远景小人物被出图模型画成了别的衣服——即使参考图和提示词都对。夜景/暖光的整体偏色不算不一致。每镜一次视觉审计,**按用量计费**。返回 flagged[{shot, characters:[{name, differences}]}] / clean / errors。dry_run=true 只报告不写回;否则写回,compose_episode 的终拼预检会以 wardrobe_mismatch 列出这些镜。处置:重出该镜首帧(generate_shot_frame)再 regenerate_shot_video;重新拼接去不掉。",
|
|
142
142
|
"scan_voice_consistency": "★原声剧(视频自带人声)客户报「同一个角色前后嗓音不一样 / 声线漂了」时跑这个。免费(本地推理,不调厂商)。对每个有台词的镜,听厂商生成的人声:台词念没念全,以及声音像不像该角色绑定的声线锚。**异步**:立即返回,后台整集约 10 分钟;同一集同时只跑一条(重复调用返回 started=false)。默认跳过已对当前视频扫过的镜,rescan=true 全部重扫。用 get_voice_consistency 查进度和逐镜结果。",
|
|
143
|
-
"get_voice_consistency": "查声线一致性扫描的进度与逐镜结果(scan_voice_consistency 启动的)。免费。summary.voice_mismatch=声音不像该角色声线锚的镜号(重点看);dialogue_issues=台词没念完/念错/多出说话声的镜;not_scanned_or_stale=还没扫或视频换过需重扫。speaker_verdict=uncertain 表示人声太短判不了,不是问题。声线不一致的镜:先用 get_pipeline_status 的 native_voice_anchor 确认角色已绑声线,再 regenerate_shot_video
|
|
143
|
+
"get_voice_consistency": "查声线一致性扫描的进度与逐镜结果(scan_voice_consistency 启动的)。免费。summary.voice_mismatch=声音不像该角色声线锚的镜号(重点看);dialogue_issues=台词没念完/念错/多出说话声的镜;not_scanned_or_stale=还没扫或视频换过需重扫。speaker_verdict=uncertain 表示人声太短判不了,不是问题。声线不一致的镜:先用 get_pipeline_status 的 native_voice_anchor 确认角色已绑声线,再 regenerate_shot_video 重出;要保住首尾帧(重出会丢构图)就走 quote_voice_unify → unify_voices,事后把人声转成声线锚的嗓音、不重生视频。做过声线统一的镜带 voice_unify:similarity / coverage / loudness_db 都是 before→after;summary.voice_unified=已进成片的镜号。",
|
|
144
|
+
"quote_voice_unify": "★原声剧(视频自带人声)「同一个角色前后嗓音不一样」、又不想为声线重出视频丢掉首尾帧构图时用。免费报价、只读。列出本集每个有台词的镜要不要做「事后声线统一」及原因:to_process=出片时没送声线锚 / 送的是旧锚,一定处理;conditional=出片时已送进当前锚,执行时先测声纹,对得上就跳过、不收费;skipped=不动(锁定镜、实拍、已有换轨产物、角色没有声线锚等,见 reason_text)。多人镜按说话人分别判,只改需要处理的那个人的句子。按转换的人声秒数计费:estimated_points 是上界、typical_points 是通常花费,两个都告诉客户,客户同意后带 quote_id 调 unify_voices。角色没有声线锚的先 set_character_voice 或 set_voice_anchor_from_shot(挑一镜嗓音最对的当基准)。逐剧灰度,未开通回 403。",
|
|
145
|
+
"unify_voices": "执行事后声线统一(必须先 quote_voice_unify,客户同意后带 quote_id)。只跑报价里的镜,后台串行(每镜约 1~2 分钟)。每镜:分离人声 → 按台词与声纹定位该角色的句子 → 逐句转成声线锚的嗓音(每句时长只变 ≤0.05s,口型与画面不动、不重生视频)→ 回填,环境声与音效原样保留。质检任一不过(转写覆盖率下降 / 时长差 >0.1s / 与锚的相似度没提升 / 响度差 >1dB)就保留原音轨并退回该镜费用。用 get_voice_unify_status 看进度与每镜前后对比;status=applied 的镜重拼成片(rerender_episode)后生效。",
|
|
146
|
+
"get_voice_unify_status": "查声线统一的进度与逐镜结果(免费)。summary:applied=已统一(重拼成片后生效)/ kept_original=质检没过、保留原音轨、费用已退(reason 写了哪项没过)/ skipped=测下来声纹本来就对得上或找不到该角色的人声 / errors=失败(费用已退)/ superseded=处理期间镜头被重出、换版本或锁定,结果作废未写回(费用已退)。每镜带 similarity(before→after,与声线锚的相似度)、coverage、loudness_db、points;stale=视频或产物换过、结论过期。",
|
|
147
|
+
"preview_voice_unify": "对单镜试听声线统一效果(免费、不写回、不扣费)。异步:start=true 启动(约 1~2 分钟),之后不带 start 再调一次取结果;结果里 productUrl 是处理后的视频(可直接听),checks 是四项质检结论。默认用该角色的声线锚当目标嗓音;reference_storyboard_id=同一集里嗓音最对的那一镜时,改用那一镜的人声当目标(适合角色还没绑锚、先挑基准的情况,speaker 指定转哪个角色)。",
|
|
144
148
|
"scan_dialogue_coverage": "★客户报「话没说完就切 / 台词只念了一半」时先跑这个。默认**免费零扣费**(只读已落库的转录审计结果)。把该集每个原声镜的视频音轨与台词做词级比对,按族给出结论:truncated(念到一半就停) / off_script(念的大半不是台词:自说自话、重复上一镜、只有环境音) / extra_speech(台词念全了但还多念) / minor_gap(零星缺词,属转写误差,不必管) / ok。★判读:三个可上报的族**处置方向不同**,别一律加长镜头——实测镜长够的镜里仍有 21% 没念全,「太短」很少是真因(平台保存分镜时已按台词自动抬时长)。truncated/off_script 的正解都是 regenerate_shot_video(厂商每次说多少是随机的,重掷常能拿到整句);同一剧反复 off_script 则换引擎。★never_audited 是本报告最重要的一栏:那些镜从没被检测过,「没测过」不等于「没问题」。rescan=true 会对它们补跑 ASR 比对(耗算力、非瞬时,limit 控制单次上限),默认不跑。TTS 配音镜不在范围内(TTS 必然念全,低覆盖率只会是转写误差)。同一集若还伴随「切太快」,那是另一回事,跑 scan_intra_shot_cuts。",
|
|
145
149
|
"update_shot": "逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、面部表情(expression_hint)、时长(duration)、成片变速(speed_factor)、镜间转场(transition_type / transition_duration_ms)、角色绑定(character_ids)、道具绑定(prop_ids)、画外音标记(character_presence)与服装绑定(active_wardrobe_id / appearance_wardrobes)。只传要改的字段、其余不动。★改镜(成功或被拒)都会作废覆盖本镜的未消费报价,生成时回 409 QUOTE_INVALIDATED——先改成功、回读核对,再报价。**免费**(纯文本写库)。★改 dialogue 会自动失效本镜已生成的 TTS 配音与字幕(需重出 tts);改文本不会自动重出图/视频,如需让画面跟上文本改动,改完再 regen 对应镜。用 get_storyboards 查改后结果(每镜带 character_ids / character_bindings / scene_id / prop_ids / active_wardrobe_id / appearance_wardrobes);景别/机位/运镜/剪辑意图与提示词正文用 get_shot_prompts 逐镜回读。★★【换衣服改这里,不是改文字】出图穿什么由**服装绑定**决定:单人镜用 active_wardrobe_id(整镜一件),多人同框各穿各的用 appearance_wardrobes(逐角色)。把「穿某某衣服」写进 description/action 不会换衣服。服装 id 用 list_wardrobe 查;改完不会自动重出图,要让画面跟上需重生本镜首帧再重生视频。★★原声镜(厂商原生音频)改 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 就是这个信号。★★【构图契约不会跟着改】改 shot_type / character_ids / character_presence / description / action / image_prompt / first_frame_prompt 后,本镜的构图契约(画面里可见几人、主体是人物还是手部等局部/道具、景别)不会自动重推,出图组织画面与帧审计判人数仍按旧契约来(典型:改成局部特写、解绑全部角色,出图照样画人像)。回执带 frame_contract_advisory 就是这种情况:讲给客户,客户同意后调 rederive_shot_contract(按 token 后付)重推,得出 updated 再报价出图;客户确认画面人数与主体都没变可以不推。★改 action 前先用 get_shot_prompts 读现值(action),别凭空整段覆盖。",
|
|
146
150
|
"rederive_shot_contract": "按本镜**当前**的正文与角色绑定,让平台重新推导构图契约(画面里可见几人、主体是人物还是局部/道具、景别)。契约本体不对外、改不了(get_shot_prompts 的 frame_contract 只给人数 / 主体类型 / 是否可能过期这几个结论);本工具只回结论 outcome:updated(已改并生效)/ unchanged(推出来和原来一样)/ rejected(推出来自相矛盾,未采用,原契约保留)/ no_candidate(没拿到可用结果,原契约保留)/ stale(推导期间本镜又被改过,结果未写入,改完再调一次),附 note 说下一步。点数不足回 402。★什么时候用:出图/预检/审核反复说人数不对、局部镜(手部/道具特写)被当成完整人物出图或审核,而你已经改过正文或绑定——补全器只填空、不覆盖已有契约,不调本工具改动不会进契约。update_shot 回执带 frame_contract_advisory、get_shot_prompts 的 frame_contract.stale=true、review_storyboards 报 frame_contract_stale / frame_contract_binding_conflict、出帧报价带 frame_contract_advisory,都是该调本工具的信号;得出 updated 或 unchanged 后「可能过期」标记清除(rejected / stale / no_candidate 保留)。★正确顺序:先 update_shot 把画面写对(谁在画面里、谁只出声音用 character_presence 标 voice_only、不该出现的人从 character_ids 解绑),再调本工具;不改正文直接调多半回 unchanged。★一次文本 AI 调用,按 token 后付(与 autofill_storyboards 同链路),调用前告知客户。★只改契约这一个字段,不碰台词/提示词/其它专业字段;已出的首尾帧不会自动重出,要让画面跟上需对本镜重新出帧(先报价)。★updated 会作废本镜及同集未消费的出帧/出视频报价,之后要重新报价。",
|
package/dist/tools/guide-data.js
CHANGED
|
@@ -255,7 +255,7 @@ export const PIPELINE = [
|
|
|
255
255
|
},
|
|
256
256
|
{
|
|
257
257
|
step: '7 出帧(镜头图)',
|
|
258
|
-
tools: ['run_precheck(免费,揪出必被厂商拒的镜)', 'quote_frames', 'generate_frames', 'tail_frame_plan(免费,首帧出完必调)', 'quote_shot_frame', 'generate_shot_frame(单镜重生)', 'quote_local_frame_edit', 'local_frame_edit(局部返修·只改框内,灰度剧)', 'get_local_frame_edit', 'adopt_local_frame_edit', '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'],
|
|
258
|
+
tools: ['run_precheck(免费,揪出必被厂商拒的镜)', 'quote_frames', 'generate_frames', 'tail_frame_plan(免费,首帧出完必调)', 'quote_shot_frame', 'generate_shot_frame(单镜重生)', 'quote_local_frame_edit', 'local_frame_edit(局部返修·只改框内,灰度剧)', 'get_local_frame_edit', 'adopt_local_frame_edit', 'chain_frames(先 dry_run:true 看计划与预估)', 'cancel_images(停批量出图:已派的照常出完扣费,未派的不再派·免费)', 'chain_shot_from_prev(免费,单道接缝)', 'quote_chain_shot_from', 'chain_shot_from', 'quote_align_prev_shot', 'align_prev_shot', 'upload_shot_frame'],
|
|
259
259
|
billing: '报价确认后扣点',
|
|
260
260
|
gate: 'review_frames(镜头图审查;免费;generate_videos 前必过)',
|
|
261
261
|
note: '★出帧是**两趟**:generate_frames 默认只出首帧,首帧出完必须调一次免费的 `tail_frame_plan` ' +
|
package/dist/tools/produce.js
CHANGED
|
@@ -782,7 +782,21 @@ export function registerProduceTools(server, client) {
|
|
|
782
782
|
'resumed_after_restart>0 = 中途服务重启过、已自动续跑(已出视频与中断前已派发的镜不重出不重扣);' +
|
|
783
783
|
'status=interrupted = 重启后没自动续跑(interrupt_reason 写原因),重新 quote_videos 后 generate_videos 会跳过已出的镜;' +
|
|
784
784
|
'shots_dispatched_without_video = 派发过但没出片的镜,用 get_jobs 看原因、regenerate_shot_video 单补;' +
|
|
785
|
-
'status=cancelling / cancelled = 客户用 cancel_videos 停了这条链,cancelled_shot_numbers
|
|
785
|
+
'status=cancelling / cancelled = 客户用 cancel_videos 停了这条链,cancelled_shot_numbers 是没出没扣费的镜。\n' +
|
|
786
|
+
'★批量出图(整集出帧 / 帧链 / 定妆图 / 设定图 / 场景图等)看 image_batches:每批 kind / status(running / done / cancelled)/' +
|
|
787
|
+
' dispatched / in_flight / completed / targets_not_dispatched;status=cancelled = 客户用 cancel_images 停了这一批。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/run-status`)));
|
|
788
|
+
// ---------- 取消批量出图(免费) ----------
|
|
789
|
+
server.tool('cancel_images', '(免费)停掉本剧还在跑的批量出图:整集出帧(generate_frames)、工作台出帧批次、帧链(chain_frames 与自动帧链)、' +
|
|
790
|
+
'定妆图、设定图、场景图、世界观图、角色变体图、锚图。语义:**已交给厂商的图照常出完、照常扣费(不退,含 best-of-N 已派出的候选)**;' +
|
|
791
|
+
'还没派的不再派、不扣费;之后的质量重试、补派、服务重启后的重排也不会再派;被取消的出帧批次重启后不续跑。' +
|
|
792
|
+
'可选 episode_id 只停这一集的批次、kind 只停一种(frames / frame_batch / frame_chain / portraits / sheets / scene_images / world_images / character_variants / anchors),不传 = 本剧全部。' +
|
|
793
|
+
'回执每批给 in_flight_items(已派出、会出完扣费)、completed_items(已出完)、cancelled_targets(没派、不扣费;null = 该批次没预先登记目标清单)。' +
|
|
794
|
+
'被取消的镜 / 角色 / 场景之后可以重新报价再发起对应的 generate_*(已出的会跳过),或单张重出。' +
|
|
795
|
+
'★只在客户明确要停时调用;单张出图(generate_shot_frame 等)不能取消;没有可取消的批次返回 409 NO_ACTIVE_IMAGE_BATCH。出视频的取消用 cancel_videos。', {
|
|
796
|
+
drama_id: z.number().int().positive(),
|
|
797
|
+
episode_id: z.number().int().positive().optional(),
|
|
798
|
+
kind: z.enum(['frames', 'frame_batch', 'frame_chain', 'portraits', 'sheets', 'scene_images', 'world_images', 'character_variants', 'anchors']).optional(),
|
|
799
|
+
}, async ({ drama_id, episode_id, kind }) => jsonResult(await client.producePost(`/dramas/${drama_id}/images/cancel`, { ...(episode_id ? { episode_id } : {}), ...(kind ? { kind } : {}) })));
|
|
786
800
|
// ---------- 分镜级 AI 操作:2 个免费质量闸 + 3 个 AI 增强(★都在出图前做)----------
|
|
787
801
|
server.tool('run_precheck', '(★推荐·免费质量闸)出图/出视频前跑生成前预检,把会被拒的镜提前揪出。免费、不扣费。' +
|
|
788
802
|
'强烈建议 generate_frames/generate_videos 前调,防白花钱被拒。\n' +
|
|
@@ -1776,7 +1790,32 @@ export function registerProduceTools(server, client) {
|
|
|
1776
1790
|
server.tool('get_voice_consistency', '查声线一致性扫描的进度与逐镜结果(scan_voice_consistency 启动的)。免费。' +
|
|
1777
1791
|
'summary.voice_mismatch=声音不像该角色声线锚的镜号(重点看);dialogue_issues=台词没念完/念错/多出说话声的镜;' +
|
|
1778
1792
|
'not_scanned_or_stale=还没扫或视频换过需重扫。speaker_verdict=uncertain 表示人声太短判不了,不是问题。' +
|
|
1779
|
-
'声线不一致的镜:先用 get_pipeline_status 的 native_voice_anchor 确认角色已绑声线,再 regenerate_shot_video
|
|
1793
|
+
'声线不一致的镜:先用 get_pipeline_status 的 native_voice_anchor 确认角色已绑声线,再 regenerate_shot_video 重出;' +
|
|
1794
|
+
'要保住首尾帧(重出会丢构图)就走 quote_voice_unify → unify_voices,事后把人声转成声线锚的嗓音、不重生视频。' +
|
|
1795
|
+
'做过声线统一的镜带 voice_unify:similarity / coverage / loudness_db 都是 before→after;summary.voice_unified=已进成片的镜号。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/voice-identity-scan`)));
|
|
1796
|
+
server.tool('quote_voice_unify', '★原声剧(视频自带人声)「同一个角色前后嗓音不一样」、又不想为声线重出视频丢掉首尾帧构图时用。免费报价、只读。' +
|
|
1797
|
+
'列出本集每个有台词的镜要不要做「事后声线统一」及原因:to_process=出片时没送声线锚 / 送的是旧锚,一定处理;' +
|
|
1798
|
+
'conditional=出片时已送进当前锚,执行时先测声纹,对得上就跳过、不收费;skipped=不动(锁定镜、实拍、已有换轨产物、角色没有声线锚等,见 reason_text)。' +
|
|
1799
|
+
'多人镜按说话人分别判,只改需要处理的那个人的句子。按转换的人声秒数计费:estimated_points 是上界、typical_points 是通常花费,两个都告诉客户,客户同意后带 quote_id 调 unify_voices。' +
|
|
1800
|
+
'角色没有声线锚的先 set_character_voice 或 set_voice_anchor_from_shot(挑一镜嗓音最对的当基准)。逐剧灰度,未开通回 403。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/voice-unify/quote`)));
|
|
1801
|
+
server.tool('unify_voices', '执行事后声线统一(必须先 quote_voice_unify,客户同意后带 quote_id)。只跑报价里的镜,后台串行(每镜约 1~2 分钟)。' +
|
|
1802
|
+
'每镜:分离人声 → 按台词与声纹定位该角色的句子 → 逐句转成声线锚的嗓音(每句时长只变 ≤0.05s,口型与画面不动、不重生视频)→ 回填,环境声与音效原样保留。' +
|
|
1803
|
+
'质检任一不过(转写覆盖率下降 / 时长差 >0.1s / 与锚的相似度没提升 / 响度差 >1dB)就保留原音轨并退回该镜费用。' +
|
|
1804
|
+
'用 get_voice_unify_status 看进度与每镜前后对比;status=applied 的镜重拼成片(rerender_episode)后生效。', { episode_id: z.number().int().positive(), quote_id: z.string().min(1) }, async ({ episode_id, quote_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/voice-unify`, { quote_id })));
|
|
1805
|
+
server.tool('get_voice_unify_status', '查声线统一的进度与逐镜结果(免费)。summary:applied=已统一(重拼成片后生效)/ kept_original=质检没过、保留原音轨、费用已退(reason 写了哪项没过)/ ' +
|
|
1806
|
+
'skipped=测下来声纹本来就对得上或找不到该角色的人声 / errors=失败(费用已退)/ superseded=处理期间镜头被重出、换版本或锁定,结果作废未写回(费用已退)。每镜带 similarity(before→after,与声线锚的相似度)、coverage、loudness_db、points;stale=视频或产物换过、结论过期。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/voice-unify/status`)));
|
|
1807
|
+
server.tool('preview_voice_unify', '对单镜试听声线统一效果(免费、不写回、不扣费)。异步:start=true 启动(约 1~2 分钟),之后不带 start 再调一次取结果;' +
|
|
1808
|
+
'结果里 productUrl 是处理后的视频(可直接听),checks 是四项质检结论。' +
|
|
1809
|
+
'默认用该角色的声线锚当目标嗓音;reference_storyboard_id=同一集里嗓音最对的那一镜时,改用那一镜的人声当目标(适合角色还没绑锚、先挑基准的情况,speaker 指定转哪个角色)。', {
|
|
1810
|
+
storyboard_id: z.number().int().positive(),
|
|
1811
|
+
start: z.boolean().optional().describe('true=启动试听;不传=查结果'),
|
|
1812
|
+
speaker: z.string().optional().describe('多人镜里要转哪个角色(配合 reference_storyboard_id)'),
|
|
1813
|
+
reference_storyboard_id: z.number().int().positive().optional().describe('拿这一镜的人声当目标嗓音(同一集、单人台词镜)'),
|
|
1814
|
+
}, async ({ storyboard_id, start, speaker, reference_storyboard_id }) => jsonResult(start
|
|
1815
|
+
? await client.producePost(`/storyboards/${storyboard_id}/voice-unify/preview`, {
|
|
1816
|
+
...(speaker ? { speaker } : {}), ...(reference_storyboard_id ? { reference_storyboard_id } : {}),
|
|
1817
|
+
})
|
|
1818
|
+
: await client.produceGet(`/storyboards/${storyboard_id}/voice-unify/preview`)));
|
|
1780
1819
|
server.tool('scan_dialogue_coverage', '★客户报「话没说完就切 / 台词只念了一半」时先跑这个。默认**免费零扣费**(只读已落库的转录审计结果)。'
|
|
1781
1820
|
+ '把该集每个原声镜的视频音轨与台词做词级比对,按族给出结论:'
|
|
1782
1821
|
+ 'truncated(念到一半就停) / off_script(念的大半不是台词:自说自话、重复上一镜、只有环境音) / '
|
|
@@ -2257,7 +2296,8 @@ export function registerProduceTools(server, client) {
|
|
|
2257
2296
|
'异步生成后用它看进度。免费。' +
|
|
2258
2297
|
'★整集出帧(generate_frames)是后台逐镜派发,被拒的镜不会出现在任务列表里——看响应的 frame_dispatch_rejections' +
|
|
2259
2298
|
'(每镜 storyboard_id/frame_type/code/message)。code=ERA_USER_REF_CONFLICT 表示客户上传的定妆图被时代审核判冲突:' +
|
|
2260
|
-
'把 message 转告客户' + ALWAYS_ASK('allow_era_ref_conflict ') + ',客户确认后带 allow_era_ref_conflict=true 对那几镜 generate_shot_frame。重启后该列表清空。'
|
|
2299
|
+
'把 message 转告客户' + ALWAYS_ASK('allow_era_ref_conflict ') + ',客户确认后带 allow_era_ref_conflict=true 对那几镜 generate_shot_frame。重启后该列表清空。' +
|
|
2300
|
+
'★image_batches = 最近 24 小时的批量出图批次(含 cancel_images 取消的,status=cancelled)。', { drama_id: z.number().int().positive() }, async ({ drama_id }) => jsonResult(await client.produceGet(`/dramas/${drama_id}/jobs`)));
|
|
2261
2301
|
server.tool('get_drama_bill', '本剧净费用账单(免费)。核账、回答「到底花了多少、钱花在哪、退了多少」时用它,别自己拼流水。' +
|
|
2262
2302
|
'\n· totals / by_kind:每类 charged(扣费)、refunded(已退回)、net(净额)、charges/refunds(笔数)。' +
|
|
2263
2303
|
'**net 才是花费**,与网页「本剧已花费」、get_budget_status 同源;charged 含失败后自动退回的空转,只用于核账。' +
|
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.242",
|
|
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.242 tool surface (operationIds match MCP tool names 1:1)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
|
9
9
|
{
|
|
@@ -2627,11 +2627,88 @@
|
|
|
2627
2627
|
}
|
|
2628
2628
|
}
|
|
2629
2629
|
},
|
|
2630
|
+
"/dramas/{drama_id}/images/cancel": {
|
|
2631
|
+
"post": {
|
|
2632
|
+
"operationId": "cancel_images",
|
|
2633
|
+
"summary": "(免费)停掉本剧还在跑的批量出图:整集出帧(generate_frames)、工作台出帧批次、帧链(chain_frames 与自动帧链)、定妆图、设定图、场景图、世界观图、角色变体图、锚图",
|
|
2634
|
+
"description": "(免费)停掉本剧还在跑的批量出图:整集出帧(generate_frames)、工作台出帧批次、帧链(chain_frames 与自动帧链)、定妆图、设定图、场景图、世界观图、角色变体图、锚图。语义:**已交给厂商的图照常出完、照常扣费(不退,含 best-of-N 已派出的候选)**;还没派的不再派、不扣费;之后的质量重试、补派、服务重启后的重排也不会再派;被取消的出帧批次重启后不续跑。可选 episode_id 只停这一集的批次、kind 只停一种(frames / frame_batch / frame_chain / portraits / sheets / scene_images / world_images / character_variants / anchors),不传 = 本剧全部。回执每批给 in_flight_items(已派出、会出完扣费)、completed_items(已出完)、cancelled_targets(没派、不扣费;null = 该批次没预先登记目标清单)。被取消的镜 / 角色 / 场景之后可以重新报价再发起对应的 generate_*(已出的会跳过),或单张重出。★只在客户明确要停时调用;单张出图(generate_shot_frame 等)不能取消;没有可取消的批次返回 409 NO_ACTIVE_IMAGE_BATCH。出视频的取消用 cancel_videos。",
|
|
2635
|
+
"tags": [
|
|
2636
|
+
"dramas"
|
|
2637
|
+
],
|
|
2638
|
+
"parameters": [
|
|
2639
|
+
{
|
|
2640
|
+
"name": "drama_id",
|
|
2641
|
+
"in": "path",
|
|
2642
|
+
"required": true,
|
|
2643
|
+
"schema": {
|
|
2644
|
+
"type": "integer",
|
|
2645
|
+
"exclusiveMinimum": 0
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
],
|
|
2649
|
+
"requestBody": {
|
|
2650
|
+
"required": false,
|
|
2651
|
+
"content": {
|
|
2652
|
+
"application/json": {
|
|
2653
|
+
"schema": {
|
|
2654
|
+
"type": "object",
|
|
2655
|
+
"properties": {
|
|
2656
|
+
"episode_id": {
|
|
2657
|
+
"type": "integer",
|
|
2658
|
+
"exclusiveMinimum": 0
|
|
2659
|
+
},
|
|
2660
|
+
"kind": {
|
|
2661
|
+
"type": "string",
|
|
2662
|
+
"enum": [
|
|
2663
|
+
"frames",
|
|
2664
|
+
"frame_batch",
|
|
2665
|
+
"frame_chain",
|
|
2666
|
+
"portraits",
|
|
2667
|
+
"sheets",
|
|
2668
|
+
"scene_images",
|
|
2669
|
+
"world_images",
|
|
2670
|
+
"character_variants",
|
|
2671
|
+
"anchors"
|
|
2672
|
+
]
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
},
|
|
2679
|
+
"responses": {
|
|
2680
|
+
"200": {
|
|
2681
|
+
"description": "StarReel envelope",
|
|
2682
|
+
"content": {
|
|
2683
|
+
"application/json": {
|
|
2684
|
+
"schema": {
|
|
2685
|
+
"type": "object",
|
|
2686
|
+
"properties": {
|
|
2687
|
+
"code": {
|
|
2688
|
+
"type": "integer"
|
|
2689
|
+
},
|
|
2690
|
+
"message": {
|
|
2691
|
+
"type": "string"
|
|
2692
|
+
},
|
|
2693
|
+
"data": {
|
|
2694
|
+
"description": "Operation result payload"
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
},
|
|
2701
|
+
"402": {
|
|
2702
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
},
|
|
2630
2707
|
"/dramas/{drama_id}/jobs": {
|
|
2631
2708
|
"get": {
|
|
2632
2709
|
"operationId": "get_jobs",
|
|
2633
2710
|
"summary": "查一部剧的任务队列进度(出图/出视频/合成各阶段的 pending/processing/done/failed)",
|
|
2634
|
-
"description": "查一部剧的任务队列进度(出图/出视频/合成各阶段的 pending/processing/done/failed)。异步生成后用它看进度。免费。★整集出帧(generate_frames)是后台逐镜派发,被拒的镜不会出现在任务列表里——看响应的 frame_dispatch_rejections(每镜 storyboard_id/frame_type/code/message)。code=ERA_USER_REF_CONFLICT 表示客户上传的定妆图被时代审核判冲突:把 message 转告客户(allow_era_ref_conflict 任何执行模式都须客户明确同意,托管也不例外),客户确认后带 allow_era_ref_conflict=true 对那几镜 generate_shot_frame
|
|
2711
|
+
"description": "查一部剧的任务队列进度(出图/出视频/合成各阶段的 pending/processing/done/failed)。异步生成后用它看进度。免费。★整集出帧(generate_frames)是后台逐镜派发,被拒的镜不会出现在任务列表里——看响应的 frame_dispatch_rejections(每镜 storyboard_id/frame_type/code/message)。code=ERA_USER_REF_CONFLICT 表示客户上传的定妆图被时代审核判冲突:把 message 转告客户(allow_era_ref_conflict 任何执行模式都须客户明确同意,托管也不例外),客户确认后带 allow_era_ref_conflict=true 对那几镜 generate_shot_frame。重启后该列表清空。★image_batches = 最近 24 小时的批量出图批次(含 cancel_images 取消的,status=cancelled)。",
|
|
2635
2712
|
"tags": [
|
|
2636
2713
|
"dramas"
|
|
2637
2714
|
],
|
|
@@ -9329,7 +9406,7 @@
|
|
|
9329
9406
|
"get": {
|
|
9330
9407
|
"operationId": "get_run_status",
|
|
9331
9408
|
"summary": "(★免费·长耗时操作后必用)查这一集当前有没有 agent 正在跑",
|
|
9332
|
-
"description": "(★免费·长耗时操作后必用)查这一集当前有没有 agent 正在跑。rewrite_script / extract_assets / generate_storyboards 都是**分钟级**后台任务,它们只回一句 status:\"generating\",本工具是唯一能区分「还在跑」与「已经结束」的手段。\n★典型耗时(生产实测):改写 2~4 分钟、拆镜 5~10 分钟——**单次 LLM 调用就可能 3~7 分钟**。所以 60 秒内查不到结果是完全正常的,绝不是失败。\n用法:发起后每 30~60 秒调一次。running:true = 还在跑,继续等,**千万不要重发**(重发拆镜会替换整集分镜,已调好/已出图的全丢、要重花钱);running:false = 那次已经结束,这时才去 get_storyboards / get_script 看产物有没有落库。\n⚠️ 服务重启会让 agent 在途登记归零,重启期间发起的运行也会显示为无在途。\n★generate_videos 整集出视频的接力链看返回里的 video_run 段(它落库,重启不会凭空消失):shots_total / shots_with_video / shots_remaining = 共几镜、已出几镜、剩几镜;running:true = 链在跑,别重发 generate_videos;resumed_after_restart>0 = 中途服务重启过、已自动续跑(已出视频与中断前已派发的镜不重出不重扣);status=interrupted = 重启后没自动续跑(interrupt_reason 写原因),重新 quote_videos 后 generate_videos 会跳过已出的镜;shots_dispatched_without_video = 派发过但没出片的镜,用 get_jobs 看原因、regenerate_shot_video 单补;status=cancelling / cancelled = 客户用 cancel_videos 停了这条链,cancelled_shot_numbers
|
|
9409
|
+
"description": "(★免费·长耗时操作后必用)查这一集当前有没有 agent 正在跑。rewrite_script / extract_assets / generate_storyboards 都是**分钟级**后台任务,它们只回一句 status:\"generating\",本工具是唯一能区分「还在跑」与「已经结束」的手段。\n★典型耗时(生产实测):改写 2~4 分钟、拆镜 5~10 分钟——**单次 LLM 调用就可能 3~7 分钟**。所以 60 秒内查不到结果是完全正常的,绝不是失败。\n用法:发起后每 30~60 秒调一次。running:true = 还在跑,继续等,**千万不要重发**(重发拆镜会替换整集分镜,已调好/已出图的全丢、要重花钱);running:false = 那次已经结束,这时才去 get_storyboards / get_script 看产物有没有落库。\n⚠️ 服务重启会让 agent 在途登记归零,重启期间发起的运行也会显示为无在途。\n★generate_videos 整集出视频的接力链看返回里的 video_run 段(它落库,重启不会凭空消失):shots_total / shots_with_video / shots_remaining = 共几镜、已出几镜、剩几镜;running:true = 链在跑,别重发 generate_videos;resumed_after_restart>0 = 中途服务重启过、已自动续跑(已出视频与中断前已派发的镜不重出不重扣);status=interrupted = 重启后没自动续跑(interrupt_reason 写原因),重新 quote_videos 后 generate_videos 会跳过已出的镜;shots_dispatched_without_video = 派发过但没出片的镜,用 get_jobs 看原因、regenerate_shot_video 单补;status=cancelling / cancelled = 客户用 cancel_videos 停了这条链,cancelled_shot_numbers 是没出没扣费的镜。\n★批量出图(整集出帧 / 帧链 / 定妆图 / 设定图 / 场景图等)看 image_batches:每批 kind / status(running / done / cancelled)/ dispatched / in_flight / completed / targets_not_dispatched;status=cancelled = 客户用 cancel_images 停了这一批。",
|
|
9333
9410
|
"tags": [
|
|
9334
9411
|
"episodes"
|
|
9335
9412
|
],
|
|
@@ -11370,7 +11447,167 @@
|
|
|
11370
11447
|
"get": {
|
|
11371
11448
|
"operationId": "get_voice_consistency",
|
|
11372
11449
|
"summary": "查声线一致性扫描的进度与逐镜结果(scan_voice_consistency 启动的)",
|
|
11373
|
-
"description": "查声线一致性扫描的进度与逐镜结果(scan_voice_consistency 启动的)。免费。summary.voice_mismatch=声音不像该角色声线锚的镜号(重点看);dialogue_issues=台词没念完/念错/多出说话声的镜;not_scanned_or_stale=还没扫或视频换过需重扫。speaker_verdict=uncertain 表示人声太短判不了,不是问题。声线不一致的镜:先用 get_pipeline_status 的 native_voice_anchor 确认角色已绑声线,再 regenerate_shot_video
|
|
11450
|
+
"description": "查声线一致性扫描的进度与逐镜结果(scan_voice_consistency 启动的)。免费。summary.voice_mismatch=声音不像该角色声线锚的镜号(重点看);dialogue_issues=台词没念完/念错/多出说话声的镜;not_scanned_or_stale=还没扫或视频换过需重扫。speaker_verdict=uncertain 表示人声太短判不了,不是问题。声线不一致的镜:先用 get_pipeline_status 的 native_voice_anchor 确认角色已绑声线,再 regenerate_shot_video 重出;要保住首尾帧(重出会丢构图)就走 quote_voice_unify → unify_voices,事后把人声转成声线锚的嗓音、不重生视频。做过声线统一的镜带 voice_unify:similarity / coverage / loudness_db 都是 before→after;summary.voice_unified=已进成片的镜号。",
|
|
11451
|
+
"tags": [
|
|
11452
|
+
"episodes"
|
|
11453
|
+
],
|
|
11454
|
+
"parameters": [
|
|
11455
|
+
{
|
|
11456
|
+
"name": "episode_id",
|
|
11457
|
+
"in": "path",
|
|
11458
|
+
"required": true,
|
|
11459
|
+
"schema": {
|
|
11460
|
+
"type": "integer",
|
|
11461
|
+
"exclusiveMinimum": 0
|
|
11462
|
+
}
|
|
11463
|
+
}
|
|
11464
|
+
],
|
|
11465
|
+
"responses": {
|
|
11466
|
+
"200": {
|
|
11467
|
+
"description": "StarReel envelope",
|
|
11468
|
+
"content": {
|
|
11469
|
+
"application/json": {
|
|
11470
|
+
"schema": {
|
|
11471
|
+
"type": "object",
|
|
11472
|
+
"properties": {
|
|
11473
|
+
"code": {
|
|
11474
|
+
"type": "integer"
|
|
11475
|
+
},
|
|
11476
|
+
"message": {
|
|
11477
|
+
"type": "string"
|
|
11478
|
+
},
|
|
11479
|
+
"data": {
|
|
11480
|
+
"description": "Operation result payload"
|
|
11481
|
+
}
|
|
11482
|
+
}
|
|
11483
|
+
}
|
|
11484
|
+
}
|
|
11485
|
+
}
|
|
11486
|
+
},
|
|
11487
|
+
"402": {
|
|
11488
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
11489
|
+
}
|
|
11490
|
+
}
|
|
11491
|
+
}
|
|
11492
|
+
},
|
|
11493
|
+
"/episodes/{episode_id}/voice-unify": {
|
|
11494
|
+
"post": {
|
|
11495
|
+
"operationId": "unify_voices",
|
|
11496
|
+
"summary": "执行事后声线统一(必须先 quote_voice_unify,客户同意后带 quote_id)",
|
|
11497
|
+
"description": "执行事后声线统一(必须先 quote_voice_unify,客户同意后带 quote_id)。只跑报价里的镜,后台串行(每镜约 1~2 分钟)。每镜:分离人声 → 按台词与声纹定位该角色的句子 → 逐句转成声线锚的嗓音(每句时长只变 ≤0.05s,口型与画面不动、不重生视频)→ 回填,环境声与音效原样保留。质检任一不过(转写覆盖率下降 / 时长差 >0.1s / 与锚的相似度没提升 / 响度差 >1dB)就保留原音轨并退回该镜费用。用 get_voice_unify_status 看进度与每镜前后对比;status=applied 的镜重拼成片(rerender_episode)后生效。",
|
|
11498
|
+
"tags": [
|
|
11499
|
+
"episodes"
|
|
11500
|
+
],
|
|
11501
|
+
"parameters": [
|
|
11502
|
+
{
|
|
11503
|
+
"name": "episode_id",
|
|
11504
|
+
"in": "path",
|
|
11505
|
+
"required": true,
|
|
11506
|
+
"schema": {
|
|
11507
|
+
"type": "integer",
|
|
11508
|
+
"exclusiveMinimum": 0
|
|
11509
|
+
}
|
|
11510
|
+
}
|
|
11511
|
+
],
|
|
11512
|
+
"requestBody": {
|
|
11513
|
+
"required": true,
|
|
11514
|
+
"content": {
|
|
11515
|
+
"application/json": {
|
|
11516
|
+
"schema": {
|
|
11517
|
+
"type": "object",
|
|
11518
|
+
"properties": {
|
|
11519
|
+
"quote_id": {
|
|
11520
|
+
"type": "string",
|
|
11521
|
+
"minLength": 1
|
|
11522
|
+
}
|
|
11523
|
+
},
|
|
11524
|
+
"required": [
|
|
11525
|
+
"quote_id"
|
|
11526
|
+
]
|
|
11527
|
+
}
|
|
11528
|
+
}
|
|
11529
|
+
}
|
|
11530
|
+
},
|
|
11531
|
+
"responses": {
|
|
11532
|
+
"200": {
|
|
11533
|
+
"description": "StarReel envelope",
|
|
11534
|
+
"content": {
|
|
11535
|
+
"application/json": {
|
|
11536
|
+
"schema": {
|
|
11537
|
+
"type": "object",
|
|
11538
|
+
"properties": {
|
|
11539
|
+
"code": {
|
|
11540
|
+
"type": "integer"
|
|
11541
|
+
},
|
|
11542
|
+
"message": {
|
|
11543
|
+
"type": "string"
|
|
11544
|
+
},
|
|
11545
|
+
"data": {
|
|
11546
|
+
"description": "Operation result payload"
|
|
11547
|
+
}
|
|
11548
|
+
}
|
|
11549
|
+
}
|
|
11550
|
+
}
|
|
11551
|
+
}
|
|
11552
|
+
},
|
|
11553
|
+
"402": {
|
|
11554
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
11555
|
+
}
|
|
11556
|
+
}
|
|
11557
|
+
}
|
|
11558
|
+
},
|
|
11559
|
+
"/episodes/{episode_id}/voice-unify/quote": {
|
|
11560
|
+
"get": {
|
|
11561
|
+
"operationId": "quote_voice_unify",
|
|
11562
|
+
"summary": "★原声剧(视频自带人声)「同一个角色前后嗓音不一样」、又不想为声线重出视频丢掉首尾帧构图时用",
|
|
11563
|
+
"description": "★原声剧(视频自带人声)「同一个角色前后嗓音不一样」、又不想为声线重出视频丢掉首尾帧构图时用。免费报价、只读。列出本集每个有台词的镜要不要做「事后声线统一」及原因:to_process=出片时没送声线锚 / 送的是旧锚,一定处理;conditional=出片时已送进当前锚,执行时先测声纹,对得上就跳过、不收费;skipped=不动(锁定镜、实拍、已有换轨产物、角色没有声线锚等,见 reason_text)。多人镜按说话人分别判,只改需要处理的那个人的句子。按转换的人声秒数计费:estimated_points 是上界、typical_points 是通常花费,两个都告诉客户,客户同意后带 quote_id 调 unify_voices。角色没有声线锚的先 set_character_voice 或 set_voice_anchor_from_shot(挑一镜嗓音最对的当基准)。逐剧灰度,未开通回 403。",
|
|
11564
|
+
"tags": [
|
|
11565
|
+
"episodes"
|
|
11566
|
+
],
|
|
11567
|
+
"parameters": [
|
|
11568
|
+
{
|
|
11569
|
+
"name": "episode_id",
|
|
11570
|
+
"in": "path",
|
|
11571
|
+
"required": true,
|
|
11572
|
+
"schema": {
|
|
11573
|
+
"type": "integer",
|
|
11574
|
+
"exclusiveMinimum": 0
|
|
11575
|
+
}
|
|
11576
|
+
}
|
|
11577
|
+
],
|
|
11578
|
+
"responses": {
|
|
11579
|
+
"200": {
|
|
11580
|
+
"description": "StarReel envelope",
|
|
11581
|
+
"content": {
|
|
11582
|
+
"application/json": {
|
|
11583
|
+
"schema": {
|
|
11584
|
+
"type": "object",
|
|
11585
|
+
"properties": {
|
|
11586
|
+
"code": {
|
|
11587
|
+
"type": "integer"
|
|
11588
|
+
},
|
|
11589
|
+
"message": {
|
|
11590
|
+
"type": "string"
|
|
11591
|
+
},
|
|
11592
|
+
"data": {
|
|
11593
|
+
"description": "Operation result payload"
|
|
11594
|
+
}
|
|
11595
|
+
}
|
|
11596
|
+
}
|
|
11597
|
+
}
|
|
11598
|
+
}
|
|
11599
|
+
},
|
|
11600
|
+
"402": {
|
|
11601
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
11602
|
+
}
|
|
11603
|
+
}
|
|
11604
|
+
}
|
|
11605
|
+
},
|
|
11606
|
+
"/episodes/{episode_id}/voice-unify/status": {
|
|
11607
|
+
"get": {
|
|
11608
|
+
"operationId": "get_voice_unify_status",
|
|
11609
|
+
"summary": "查声线统一的进度与逐镜结果(免费)",
|
|
11610
|
+
"description": "查声线统一的进度与逐镜结果(免费)。summary:applied=已统一(重拼成片后生效)/ kept_original=质检没过、保留原音轨、费用已退(reason 写了哪项没过)/ skipped=测下来声纹本来就对得上或找不到该角色的人声 / errors=失败(费用已退)/ superseded=处理期间镜头被重出、换版本或锁定,结果作废未写回(费用已退)。每镜带 similarity(before→after,与声线锚的相似度)、coverage、loudness_db、points;stale=视频或产物换过、结论过期。",
|
|
11374
11611
|
"tags": [
|
|
11375
11612
|
"episodes"
|
|
11376
11613
|
],
|
|
@@ -16697,6 +16934,72 @@
|
|
|
16697
16934
|
}
|
|
16698
16935
|
}
|
|
16699
16936
|
},
|
|
16937
|
+
"/storyboards/{storyboard_id}/voice-unify/preview": {
|
|
16938
|
+
"post": {
|
|
16939
|
+
"operationId": "preview_voice_unify",
|
|
16940
|
+
"summary": "对单镜试听声线统一效果(免费、不写回、不扣费)",
|
|
16941
|
+
"description": "对单镜试听声线统一效果(免费、不写回、不扣费)。异步:start=true 启动(约 1~2 分钟),之后不带 start 再调一次取结果;结果里 productUrl 是处理后的视频(可直接听),checks 是四项质检结论。默认用该角色的声线锚当目标嗓音;reference_storyboard_id=同一集里嗓音最对的那一镜时,改用那一镜的人声当目标(适合角色还没绑锚、先挑基准的情况,speaker 指定转哪个角色)。",
|
|
16942
|
+
"tags": [
|
|
16943
|
+
"storyboards"
|
|
16944
|
+
],
|
|
16945
|
+
"parameters": [
|
|
16946
|
+
{
|
|
16947
|
+
"name": "storyboard_id",
|
|
16948
|
+
"in": "path",
|
|
16949
|
+
"required": true,
|
|
16950
|
+
"schema": {
|
|
16951
|
+
"type": "integer",
|
|
16952
|
+
"exclusiveMinimum": 0
|
|
16953
|
+
}
|
|
16954
|
+
}
|
|
16955
|
+
],
|
|
16956
|
+
"requestBody": {
|
|
16957
|
+
"required": false,
|
|
16958
|
+
"content": {
|
|
16959
|
+
"application/json": {
|
|
16960
|
+
"schema": {
|
|
16961
|
+
"type": "object",
|
|
16962
|
+
"properties": {
|
|
16963
|
+
"speaker": {
|
|
16964
|
+
"type": "string"
|
|
16965
|
+
},
|
|
16966
|
+
"reference_storyboard_id": {
|
|
16967
|
+
"type": "integer",
|
|
16968
|
+
"exclusiveMinimum": 0
|
|
16969
|
+
}
|
|
16970
|
+
}
|
|
16971
|
+
}
|
|
16972
|
+
}
|
|
16973
|
+
}
|
|
16974
|
+
},
|
|
16975
|
+
"responses": {
|
|
16976
|
+
"200": {
|
|
16977
|
+
"description": "StarReel envelope",
|
|
16978
|
+
"content": {
|
|
16979
|
+
"application/json": {
|
|
16980
|
+
"schema": {
|
|
16981
|
+
"type": "object",
|
|
16982
|
+
"properties": {
|
|
16983
|
+
"code": {
|
|
16984
|
+
"type": "integer"
|
|
16985
|
+
},
|
|
16986
|
+
"message": {
|
|
16987
|
+
"type": "string"
|
|
16988
|
+
},
|
|
16989
|
+
"data": {
|
|
16990
|
+
"description": "Operation result payload"
|
|
16991
|
+
}
|
|
16992
|
+
}
|
|
16993
|
+
}
|
|
16994
|
+
}
|
|
16995
|
+
}
|
|
16996
|
+
},
|
|
16997
|
+
"402": {
|
|
16998
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
16999
|
+
}
|
|
17000
|
+
}
|
|
17001
|
+
}
|
|
17002
|
+
},
|
|
16700
17003
|
"/videos/edit-capabilities": {
|
|
16701
17004
|
"get": {
|
|
16702
17005
|
"operationId": "get_edit_capabilities",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starreel/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.242",
|
|
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.242",
|
|
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.242",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
},
|