@starreel/mcp 0.1.61 → 0.1.62
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 +11 -3
- package/dist/tools/guide-data.js +85 -2
- package/dist/tools/guide.js +3 -1
- package/dist/tools/produce.js +24 -4
- package/openapi.json +3 -3
- package/package.json +1 -1
- package/server.json +2 -2
package/SKILL.md
CHANGED
|
@@ -612,9 +612,17 @@ to close") tells the vendor to fit that entire sequence into each 3-second shot.
|
|
|
612
612
|
decide transitions and assemble the cut on your own side. Use this instead of
|
|
613
613
|
`compose_episode` when you want to judge each seam yourself; use
|
|
614
614
|
`compose_episode` when you want the platform's finishing pipeline (pre-flight
|
|
615
|
-
checks, A/V duration parity, loudness mastering).
|
|
616
|
-
`
|
|
617
|
-
|
|
615
|
+
checks, A/V duration parity, loudness mastering). Call
|
|
616
|
+
`get_capabilities_guide(section="local_postproduction")` for the full stage-by-stage
|
|
617
|
+
walkthrough. Three facts that will bite you: **where the voice lives is per-shot —
|
|
618
|
+
read `shots[].voice_track.location`, never the episode-level
|
|
619
|
+
`audio_contract.mode`** (that field is a declaration; fully-offscreen narration
|
|
620
|
+
shots get their voice mixed into the raw clip on our side, so even a `mode="tts"`
|
|
621
|
+
episode contains shots whose voice is already baked in — re-laying it says the line
|
|
622
|
+
twice, skipping it loses it, and `location="missing"` means we know the voice is
|
|
623
|
+
gone and you should regenerate that shot rather than paper over it). Check per line
|
|
624
|
+
with `shots[].spoken_lines[]`: subtitles are per-line but audio is per-shot, so
|
|
625
|
+
**having subtitles never means having sound**; every shot must be cut to
|
|
618
626
|
`trim_head_ms`/`duration_ms` or you splice in frames the platform already QC'd out;
|
|
619
627
|
and all subtitle/dialogue/SFX offsets are relative to **each shot's own trimmed
|
|
620
628
|
start**, not to the final timeline — add whatever overlapping transitions you like
|
package/dist/tools/guide-data.js
CHANGED
|
@@ -141,7 +141,9 @@ export const ENTRY_POINTS = [
|
|
|
141
141
|
{
|
|
142
142
|
customer_has: '想自己剪:要逐镜素材包(裸片 / 对白轨 / 音效 / 配乐 / 字幕)',
|
|
143
143
|
use: ['export_handoff_pack', 'get_handoff_toolchain', 'save_handoff_toolchain'],
|
|
144
|
-
note: '与 `compose_episode`
|
|
144
|
+
note: '与 `compose_episode` 二选一。★人声在哪要**逐镜**看 voice_track.location——整集的 audio_contract.mode 只是声明,' +
|
|
145
|
+
'不是逐镜真值(全画外旁白镜的旁白是平台在完成侧混进裸片的);逐句核对看 spoken_lines,有字幕不等于有声音。' +
|
|
146
|
+
'完整流程见 local_postproduction 段。',
|
|
145
147
|
},
|
|
146
148
|
{
|
|
147
149
|
customer_has: '多语言发行',
|
|
@@ -277,6 +279,77 @@ export const COMMON_REQUESTS = [
|
|
|
277
279
|
{ customer_says: '我想自己剪', do: '`export_handoff_pack` + `get_handoff_toolchain`,不走 `compose_episode`。' },
|
|
278
280
|
{ customer_says: '要配音 / 不要视频原声', do: '`update_project_settings` use_clip_audio=false → `assign_voices` → `generate_tts` → `compose_episode`。' },
|
|
279
281
|
];
|
|
282
|
+
/**
|
|
283
|
+
* v0.9.1371 — 本地后期引导:客户把镜头下载到**自己电脑**上剪。
|
|
284
|
+
* 与 `compose_episode` 二选一——那条是「平台替你拼、带平台级质量闸」,这条是「素材给你、你自己拼」。
|
|
285
|
+
* 不单开一个 guide 工具:入口越多,agent 越要先猜「该调哪个」。
|
|
286
|
+
*/
|
|
287
|
+
export const LOCAL_POSTPRODUCTION = {
|
|
288
|
+
when: '客户要把镜头下载到自己电脑上剪、配乐、烧字幕、优化转场、做字卡、补旁白时走这条;' +
|
|
289
|
+
'想让平台代拼并要平台级质量闸(终拼预检 / 音画等长 / 响度母带)用 `compose_episode`。两条二选一。',
|
|
290
|
+
where_it_runs: '★脚本与 ffmpeg 全部跑在**客户自己的机器**上,平台只发素材 URL 与工具链源码。' +
|
|
291
|
+
'manifest 里是远程 URL,不是服务器上的本地路径;`save_handoff_toolchain` 的 dir 也是客户机器上的绝对路径。' +
|
|
292
|
+
'别把服务器路径当成客户电脑上的路径,也别替客户声称"已经在本地跑完了"——真正执行的是客户那侧。',
|
|
293
|
+
tools: ['export_handoff_pack', 'save_handoff_toolchain', 'get_handoff_toolchain'],
|
|
294
|
+
stages: [
|
|
295
|
+
{
|
|
296
|
+
stage: '1 对需求',
|
|
297
|
+
do: '先问清:哪一集、目标时长、客户有没有自带配乐、字幕样式与排版要求。' +
|
|
298
|
+
'画幅、字幕样式这些项目里已经定过的,用 `get_drama` 读出来直接沿用——客户上一版确认过的偏好别每版重问。',
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
stage: '2 查环境',
|
|
302
|
+
do: '确认客户机器上有 ffmpeg(烧字幕要带 libass)、ffprobe、jq、python3,以及够放整集素材的磁盘。',
|
|
303
|
+
gotcha: '缺 libass 时字幕会**静默不烧**——成片看着正常,只是没有字幕。先查再跑,别等出片才发现。',
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
stage: '3 取包',
|
|
307
|
+
do: '`export_handoff_pack` 拿 manifest → `save_handoff_toolchain` 把三个脚本落到客户目录 → 跑 fetch_pack.py 下载素材并把内联字幕落成 SRT。',
|
|
308
|
+
gotcha: '素材 URL 到 expires_at 就失效;过期重新调 `export_handoff_pack`,别拿旧 manifest 硬跑。',
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
stage: '4 核声音',
|
|
312
|
+
do: '★动剪辑前先核对声音。**逐镜**读 voice_track.location 决定这镜该不该铺对白轨、能不能叠;' +
|
|
313
|
+
'**逐行**读 spoken_lines 逐句核对。location=unknown 的镜必须实际试听裸片。',
|
|
314
|
+
gotcha: '**有字幕不等于有声音**:字幕是逐句的、音频是逐镜的,粒度本来就对不上,' +
|
|
315
|
+
'别按「这镜有字幕」推定每句都有人念。voice_status=caption_no_voice 的行是字卡,本来就没有配音,不是缺失。',
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
stage: '5 判接缝',
|
|
319
|
+
do: '逐个接缝看前后画面,结合动作、景别、视线与声音选切点。scene_boundary="start" 是换场(适合给转场),' +
|
|
320
|
+
'"continue" 是同场景(平台默认硬切)。',
|
|
321
|
+
gotcha: '同场景逐镜叠化是"幻灯片拼凑感"的主因;缺失的交接动作**拉长叠化也补不出来**,该重生成就重生成。',
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
stage: '6 装配',
|
|
325
|
+
do: '先做代表性样段(字卡、混音各挑一两处)给客户看,再整集出片:compile_timeline.py 展开时间轴 → assemble.sh 装配。',
|
|
326
|
+
gotcha: '裁剪与重叠转场都会移动入点——字幕/对白/音效的绝对时间一律交给 compile_timeline.py 算,**别手算累加**。' +
|
|
327
|
+
'只改声音时保留视频码流(-c:v copy),别整片重编码。',
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
stage: '7 验收',
|
|
331
|
+
do: '看**真实成片**:画面、字幕位置、旁白完整性、每个接缝、峰值与音画同步。交付可播放文件 + 版本 + 检查结果。',
|
|
332
|
+
gotcha: '没做的试听或视觉检查要**明说没做**,不许默认通过。',
|
|
333
|
+
},
|
|
334
|
+
],
|
|
335
|
+
voice_rules: [
|
|
336
|
+
'location=separate_file:对白在 dialogue_audio,必须自己铺轨,不铺这镜就没台词。',
|
|
337
|
+
'location=baked_in_clip:人声已在裸片音轨里,**再叠一遍是同一句说两遍**(全画外旁白镜最常见)。',
|
|
338
|
+
'location=missing:平台侧确认缺失。正解是回平台 `regenerate_shot_video` 重生成,或 `generate_tts` 补这句,' +
|
|
339
|
+
'音色复用已授权的克隆音(`list_voices` / `set_character_voice`),别在本地硬凑,也别拿转场掩盖。',
|
|
340
|
+
'人声与配乐分开控制:客户说"这句小一点"是调那句的对白轨增益,不是压整条 BGM;' +
|
|
341
|
+
'整体响度达标**不代表**每句都听得清。',
|
|
342
|
+
'clip.probed_has_audio_stream=false 表示平台实测这条裸片连音轨流都没有;反过来不成立——' +
|
|
343
|
+
'有音轨不代表有人声,全旁白镜的环境音本来就是要求厂商出的。',
|
|
344
|
+
],
|
|
345
|
+
not_verified_until: [
|
|
346
|
+
'「素材下载完成」不是验收。',
|
|
347
|
+
'「脚本退出码 0 / 执行成功」不是验收——ffmpeg 跑完不等于成片对。',
|
|
348
|
+
'「自动转写通过」不等于试听过,别拿它冒充人工听过。',
|
|
349
|
+
'只有看过真实成片(画面 / 字幕位置 / 旁白完整 / 接缝 / 音画同步)才算验收完成;' +
|
|
350
|
+
'平台侧成片用 `get_final_cut` 取。',
|
|
351
|
+
],
|
|
352
|
+
};
|
|
280
353
|
export const HOW_TO_READ = '先按 entry_points 判客户手上的材料该走哪条通道(这是最常被跳过的一步),再按 pipeline 顺序推进、每道 review_gates 必过;' +
|
|
281
354
|
'收费步按 billing.quote_flow 报价确认;遇到质量投诉按 qa_tools 的 symptom 选检测工具先定病因。';
|
|
282
355
|
export function buildGuide() {
|
|
@@ -290,9 +363,10 @@ export function buildGuide() {
|
|
|
290
363
|
optional_boosts: OPTIONAL_BOOSTS,
|
|
291
364
|
billing: BILLING,
|
|
292
365
|
common_requests: COMMON_REQUESTS,
|
|
366
|
+
local_postproduction: LOCAL_POSTPRODUCTION,
|
|
293
367
|
};
|
|
294
368
|
}
|
|
295
|
-
export const GUIDE_SECTIONS = ['entry_points', 'pipeline', 'review_gates', 'qa_tools', 'optional_boosts', 'billing', 'common_requests'];
|
|
369
|
+
export const GUIDE_SECTIONS = ['entry_points', 'pipeline', 'review_gates', 'qa_tools', 'optional_boosts', 'billing', 'common_requests', 'local_postproduction'];
|
|
296
370
|
const head = (s) => /^[a-z][a-z0-9_]*/.exec(s.trim())?.[0] ?? null;
|
|
297
371
|
const inProse = (s) => [...(s ?? '').matchAll(/`([a-z][a-z0-9_]*)`/g)].map((m) => m[1]);
|
|
298
372
|
/** 引导里引用到的全部工具名(去重)——哨兵测试用:每一个都必须真的注册了。 */
|
|
@@ -326,6 +400,15 @@ export function referencedTools() {
|
|
|
326
400
|
BILLING.tools.forEach(add);
|
|
327
401
|
for (const c of COMMON_REQUESTS)
|
|
328
402
|
inProse(c.do).forEach(add);
|
|
403
|
+
// v0.9.1371 — 本地后期段同样纳入哨兵:漏了这几行,这段引导就能悄悄指向不存在的工具。
|
|
404
|
+
LOCAL_POSTPRODUCTION.tools.forEach(add);
|
|
405
|
+
[LOCAL_POSTPRODUCTION.when, LOCAL_POSTPRODUCTION.where_it_runs].forEach((s) => inProse(s).forEach(add));
|
|
406
|
+
for (const s of LOCAL_POSTPRODUCTION.stages) {
|
|
407
|
+
inProse(s.do).forEach(add);
|
|
408
|
+
inProse(s.gotcha).forEach(add);
|
|
409
|
+
}
|
|
410
|
+
for (const r of [...LOCAL_POSTPRODUCTION.voice_rules, ...LOCAL_POSTPRODUCTION.not_verified_until])
|
|
411
|
+
inProse(r).forEach(add);
|
|
329
412
|
return [...out].sort();
|
|
330
413
|
}
|
|
331
414
|
/**
|
package/dist/tools/guide.js
CHANGED
|
@@ -10,7 +10,9 @@ export function registerGuideTools(server) {
|
|
|
10
10
|
'entry_points(客户手上是小说/成熟剧本/想去外部 AI 改写/成品分镜表/自有素材/声音样本/歌曲/产品/已有成片要改/想自己剪/多语言 → 各走哪些工具、别走哪条路)、' +
|
|
11
11
|
'pipeline(10 步产线每步的工具、免费还是收费、哪道审查闸)、review_gates(三道免费硬闸规则)、' +
|
|
12
12
|
'qa_tools(按客户描述的症状选检测工具与修法)、optional_boosts(可选增强及何时做)、billing(报价确认与免费族)、' +
|
|
13
|
-
'common_requests(客户常见原话 → 该做什么)
|
|
13
|
+
'common_requests(客户常见原话 → 该做什么)、' +
|
|
14
|
+
'local_postproduction(★客户要把镜头下载到**自己电脑**上剪 / 配乐 / 烧字幕 / 优化转场 / 补旁白时的完整流程:' +
|
|
15
|
+
'阶段顺序、执行位置、逐镜逐句怎么核对声音、什么才算验收完成)。传 section 只取一段。' +
|
|
14
16
|
'★工具描述回答"这个工具做什么",本工具回答"什么情况下该用哪个"——客户交来的是成品分镜表却被 set_script→rewrite_script 改写成散文,就是没先看这张表。', {
|
|
15
17
|
section: z.enum(GUIDE_SECTIONS).optional().describe('只取某一段;不传返回全部'),
|
|
16
18
|
}, async ({ section }) => {
|
package/dist/tools/produce.js
CHANGED
|
@@ -239,7 +239,7 @@ export function registerProduceTools(server, client) {
|
|
|
239
239
|
ethnicity_note: z.string().optional().describe("ethnicity='custom' 时的自由文本(如 北欧/波斯);其余取值忽略"),
|
|
240
240
|
project_type: z.enum(['drama', 'ad', 'mv', 'brand_film']).optional()
|
|
241
241
|
.describe('项目类型(默认 drama)。ad=广告(改写走 ad_script_rewriter);mv=音乐(走歌词→故事→剧本子流程);brand_film=品牌微电影(默认16:9)'),
|
|
242
|
-
rewrite_mode: z.enum(['standard', 'director']).optional().describe('AI
|
|
242
|
+
rewrite_mode: z.enum(['standard', 'director']).optional().describe('AI改写深度(★默认 director):director=只做格式规范化与最小可拍性修正,不擅自补台词补动机;standard=按商业短剧剧作律优化,会主动加戏'),
|
|
243
243
|
rewrite_pipeline: z.enum(['auto', 'two_pass', 'single_forced']).optional().describe('改写流水线:auto(默认,按原稿形态智能路由——剧本形态走两步保真,小说/大纲走创作改写)/two_pass(强制两步保真,客户自带成熟剧本必选)/single_forced(强制单步创作)'),
|
|
244
244
|
fidelity_enforce: z.number().int().min(0).max(1).optional().describe('1=改写保真硬闸:丢台词/丢人物/丢动作节拍直接拒收重做(客户要求逐句保留时开)'),
|
|
245
245
|
director_style: z.string().optional().describe('导演风格包 key'),
|
|
@@ -609,7 +609,7 @@ export function registerProduceTools(server, client) {
|
|
|
609
609
|
director_style: z.string().optional(),
|
|
610
610
|
theme_statement: z.string().optional().describe('一句话主题'),
|
|
611
611
|
subtitle_preset: z.string().optional(),
|
|
612
|
-
scene_group_mode: z.boolean().optional().describe('长镜模式(
|
|
612
|
+
scene_group_mode: z.boolean().optional().describe('长镜模式(连续动作/电影级长镜·★所有类型建剧默认开):false=改回逐镜独立生成再拼接'),
|
|
613
613
|
// 广告专属
|
|
614
614
|
cta_text: z.string().optional(),
|
|
615
615
|
target_duration_s: z.number().optional(),
|
|
@@ -1029,8 +1029,14 @@ export function registerProduceTools(server, client) {
|
|
|
1029
1029
|
'写一份 plan.json;④ 用 get_handoff_toolchain 拿到 compile_timeline.py 展开时间轴、' +
|
|
1030
1030
|
'assemble.sh 装配出成片。工具链已经把「加了重叠转场之后字幕/对白/音效怎么跟着位移」算好了。\n' +
|
|
1031
1031
|
'\n【三个不看就会翻车的事实】\n' +
|
|
1032
|
-
'① audio_contract.mode
|
|
1033
|
-
'
|
|
1032
|
+
'① **人声在哪要逐镜读 `shots[].voice_track.location`,不能读整集的 audio_contract.mode**——' +
|
|
1033
|
+
'后者是整剧级声明,而全画外旁白镜的旁白是平台在完成侧混进裸片的,同一集里逐镜可以不同。' +
|
|
1034
|
+
'四种取值各有各的处置:`separate_file`=对白在 dialogue_audio,不铺这镜就没台词;' +
|
|
1035
|
+
'`baked_in_clip`=已在裸片音轨里,再叠一遍会双声;' +
|
|
1036
|
+
'`missing`=**平台侧确认缺失**(旁白补偿失败),字幕还在但声音哪都没有——回平台重生成该镜,' +
|
|
1037
|
+
'拉长转场掩盖不了;`unknown`=有台词却查不到来源,**必须试听裸片**再决定。' +
|
|
1038
|
+
'★有字幕从来不等于有声音:字幕是逐句的,音频是逐镜的。`conflicts_with_contract=true` 的镜' +
|
|
1039
|
+
'以实测为准,notes 里已按镜号点名。\n' +
|
|
1034
1040
|
'② 每镜必须按 trim_head_ms / duration_ms 裁剪再用;直接拼整条裸片会把平台已经 QC 掉的' +
|
|
1035
1041
|
'首尾形变帧一起拼进去。\n' +
|
|
1036
1042
|
'③ 字幕 cue、dialogue_audio.offset_ms、sfx[].offset_ms 的基准都是「该镜 trim 之后的第 0 毫秒」,' +
|
|
@@ -1042,6 +1048,15 @@ export function registerProduceTools(server, client) {
|
|
|
1042
1048
|
assembly_guide: {
|
|
1043
1049
|
step_1_download: '按 shots[].clip.url / dialogue_audio.url / sfx[].url / bgm[].url 下载素材。' +
|
|
1044
1050
|
'URL 到 expires_at 失效,过期重新调本工具。',
|
|
1051
|
+
step_1b_verify_voice: '★下载完先核对声音,再动剪辑。**逐镜**读 voice_track.location 决定这镜的人声该不该铺、' +
|
|
1052
|
+
'能不能叠;location="unknown" 的镜**必须实际试听裸片**,不能凭字幕存在推定有声音;' +
|
|
1053
|
+
'location="missing" 的镜先回平台重生成,别开始剪。' +
|
|
1054
|
+
'clip.probed_has_audio_stream=false 表示平台实测这条裸片连音轨流都没有——' +
|
|
1055
|
+
'注意反过来不成立:有音轨不代表有人声,全旁白镜的环境音本来就是要求厂商出的。\n' +
|
|
1056
|
+
'★再**逐行**读 shots[].spoken_lines[]:字幕是逐句的、音频是逐镜的,' +
|
|
1057
|
+
'「这镜有字幕」推不出「每句都有声音」。每行带 speaker / text / voice_status,' +
|
|
1058
|
+
'把它当逐句核对清单用。voice_status="caption_no_voice" 的行是字卡文本,' +
|
|
1059
|
+
'**本来就没有配音**(平台侧也是当独立字幕呈现的)——不是缺失,别去补一段不该存在的配音。',
|
|
1045
1060
|
step_2_decide_transitions: '自己分析画面决定每个接缝的转场。scene_boundary="start" 是换场(适合给转场),' +
|
|
1046
1061
|
'"continue" 是同场景(平台默认硬切——同场景逐镜叠化是"幻灯片拼凑感"的主因)。' +
|
|
1047
1062
|
'transition_hint 是平台建议,你可以覆盖。',
|
|
@@ -1054,6 +1069,11 @@ export function registerProduceTools(server, client) {
|
|
|
1054
1069
|
' python3 compile_timeline.py ./pack --transitions plan.json\n' +
|
|
1055
1070
|
' ./assemble.sh ./pack out.mp4 plan.json',
|
|
1056
1071
|
gotchas: [
|
|
1072
|
+
'voice_track.location="baked_in_clip" 的镜**不要**再铺 dialogue_audio,那一镜的人声已经在裸片音轨里,' +
|
|
1073
|
+
'叠上去是同一句话说两遍(全画外旁白镜最常见)。',
|
|
1074
|
+
'subtitle.cues 的文本已剥掉说话人前缀与画外标记(与平台烧字幕同一条清洗),直接烧即可,' +
|
|
1075
|
+
'别再自己解析「名:」——但 cues 的**切分**是按语音停顿来的,与 spoken_lines 的行不是一一对应,' +
|
|
1076
|
+
'逐句核对声音请用 spoken_lines,不要按 cue 条数推定句数。',
|
|
1057
1077
|
'clip.duration_source="authored" 的镜是 probe 失败退回声明时长的,请自行 ffprobe 校正,否则拼接有累积误差。',
|
|
1058
1078
|
'render_target.color_lut 非 null 时,裸片是**未调色**的:必须施加随包的 haldclut 查找表,' +
|
|
1059
1079
|
'否则你的成片与平台成片有色差。fetch_pack.py 会下载它、assemble.sh 会自动施加。',
|
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 → portraits & sheets → storyboards → 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). 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.62",
|
|
6
|
+
"description": "Turn a script into a finished, downloadable short-drama episode over REST.\n\nPipeline: script → AI rewrite → cast/scenes/props extraction → portraits & sheets → storyboards → 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). 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.62 tool surface (operationIds match MCP tool names 1:1)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
|
9
9
|
{
|
|
@@ -3358,7 +3358,7 @@
|
|
|
3358
3358
|
"get": {
|
|
3359
3359
|
"operationId": "export_handoff_pack",
|
|
3360
3360
|
"summary": "导出本集「素材交接包」清单:逐镜裸片 + 对白音轨 + 音效 + 配乐 + 字幕的可下载 URL,交给你在**自己那边**完成转场决策、拼接、混音、烧字幕——平台不参与终拼",
|
|
3361
|
-
"description": "导出本集「素材交接包」清单:逐镜裸片 + 对白音轨 + 音效 + 配乐 + 字幕的可下载 URL,交给你在**自己那边**完成转场决策、拼接、混音、烧字幕——平台不参与终拼。免费,零扣费。\n\n【推荐流程】① 调本工具拿 manifest;② 按 clips[].url 把裸片下载到本地;③ 你自己看片判断每个接缝该用什么转场(manifest 给了 scene_boundary 场景边界作判据),写一份 plan.json;④ 用 get_handoff_toolchain 拿到 compile_timeline.py 展开时间轴、assemble.sh 装配出成片。工具链已经把「加了重叠转场之后字幕/对白/音效怎么跟着位移」算好了。\n\n【三个不看就会翻车的事实】\n① audio_contract.mode
|
|
3361
|
+
"description": "导出本集「素材交接包」清单:逐镜裸片 + 对白音轨 + 音效 + 配乐 + 字幕的可下载 URL,交给你在**自己那边**完成转场决策、拼接、混音、烧字幕——平台不参与终拼。免费,零扣费。\n\n【推荐流程】① 调本工具拿 manifest;② 按 clips[].url 把裸片下载到本地;③ 你自己看片判断每个接缝该用什么转场(manifest 给了 scene_boundary 场景边界作判据),写一份 plan.json;④ 用 get_handoff_toolchain 拿到 compile_timeline.py 展开时间轴、assemble.sh 装配出成片。工具链已经把「加了重叠转场之后字幕/对白/音效怎么跟着位移」算好了。\n\n【三个不看就会翻车的事实】\n① **人声在哪要逐镜读 `shots[].voice_track.location`,不能读整集的 audio_contract.mode**——后者是整剧级声明,而全画外旁白镜的旁白是平台在完成侧混进裸片的,同一集里逐镜可以不同。四种取值各有各的处置:`separate_file`=对白在 dialogue_audio,不铺这镜就没台词;`baked_in_clip`=已在裸片音轨里,再叠一遍会双声;`missing`=**平台侧确认缺失**(旁白补偿失败),字幕还在但声音哪都没有——回平台重生成该镜,拉长转场掩盖不了;`unknown`=有台词却查不到来源,**必须试听裸片**再决定。★有字幕从来不等于有声音:字幕是逐句的,音频是逐镜的。`conflicts_with_contract=true` 的镜以实测为准,notes 里已按镜号点名。\n② 每镜必须按 trim_head_ms / duration_ms 裁剪再用;直接拼整条裸片会把平台已经 QC 掉的首尾形变帧一起拼进去。\n③ 字幕 cue、dialogue_audio.offset_ms、sfx[].offset_ms 的基准都是「该镜 trim 之后的第 0 毫秒」,不是成片绝对时间。你加多少重叠转场都不用改它们——交给 compile_timeline.py 展开,别手算累加。\n\n想让平台代拼、要平台级质量闸(终拼预检/音画等长/响度母带),改用 compose_episode。",
|
|
3362
3362
|
"tags": [
|
|
3363
3363
|
"episodes"
|
|
3364
3364
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starreel/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.62",
|
|
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.62",
|
|
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.62",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
},
|