@starreel/mcp 0.1.177 → 0.1.196
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 +20 -3
- package/dist/i18n/tools.en.json +12 -10
- package/dist/i18n/tools.zh-CN.json +22 -20
- package/dist/tools/produce.js +46 -18
- package/openapi.json +230 -25
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/tools/produce.js
CHANGED
|
@@ -71,16 +71,23 @@ const QUOTE_RANGE_HINT = '★返回两个数:estimated_points 是**上界**(按
|
|
|
71
71
|
const REVIEW_GATE_HINT = (tool, layer) => `\n★【${layer}审查硬闸·免费】本步前必须先调 ${tool}:把返回的 findings 逐条原样告诉客户` +
|
|
72
72
|
`(每条带 code=问题类型、shots=命中镜号、action=该调哪个工具修),再把 review_token 传进本工具。` +
|
|
73
73
|
`未审查会被 400 拒。审查后又改了内容 → token 自动失效,复审一次即可(仍免费)。` +
|
|
74
|
+
`单镜工具(generate_shot_frame / regenerate_shot_video)只核本镜与相邻镜:改了别的镜不用复审;本镜、相邻镜或共享资产变了才 400——` +
|
|
75
|
+
`这时带 base_review_token=<旧 token> 调审查工具做增量复审,只重审变更镜,质检也只看变更镜。` +
|
|
74
76
|
`有 error 时默认拦截;客户知情并坚持照现状继续,才带 acknowledge_review:true——` +
|
|
75
77
|
`带病推进大概率产出废片且照常扣费${ALWAYS_ASK('acknowledge_review 只代表客户本人同意,')};` +
|
|
76
78
|
`托管环节只有白名单内的启发式 error 能带 auto_acknowledge:true 放行(平台判,不在白名单回 400 AUTOPILOT_MUST_ASK:must_ask_customer=true 才暂停问客户,false = 按 action 自修复审)。` +
|
|
77
79
|
`★灰度剧还要你(agent)亲自质检:按 ${tool} 返回的 agent_qc 逐件看素材、逐条答清单,调 submit_qc_report 提交后这张 token 才能用` +
|
|
78
80
|
`(没交 → 400 agent_qc_required;报告有问题 → 与 error 同样默认拦)。`;
|
|
79
81
|
/** 五个审查工具共用:平台审查之外,外部 agent 亲自看素材的质检(2026-10-14 用户拍板)。 */
|
|
80
|
-
const AGENT_QC_HINT = '\n
|
|
82
|
+
const AGENT_QC_HINT = '\n★【增量复审·省时省量】review_storyboards / review_frames / review_assets 可带 base_review_token(上一张已交质检且 verdict=pass 的本层 token):' +
|
|
83
|
+
'只把变更镜及其相邻镜列进 agent_qc.materials、findings 只回这些镜(incremental.applied=true,另有 findings_hidden 计数),质检报告只需覆盖它们;' +
|
|
84
|
+
'共享资产变了、base 没质检通过时自动退回整集(incremental.reason 说明原因)。改一两镜后别整集重审。' +
|
|
85
|
+
'\n★【agent 亲自质检·免费】返回的 agent_qc 里有本层清单(checklist)和本集要看的素材(materials,每件一个 ref,图/视频给链接)。' +
|
|
81
86
|
'平台只判「有没有、在不在、被没被拒」,「像不像、对不对、好不好」要你自己看:图片下载打开看、视频至少抽开头/中间/结尾帧、文本用 tool 通读。' +
|
|
82
87
|
'逐条回答清单(ok / issue / na,issue 写明哪件什么问题),看过的每个 ref 都列进 inspected,调 submit_qc_report 提交;质检结论原样讲给客户。' +
|
|
83
88
|
'agent_qc.required=true 时没提交报告这张 review_token 进不了下一步(400 agent_qc_required),报告有问题与平台 error 同样默认拦。';
|
|
89
|
+
/** 增量复审(缺口 #16):上一张本层 token,已交质检且 pass 时只重审变更镜。 */
|
|
90
|
+
const BASE_REVIEW_ARG = z.string().optional().describe('增量复审:上一张本层 review_token(已交 agent 质检且 verdict=pass)。带上只重审变更镜及其相邻镜,素材与质检只覆盖它们;不满足条件自动退回整集');
|
|
84
91
|
/** 资产层 token:出镜头图同时要分镜层(review_token)与资产层两张,资产层这张单独一个参数。 */
|
|
85
92
|
const ASSET_REVIEW_ARG = {
|
|
86
93
|
asset_review_token: z.string().optional().describe('★来自 review_assets 的凭据(资产层硬闸:角色形象图/场景图/道具图;灰度剧必填,缺了 400 会点名 review_assets)。与分镜层的 review_token 一起传'),
|
|
@@ -138,9 +145,9 @@ export const WORKFLOW_HINT = AUTOPILOT_HINT +
|
|
|
138
145
|
'★visual_lock/art_bible 只写画面级/世界级锁(镜头语言·环境·美术基调·禁入元素),**绝不为具体角色钉服装/发型/外观细节**——' +
|
|
139
146
|
'角色外观的唯一真相源是 extract_assets 产出的人物档案(要改走 update_character);两处都写必然互相矛盾,' +
|
|
140
147
|
'定妆图跟档案、设定图跟视觉锁,一致性闸按定妆图拒收 → 设定图/镜头帧**结构性连拒**,重掷多少次都过不了、纯白花钱。' +
|
|
141
|
-
'
|
|
148
|
+
'★★【时代契约·免费·非当代或超现实题材出图前必设】setting_brief 里的世界观是**自由文本**,只能提供背景、压不住画面;' +
|
|
142
149
|
'真正能压过视觉锁的是**结构化时代契约**:用 set_era_contract 设本集档位' +
|
|
143
|
-
'(modern/republican/historical/fantasy),get_era_contract 读现值。**不设就是空着**——' +
|
|
150
|
+
'(modern/republican/historical/fantasy/surreal),get_era_contract 读现值。**不设就是空着**——' +
|
|
144
151
|
'平台只能靠提示词正文堆字对抗,现代物件混进古代画面、场景图画成别的时代,基本都由这里空着导致。' +
|
|
145
152
|
'★仙侠/奇幻/仙境类**必须填 fantasy,别填 historical**:后者要求考据写实,会把发光灵气、悬浮地貌、' +
|
|
146
153
|
'非人化形一并判成「不合时代」,把画面往写实古代拽。某一场要破例(如奇幻世界里一场现代回忆)' +
|
|
@@ -214,7 +221,7 @@ export const WORKFLOW_HINT = AUTOPILOT_HINT +
|
|
|
214
221
|
'★★【单镜路径同样受审查闸】:generate_shot_frame 同样要带分镜层 review_token,regenerate_shot_video 同样要带镜头图片层 review_token——' +
|
|
215
222
|
'别指望用逐镜工具绕开审查(实测有整集 25 镜全靠单镜出帧、一道闸都没碰到的做法,成片返工全是真扣费)。' +
|
|
216
223
|
'出完帧**不会**让分镜层 token 失效(指纹只看分镜内容);只有改了分镜内容——update_shot / 导入 / 增删镜 / 改角色绑定——才要复审一次(免费、秒级)。' +
|
|
217
|
-
'
|
|
224
|
+
'出完一镜的帧只让本镜与相邻镜的**镜头图片层** token 失效;要对它们 regenerate_shot_video 时带 base_review_token 增量 review_frames 即可。' +
|
|
218
225
|
'★★【原声剧先锁声线,再批量出视频】use_clip_audio=true(默认)时每镜嗓音由视频厂商各自采样,不锁必漂,事后统一要逐镜重出。' +
|
|
219
226
|
'有客户授权音源→clone_voice+set_character_voice,在 generate_videos 之前;没有→每个说话角色先用单镜工具 quote_regenerate_shot_video→regenerate_shot_video 出一镜台词较长的' +
|
|
220
227
|
'(generate_videos 没有按镜参数、只批量补缺视频的镜;单镜重生对还没有视频的镜同样可用),' +
|
|
@@ -666,7 +673,8 @@ export function registerProduceTools(server, client) {
|
|
|
666
673
|
'两者均暂停本次自动尾帧回写与续接,先复核视频;字段缺席不代表做过检测,也不要直接重试收费生成。' +
|
|
667
674
|
'★not_required=旁白/片尾卡镜:帧与视频由成片层渲染,本镜不需要生成——数补齐进度时把它当已完成,别重试。' +
|
|
668
675
|
'fail_reason(sensitive/text_sensitive/copyright/face_mismatch/account_overdue/quota_full/authorizing/' +
|
|
669
|
-
'insufficient_credits/transient/repeat_rejected/diagnosis_required/pair_collateral/model_unavailable)、retryable(true=可重试;false=先按fail_hint处理,勿原样重试)、fail_hint(人读文案)。' +
|
|
676
|
+
'insufficient_credits/transient/repeat_rejected/diagnosis_required/pair_collateral/model_unavailable/requote_required/needs_content_fix/contract_rejected/unknown)、retryable(true=可重试;false=先按fail_hint处理,勿原样重试)、fail_hint(人读文案)。' +
|
|
677
|
+
'★视频失败的镜还带 video_charge_status(charged=已扣 video_charged_points 点/no_charge_recorded=本地流水未记扣费/pending=扣费结论未出;没有该字段=扣费状态未知)。只有 charged 是确定结论;no_charge_recorded 不等于已退款,别替平台承诺,要确认扣没扣用 get_drama_bill。★requote_required=报价条件已变、本镜未派发未扣费:先 quote_videos 重新报价(免费)再发起。' +
|
|
670
678
|
'★model_unavailable=所选图片/视频模型的厂商已暂停或暂不可用:fail_hint 里列了当前可用的替代模型(扣没扣费以错误文案为准,别替平台向用户承诺已退款),' +
|
|
671
679
|
'问用户后用 update_project_settings 改 video_engine/image_model(或只对本镜用 regenerate_shot_video 的 model / generate_shot_frame 的 image_model)再生成,原样重试只会再失败。' +
|
|
672
680
|
'★diagnosis_required=同输入同细因连败或已有候选等待判决:先查看已有候选及审计依据。审计故障先重审同一候选,原因未知先复核,不得直接改剧本或重复生成。' +
|
|
@@ -801,26 +809,27 @@ export function registerProduceTools(server, client) {
|
|
|
801
809
|
'★code=forbidden_term 的 finding 带 `terms` 字段(命中的具体词,如「背景音乐」「强光」)与 `shots`(镜号),' +
|
|
802
810
|
'照着这两个去 update_shot 改掉即可,不用逐字猜。' +
|
|
803
811
|
'★禁区词判**否定语义**:写「无背景音乐」「不要配乐」不算违规(那是在遵守约束),不必为此改稿。' +
|
|
804
|
-
'★warnings 里的「动作过载」(action_overload,advisory 不拦):一镜塞了超过时长承载量的独立动作,出视频前用 split_shot 拆开或删动作——成片后靠慢放/叠化补救不了。多人各做一件事或本身连贯的一串可忽略。' + AGENT_QC_HINT, { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/storyboards
|
|
812
|
+
'★warnings 里的「动作过载」(action_overload,advisory 不拦):一镜塞了超过时长承载量的独立动作,出视频前用 split_shot 拆开或删动作——成片后靠慢放/叠化补救不了。多人各做一件事或本身连贯的一串可忽略。' + AGENT_QC_HINT, { episode_id: z.number().int().positive(), base_review_token: BASE_REVIEW_ARG }, async ({ episode_id, base_review_token }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/storyboards`, base_review_token ? { base_review_token } : undefined)));
|
|
805
813
|
server.tool('review_frames', '【第③道硬闸·免费】审查镜头图片层:角色身份锚覆盖(缺定妆图的角色在镜头里必漂)、出图失败率、' +
|
|
806
814
|
'孤儿角色变体、场景图被人物污染。★generate_videos 之前必须先跑本工具——出视频是全链最贵的一步,' +
|
|
807
815
|
'拿着漂移的首帧整集出视频是最典型的废片形态。按 findings.action 修完(多为 generate_character_portraits / ' +
|
|
808
816
|
'generate_shot_frame 单镜重生)再复审。' +
|
|
809
817
|
'★还会报**镜间接缝**(warning,不拦):code=seam_unchained(标了连续却从没做过首尾帧衔接,或发起的衔接重生没落地 / 衔接后首帧又被重生)/' +
|
|
810
818
|
'seam_broken(接过但没接上,或上一镜尾帧在衔接之后又重生过),shots 是「与上一镜的缝有问题」的那一镜。出视频前修最便宜——视频按首帧生成,' +
|
|
811
|
-
'首帧与上镜尾帧对不上,成片就是一次跳切。修法看 action(整集 chain_frames 先 dry_run;单道 chain_shot_from_prev / chain_shot_from)。' + AGENT_QC_HINT, { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/frames
|
|
819
|
+
'首帧与上镜尾帧对不上,成片就是一次跳切。修法看 action(整集 chain_frames 先 dry_run;单道 chain_shot_from_prev / chain_shot_from)。' + AGENT_QC_HINT, { episode_id: z.number().int().positive(), base_review_token: BASE_REVIEW_ARG }, async ({ episode_id, base_review_token }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/frames`, base_review_token ? { base_review_token } : undefined)));
|
|
812
820
|
server.tool('review_assets', '【资产层硬闸·免费】审查本集**出镜**用到的角色形象图、场景图、道具图——覆盖与质量:' +
|
|
813
821
|
'出镜角色缺定妆图 / 缺设定图 / 还在生成 / 生成失败 / 设定图被一致性闸拒收(hint 带拒收理由);' +
|
|
814
822
|
'场景缺空景基板;分镜引用的道具缺道具图 / 被拒;道具图与本镜时代形制冲突;缺色彩脚本(warning)。' +
|
|
815
823
|
'★出完定妆图、设定图、场景图、道具图后都调一次;generate_frames / generate_shot_frame 之前必须审过——' +
|
|
816
824
|
'把返回的 review_token 作为 **asset_review_token**,连同分镜层的 review_token 一起传(两张都要)。' +
|
|
817
825
|
'只看资产本身:出完镜头图不会让它失效;换了定妆图/场景图/道具图会失效,复审即可(免费、秒级)。' +
|
|
818
|
-
'findings 逐条讲给客户(code=问题类型、names=哪个角色/场景/道具、shots=影响的镜号、action=该调哪个工具修)。' + AGENT_QC_HINT, { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/assets
|
|
826
|
+
'findings 逐条讲给客户(code=问题类型、names=哪个角色/场景/道具、shots=影响的镜号、action=该调哪个工具修)。' + AGENT_QC_HINT, { episode_id: z.number().int().positive(), base_review_token: BASE_REVIEW_ARG }, async ({ episode_id, base_review_token }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/assets`, base_review_token ? { base_review_token } : undefined)));
|
|
819
827
|
server.tool('review_videos', '【视频与配音层硬闸·免费】审查本集视频与配音——覆盖与质量:缺视频 / 还在生成 / 生成失败 / 被厂商拒;' +
|
|
820
828
|
'首帧换过而视频还是旧帧出的(video_stale);疑似片尾硬切、无台词镜意外人声(warning);' +
|
|
821
829
|
'配音剧:台词镜缺配音、会开口的角色没音色、缺旁白角色;原声剧:出片时没挂上当前声线的镜、没锁声线的角色;缺配乐(warning)。' +
|
|
822
830
|
'★出完视频、配音(generate_tts)、配乐后都调一次;compose_episode 之前必须审过,带返回的 review_token。' +
|
|
823
|
-
'更细的检查(要解码画面/音轨)另有 scan_intra_shot_cuts / scan_dialogue_coverage / audit_silent_shot_audio;拼完成片再跑 review_final_cut。' +
|
|
831
|
+
'更细的检查(要解码画面/音轨)另有 scan_intra_shot_cuts / scan_dialogue_coverage / audit_silent_shot_audio;拼完成片再跑 review_final_cut。' +
|
|
832
|
+
'★返回带 post_production_advisory = 剧本标注「后期」的叙事必需特效还没处理(平台不会合成):原样告诉客户,用 get_post_production_checklist 看清单。' + AGENT_QC_HINT, { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/videos`)));
|
|
824
833
|
server.tool('submit_qc_report', '提交你(agent)亲自看素材做的质检报告。免费。先调对应层的 review_*(script / storyboards / assets / frames / videos),' +
|
|
825
834
|
'按返回的 agent_qc 逐件打开 materials 看、逐条回答 checklist,再调本工具。' +
|
|
826
835
|
'★平台只校验报告**是否完整**,不评判你的结论:checklist 每个 id 都要答(ok / issue / na,issue 必须写 note 说清哪件什么问题);' +
|
|
@@ -916,7 +925,7 @@ export function registerProduceTools(server, client) {
|
|
|
916
925
|
'gpt-image-2.5-flare(默认·基础11点+每张参考图18点)/gpt-image-2.5-sunburst(同价·中文字形与细节更准)/' +
|
|
917
926
|
'gemini-3.1-flash-image(Nano Banana 2·71点)/gemini-3-pro-image(Nano Banana Pro·更精细·175点)/' +
|
|
918
927
|
'gemini-3.1-flash-lite-image(Nano Banana 2 Lite·便宜·31点)/doubao-seedream-5-0-260128(Seedream 5.0)'),
|
|
919
|
-
allow_era_ref_conflict: z.boolean().optional().describe('
|
|
928
|
+
allow_era_ref_conflict: z.boolean().optional().describe('★默认不传。时代审核判定角色定妆参考与时代设定冲突时,出图会被拦下(未扣费):客户上传的定妆图及其派生图报 400 ERA_USER_REF_CONFLICT,平台生成的定妆图报 era_identity_ref_blocked。**先把冲突原因告诉客户、由客户确认造型无误**后才带 true' + ALWAYS_ASK('allow_era_ref_conflict ') + ':这些图保留不剔、照常出图。造型真不对就改定妆图,时代设定错了就 set_era_contract'),
|
|
920
929
|
}, async ({ episode_id, quote_id, frame_type, image_model, review_token, asset_review_token, acknowledge_review, auto_acknowledge, allow_era_ref_conflict }) => jsonResult(await client.producePost(`/episodes/${episode_id}/frames/generate`, {
|
|
921
930
|
quote_id, frame_type, image_model, review_token, asset_review_token, acknowledge_review, auto_acknowledge, allow_era_ref_conflict,
|
|
922
931
|
})));
|
|
@@ -952,7 +961,7 @@ export function registerProduceTools(server, client) {
|
|
|
952
961
|
reopen_pair_id: z.string().optional().describe('来自 get_storyboards 该镜的同名字段;只重掷有问题的那一侧,不必再传 frame_type'),
|
|
953
962
|
image_model: z.string().optional().describe('临时覆盖本次重画的图片模型(★必须与 quote_shot_frame 传的那个一致,否则 400 IMAGE_MODEL_MISMATCH;不传=用 drama 级设定,默认 ChatGPT Image 2.5 Flare);取值同 generate_frames'),
|
|
954
963
|
allow_missing_terminal: z.boolean().optional().describe('★逃生门,默认不传。本镜标为「状态改变」却没写终态时,出尾帧会被前置闸拦下;带 true 表示「我知道,照现状出」。正解是先 update_shot 补 last_frame_prompt——那类镜照现状出的成功率 9.4%,这个参数只用于确认本镜就该「几乎不变」的场合'),
|
|
955
|
-
allow_era_ref_conflict: z.boolean().optional().describe('
|
|
964
|
+
allow_era_ref_conflict: z.boolean().optional().describe('★默认不传。时代审核判定角色定妆参考与时代设定冲突时,出图会被拦下(未扣费):客户上传的定妆图及其派生图报 400 ERA_USER_REF_CONFLICT,平台生成的定妆图报 era_identity_ref_blocked。**先把冲突原因告诉客户、由客户确认造型无误**后才带 true' + ALWAYS_ASK('allow_era_ref_conflict ') + ':这些图保留不剔、照常出图。造型真不对就改定妆图,时代设定错了就 set_era_contract'),
|
|
956
965
|
...SHOT_REGEN_ARG,
|
|
957
966
|
}, async ({ storyboard_id, quote_id, review_token, asset_review_token, acknowledge_review, auto_acknowledge, frame_type, replace_user_frame, reopen_pair_id, image_model, allow_missing_terminal, allow_era_ref_conflict, customer_approved_more_regens }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/frame/generate`, { quote_id, review_token, asset_review_token, acknowledge_review, auto_acknowledge, frame_type, replace_user_frame, reopen_pair_id, image_model, allow_missing_terminal, allow_era_ref_conflict, customer_approved_more_regens })));
|
|
958
967
|
// ---------- 出视频(videos,大额) ----------
|
|
@@ -986,7 +995,7 @@ export function registerProduceTools(server, client) {
|
|
|
986
995
|
server.tool('compose_episode', '把某一集所有镜头视频拼成一条成片(终拼)。**免费**(纯拼接,无需报价确认),后台异步。' +
|
|
987
996
|
'发起前有终拼预检:缺视频的镜或仍在生成中的视频任务会 400 硬阻断并列出问题镜(blockers),' +
|
|
988
997
|
'补齐后重试;确要拼部分成片传 force=true(缺视频镜被跳过,成片缺镜,留痕)。' +
|
|
989
|
-
'响应里的 advisories(时长偏差/孤儿任务/缺TTS)只提醒不阻断,建议逐条处理后再拼。发起后用 get_final_cut 轮询。' +
|
|
998
|
+
'响应里的 advisories(时长偏差/孤儿任务/缺TTS/post_production_pending 后期特效未完成)只提醒不阻断,建议逐条处理后再拼。发起后用 get_final_cut 轮询。' +
|
|
990
999
|
REVIEW_GATE_HINT('review_videos', '视频与配音') +
|
|
991
1000
|
'\n★【完成后质检·免费】成片出来后跑 review_final_cut(缺镜/字幕放不下/身份锚/跳轴/错别字,proofread=false 则不扣费),' +
|
|
992
1001
|
'结论讲给客户;客户确认后才 confirm_delivery_acceptance' + ALWAYS_ASK('交付验收') + '。force 只越过终拼预检,不越过审查闸。', {
|
|
@@ -1271,7 +1280,7 @@ export function registerProduceTools(server, client) {
|
|
|
1271
1280
|
'后续镜之间背景也会一路漂。它与定妆图是一对:定妆图锚人、场景图锚景。' +
|
|
1272
1281
|
'★出得不对不要重调本工具(它只补缺图的场景、已有图的一律跳过):' +
|
|
1273
1282
|
'`get_scene_prompt` 读正文 → `update_scene` 改 image_prompt → `regenerate_scene_image` 单场重出。' +
|
|
1274
|
-
'
|
|
1283
|
+
'★非当代或超现实题材先设 `set_era_contract`,否则基板会画成别的时代,下游整场的镜头帧跟着错。' +
|
|
1275
1284
|
'★进度看 `get_pipeline_status` 的 generate_scene_images 步。' + CONFIRM_HINT + ASSET_QC_HINT, { drama_id: z.number().int().positive(), quote_id: z.string().describe('来自 quote_scene_images') }, async ({ drama_id, quote_id }) => jsonResult(await client.producePost(`/dramas/${drama_id}/scene-images/generate`, { quote_id })));
|
|
1276
1285
|
// ========== A · 客户上传自己的图片 ==========
|
|
1277
1286
|
server.tool('upload_image', '把本地图片上传到我方 COS,返回 image_url(字节直传 COS、不过业务服务器)。' +
|
|
@@ -1598,7 +1607,7 @@ export function registerProduceTools(server, client) {
|
|
|
1598
1607
|
const suffix = qs.toString() ? `?${qs.toString()}` : '';
|
|
1599
1608
|
return jsonResult(await client.produceGet(`/episodes/${episode_id}/dialogue-coverage${suffix}`));
|
|
1600
1609
|
});
|
|
1601
|
-
server.tool('update_shot', '逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、面部表情(expression_hint)、时长(duration)、成片变速(speed_factor)、角色绑定(character_ids)、画外音标记(character_presence)与服装绑定(active_wardrobe_id / appearance_wardrobes)。只传要改的字段、其余不动。★改镜(成功或被拒)都会作废覆盖本镜的未消费报价,生成时回 409 QUOTE_INVALIDATED——先改成功、回读核对,再报价。' +
|
|
1610
|
+
server.tool('update_shot', '逐镜编辑:改单个分镜的文本内容(景别/动作/台词/画面描述/运镜等)、面部表情(expression_hint)、时长(duration)、成片变速(speed_factor)、镜间转场(transition_type / transition_duration_ms)、角色绑定(character_ids)、画外音标记(character_presence)与服装绑定(active_wardrobe_id / appearance_wardrobes)。只传要改的字段、其余不动。★改镜(成功或被拒)都会作废覆盖本镜的未消费报价,生成时回 409 QUOTE_INVALIDATED——先改成功、回读核对,再报价。' +
|
|
1602
1611
|
'**免费**(纯文本写库)。★改 dialogue 会自动失效本镜已生成的 TTS 配音与字幕(需重出 tts);' +
|
|
1603
1612
|
'改文本不会自动重出图/视频,如需让画面跟上文本改动,改完再 regen 对应镜。用 get_storyboards 查改后结果(每镜带 character_ids / character_bindings / scene_id / prop_ids / active_wardrobe_id / appearance_wardrobes)。' +
|
|
1604
1613
|
'★★【换衣服改这里,不是改文字】出图穿什么由**服装绑定**决定:单人镜用 active_wardrobe_id(整镜一件),' +
|
|
@@ -1658,6 +1667,8 @@ export function registerProduceTools(server, client) {
|
|
|
1658
1667
|
shot_intent: z.string().optional().describe('这镜为什么存在(叙事意图)'),
|
|
1659
1668
|
duration: z.number().positive().optional().describe('本镜时长(秒,可带小数如 2.5)。上限=本剧视频引擎的单镜上限,超出直接拒并告知上限(更长内容用 split_shot 拆镜)。有台词时平台按语速律只抬不降,抬了会在回执 speech_duration_note 里说。★改时长不会自动重出视频:已有视频仍是旧长度,要厂商按新时长出就 regenerate_shot_video(报价按新时长算)。★别拿加长治「动作太慢」——同样的动作摊到更长时间里只会更慢,见 qa_tools「动作太慢」。★改短后若本镜动作起止姿态里的秒数时间轴超出新时长,回执带 pose_timeline_advisory:那段时间轴出视频时已自动不送,把新分秒动作写进 video_prompt'),
|
|
1660
1669
|
speed_factor: z.number().positive().nullable().optional().describe('成片变速:<1 慢镜、>1 快放、null 清除(0.5–2.0,越界被钳到范围内)。只在终拼/剪映导出时变速播放(画面 setpts + 声音 atempo,音高不变),**不重出视频、不扣费**,但会改变本镜在成片里占的时长。适合做慢镜/升格氛围;治不了「动作没演出来」——那是视频内容本身,要改 video_prompt 重出;也治不了一镜塞太多动作(action_overload)——那要拆镜重出。有台词的镜慎用(人声也跟着变快变慢)'),
|
|
1670
|
+
transition_type: z.enum(['cut', 'fade', 'wipe_left', 'flash_white', 'flash_black', 'zoom_punch', 'whip_pan', 'glass_shatter', 'invert_flash']).nullable().optional().describe('进入本镜的镜间转场(与上一镜的接缝):cut 硬切 / fade 交叉溶解 / flash_white 闪白 / flash_black 闪黑 / wipe_left 擦切 / zoom_punch / whip_pan 甩镜 等;null = 回到剧级默认(同场景默认硬切)。只在终拼生效,**不重出视频、不扣费**;改完调 compose_episode 重新终拼才生效(rerender_episode 沿用已存时间轴,带不上新转场)。叠化会吃掉前镜尾巴同等时长,有对白的接缝用短时长'),
|
|
1671
|
+
transition_duration_ms: z.number().int().min(0).max(2000).nullable().optional().describe('转场时长(毫秒,0–2000)。经验:换场叠化 500、同场 300;闪白/闪黑 130 左右;null = 用剧级默认时长'),
|
|
1661
1672
|
video_engine: z.enum(VIDEO_ENGINES).nullable().optional().describe('本镜视频引擎(**存为镜头设置**,之后这一镜的单镜出视频 / 整集批量 / 重生都按它;null 清除=跟随剧 video_engine)。' +
|
|
1662
1673
|
'与整剧的区别:只改这一镜。设了引擎的镜**不进场景组**(组的规划按剧引擎做),会单独出,失去与相邻镜一次成片的连贯性——别为个别镜随手设。' +
|
|
1663
1674
|
'须支持本剧分辨率(seedance-2.5 只有 480p/720p;hailuo-3 只有 720p/1080p)且容得下本镜时长(seedance-2.5/wan3.0 30s,hailuo-3 15s),否则 400。' +
|
|
@@ -1749,6 +1760,20 @@ export function registerProduceTools(server, client) {
|
|
|
1749
1760
|
+ 'account_overdue 不是你的点数问题,停下告知用户稍后再试,别反复重提;'
|
|
1750
1761
|
+ 'model_unavailable=所选视频模型的厂商已暂停或暂不可用,error 里列了可用的替代模型,问用户后换模型再提。'
|
|
1751
1762
|
+ '\n★带 **verify_rejected** = 这些镜换完复核没通过(断音/重复念/念错),产物没写回、费用已退——换音修不好,改 regenerate_shot_video。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/dialogue-repair-status`)));
|
|
1763
|
+
server.tool('get_post_production_checklist', '读本集的**后期特效清单**(免费)。剧本里 [VFX: …] 标注、分镜提示词里写「后期 / postproduction / composited later」的项,' +
|
|
1764
|
+
'**平台不会自动合成**——出图出视频按约束把它们留空,终拼也不补,不处理成片就缺这些叙事元素。' +
|
|
1765
|
+
'逐项给:镜号 shot_number、时间 start_s~end_s、内容 content、来源 source(vfx_tag 分镜标注 / prompt 提示词 / script_unassigned 改写稿里有但没落到任何镜)、' +
|
|
1766
|
+
'narrative_required(叙事必需;画质类如调色为 false)、status(pending / done_external / waived)。' +
|
|
1767
|
+
'★拼成片前看一遍,把 narrative_required 的 pending 项讲给客户,问他:外部后期做(做完后 mark_post_production_item 标 done_external)、' +
|
|
1768
|
+
'改分镜让平台直接画出来(update_shot 改提示词后重出该镜)、或放弃(标 waived)。review_videos / compose_episode 会对未处理项给 advisory。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/post-production-checklist`)));
|
|
1769
|
+
server.tool('mark_post_production_item', '给后期特效清单里的一项打标记(免费):status=done_external(客户已在平台外完成)/ waived(客户决定不做)/ pending(撤销标记)。' +
|
|
1770
|
+
'key 取自 get_post_production_checklist;分镜或提示词改过后 key 会变,400 时重读清单。' + ALWAYS_ASK('标记后期项') +
|
|
1771
|
+
'——标记只是记账,不会改成片;客户说外部做完了,成片要用外部那一版就走 register_external_delivery。', {
|
|
1772
|
+
episode_id: z.number().int().positive(),
|
|
1773
|
+
key: z.string().min(1).describe('清单项的 key'),
|
|
1774
|
+
status: z.enum(['done_external', 'waived', 'pending']),
|
|
1775
|
+
note: z.string().max(500).optional().describe('备注,如外部完成的工具/版本'),
|
|
1776
|
+
}, async ({ episode_id, key, status, note }) => jsonResult(await client.producePost(`/episodes/${episode_id}/post-production-checklist/mark`, { key, status, ...(note ? { note } : {}) })));
|
|
1752
1777
|
server.tool('get_shot_name_card', '读这一镜的**人物名片**现值(免费):名字、头衔、显示位置那些。'
|
|
1753
1778
|
+ '\n★改之前先读一遍——set_shot_name_card 是**整体覆盖**,不读就改会把没打算动的字段清掉。', { storyboard_id: z.number().int().positive() }, async ({ storyboard_id }) => jsonResult(await client.produceGet(`/storyboards/${storyboard_id}/name-card`)));
|
|
1754
1779
|
server.tool('generate_bgm', '给整集生成/更换 AI 配乐(按情绪弧线)。后台异步,按用量后付不欠费。返回情绪弧线段数与预估耗时;' +
|
|
@@ -2082,7 +2107,7 @@ export function registerProduceTools(server, client) {
|
|
|
2082
2107
|
image_prompt: z.string().optional()
|
|
2083
2108
|
.describe('这一场**空景图**的提示词正文(全量覆盖本场现值)。★先 get_scene_prompt 读现值再改;★写空景——这张是场景基板,画面里不该有人物(人物由镜头帧那层注入)。出图时平台会在正文之上再拼画风块、空景约束与时代锁,不必你写'),
|
|
2084
2109
|
era_contract: z.object({
|
|
2085
|
-
era: z.string().describe('modern / republican / historical / fantasy(也收中文「现代 / 民国 / 古代 /
|
|
2110
|
+
era: z.string().describe('modern / republican / historical / fantasy / surreal(也收中文「现代 / 民国 / 古代 / 仙侠 / 超现实」)'),
|
|
2086
2111
|
positive: z.array(z.string()).optional().describe('本场额外的正向约束(可留空,平台自带该档基线)'),
|
|
2087
2112
|
negative: z.array(z.string()).optional().describe('本场额外的禁止项(可留空)'),
|
|
2088
2113
|
}).nullable().optional()
|
|
@@ -2093,24 +2118,27 @@ export function registerProduceTools(server, client) {
|
|
|
2093
2118
|
server.tool('set_era_contract', '设**本集**的时代契约(免费,纯文本写库)。★这是唯一压得过视觉锁的时代机制——'
|
|
2094
2119
|
+ '古装/民国/仙侠类项目**出图前必设**,不设的话平台只能靠提示词正文堆字对抗,'
|
|
2095
2120
|
+ '时代错乱(现代物件混进古代画面、仙境被画成写实古代)基本都是这里空着导致的。\n'
|
|
2096
|
-
+ '
|
|
2121
|
+
+ '五档怎么选:\n'
|
|
2097
2122
|
+ '· modern —— 现代/当代都市。不确定时用这档。\n'
|
|
2098
2123
|
+ '· republican —— 民国、二十世纪早期。\n'
|
|
2099
2124
|
+ '· historical —— 可考据的历史朝代;这档会要求画面向**考据写实**靠拢。\n'
|
|
2100
2125
|
+ '· fantasy —— ★仙侠/奇幻/仙境:修真世界、妖灵化形一类**非写实**的东方奇幻。'
|
|
2101
2126
|
+ '这类项目**别填 historical**——那档要求考据写实,会把发光灵气、悬浮地貌、非人化形'
|
|
2102
2127
|
+ '一并判成「不合时代」,把画面往写实古代拽。\n'
|
|
2128
|
+
+ '· surreal —— ★现代 + 超现实:当代都市里有作者设定的超现实元素(超现实人体、都市异象)。'
|
|
2129
|
+
+ '基线同 modern;把超现实设定逐条写进 positive,它们被当作世界观正典、审计不判时代冲突;'
|
|
2130
|
+
+ '其中描述人物身体的设定适用于画面里每个人(含无参考的路人与人群),描述环境的只作用于世界。这类项目**别填 fantasy**——那档写死东方仙侠并禁当代服装。\n'
|
|
2103
2131
|
+ '★设完不会自动重出已生成的图:要让画面跟上,得再调 generate_frames / regenerate_scene_image。'
|
|
2104
2132
|
+ '★某一场要破例,用 update_scene 的 era_contract 单独覆写(场级压过集级)。', {
|
|
2105
2133
|
episode_id: z.number().int().positive(),
|
|
2106
2134
|
era: z.string().nullable()
|
|
2107
|
-
.describe('modern / republican / historical / fantasy(也收中文「现代 / 民国 / 古代 /
|
|
2135
|
+
.describe('modern / republican / historical / fantasy / surreal(也收中文「现代 / 民国 / 古代 / 仙侠 / 超现实」)。传 null 清空本集契约'),
|
|
2108
2136
|
positive: z.array(z.string()).optional()
|
|
2109
2137
|
.describe('额外的正向约束(可留空,平台自带该档基线)。写世界观独有的东西,别重复该档已有的常识'),
|
|
2110
2138
|
negative: z.array(z.string()).optional()
|
|
2111
2139
|
.describe('额外的禁止项(可留空)。写该档基线没覆盖、但本项目必须禁的东西'),
|
|
2112
2140
|
}, async ({ episode_id, ...rest }) => jsonResult(await client.producePut(`/episodes/${episode_id}/era-contract`, rest)));
|
|
2113
|
-
server.tool('get_era_contract', '读本集的时代契约现值 + 各场的场级覆写清单 +
|
|
2141
|
+
server.tool('get_era_contract', '读本集的时代契约现值 + 各场的场级覆写清单 + 五个可选档位的用途说明。免费。'
|
|
2114
2142
|
+ '改之前先读一次:能看清「集级设的是哪档、哪几场被单独覆写过」,避免整集统一的时代被逐场填乱。'
|
|
2115
2143
|
+ '★era_contract 为 null 就是**没设**——古装/仙侠项目看到 null 应当先 set_era_contract 再出图。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/era-contract`)));
|
|
2116
2144
|
server.tool('get_scene_prompt', '读某一场**场景图(空景基板)**的提示词正文,供直接微调后用 update_scene 的 image_prompt 写回。免费。' +
|