@starreel/mcp 0.1.111 → 0.1.113

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 CHANGED
@@ -258,7 +258,13 @@ content that will be rejected.
258
258
  `native_voice_anchor` lists `unanchored_speakers` (not locked yet) and
259
259
  `stale_shots` (made before the lock — `regenerate_shot_video` them). Decide
260
260
  the voice reference early; picking it after the whole episode is rendered
261
- means redoing shots.
261
+ means redoing shots. The shot's line field may be empty — then the actual
262
+ audio decides: a calibrated speech probe must hear a voice in the chosen
263
+ window, and its transcript becomes the anchor text (`text_source:
264
+ "transcript"`); no voice or no usable transcript is refused. Call it with
265
+ `preview: true` first: you get `preview_url` and the anchor text without
266
+ anything being written, then call again without `preview` (same
267
+ `start_s` / `dur_s`) to lock it.
262
268
 
263
269
  **No sample? Design one.** `design_voice` turns a one-sentence description
264
270
  (age, gender, timbre, pace, mood — say what you want, not what you don't)
@@ -1073,7 +1079,12 @@ to close") tells the vendor to fit that entire sequence into each 3-second shot.
1073
1079
  `design_voice` → `get_voice_design` → `save_designed_voice` (no sample needed),
1074
1080
  `speak_with_voice`, `set_character_voice`, `list_voices`, `delete_voice`,
1075
1081
  `generate_bgm` (optional `prompt` steers the music; read `get_bgm_prompt_guide` first),
1076
- `get_bgm_prompt_guide`, `replace_shot_dialogue`
1082
+ `get_bgm_prompt_guide`, `replace_shot_dialogue`, `revoice_narration`
1083
+ - **Mix** (free; settings only — `compose_episode` again to hear them, `rerender_episode`
1084
+ reuses the old timeline): whole drama via `update_project_settings`
1085
+ (`bgm_volume_preset` / `bgm_volume_db` / `lufs_target`); one episode via
1086
+ `set_episode_audio`; one music section's level and fades via `list_bgm_cues` →
1087
+ `update_bgm_cue`. Don't download the cut to re-mix it locally.
1077
1088
  - **Finish**: `compose_episode`, `get_final_cut`, `get_export`,
1078
1089
  `generate_episode_poster`, `generate_cover`
1079
1090
  - **What did this drama cost?** `get_drama_bill` — per kind `charged` / `refunded`
@@ -255,6 +255,7 @@ const PROJECT_SETTINGS_FIELDS = {
255
255
  bgm_source: z.enum(['own', 'clip']).optional().describe("BGM来源:own=自有BGM流水线(默认,抑制裸片BGM);clip=保留视频原生BGM、终拼不叠加"),
256
256
  bgm_volume_preset: z.enum(['off', 'low', 'auto', 'high']).optional().describe('BGM音量档:off静音/low轻(-28dB)/auto自适应(默认,静段可闻·对白不压麦)/high强'),
257
257
  bgm_volume_db: z.number().optional().describe('自定义BGM音量(dB,负值),覆盖预设档、关自适应'),
258
+ lufs_target: z.number().min(-23).max(-10).optional().describe('成片整体响度目标(LUFS,默认-16;越接近0越响)。终拼母带按它处理,改完需 compose_episode 重新合成'),
258
259
  use_clip_audio: z.boolean().optional().describe('用视频原声(★默认开):true/不传=跳过TTS配音直接用视频自带声;false=改回TTS配音。所有类型默认视频原声,建剧时应主动告知客户可切换配音(★直接改成片音频)'),
259
260
  // 字幕(烧录/双语/仅译文/位置/边距/动效)
260
261
  show_subtitles: z.boolean().optional().describe('字幕烧录总开关:false=不烧字幕轨'),
@@ -815,7 +816,13 @@ export function registerProduceTools(server, client) {
815
816
  + '走 TTS 配音的片子不会有这个问题。'
816
817
  + '\n★**很慢**:每镜要完整解码音轨,实测 6~10 秒/镜(后端限并发 4),整集几十镜要等几分钟。'
817
818
  + '别在产线中途反复调,放在成片前查一次。'
818
- + '\n★shots_probe_failed 是**没测成**的镜数,不代表那些镜有问题。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/silent-shot-audio-audit`)));
819
+ + '\n★shots_probe_failed 是**没测成**的镜数,不代表那些镜有问题。'
820
+ + '\n★★probe_speech:true 再对**台词栏为空**的镜跑人声检测(已标定判据):厂商在无台词镜里自己念出一句话时,'
821
+ + '响度比测不出来,这个能——命中的镜列在 unexpected_speech,text 是念出的内容。更慢(每镜下载+转写),'
822
+ + '一次最多 20 镜,skipped_by_limit 是剩下的、再调一次接着扫。只报不改:由客户决定 mute_only 静掉还是重生成。', {
823
+ episode_id: z.number().int().positive(),
824
+ probe_speech: z.boolean().optional().describe('true=对无台词镜额外跑人声检测(慢,一次≤20镜)'),
825
+ }, async ({ episode_id, probe_speech }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/silent-shot-audio-audit${probe_speech ? '?probe_speech=1' : ''}`)));
819
826
  server.tool('get_asset_recovery', '列本集可恢复的**历史视频产物**(免费·只读):以前生成过、后来被覆盖掉的整集成片与逐镜视频。'
820
827
  + '\n用途:客户说「上一版那个成片好」「这一镜前天那条视频比现在这条好」时,从这里找回来。'
821
828
  + '\n★★只管视频,**不含图片帧**:首尾帧不在这里,列表里也永远不会出现。'
@@ -1394,6 +1401,25 @@ export function registerProduceTools(server, client) {
1394
1401
  ...(prompt === undefined ? {} : { prompt }),
1395
1402
  ...(prompt_mode ? { prompt_mode } : {}),
1396
1403
  })));
1404
+ server.tool('set_episode_audio', '设置**本集**配乐音量(覆盖整剧设定,免费)。整剧统一的用 update_project_settings。' +
1405
+ '★只改设置:成片要 compose_episode 重新合成才变(rerender_episode 用旧时间线,不带上)。' +
1406
+ '★想调某一段配乐的音量或淡入淡出,用 list_bgm_cues + update_bgm_cue。', {
1407
+ episode_id: z.number().int().positive(),
1408
+ bgm_volume_preset: z.enum(['off', 'low', 'auto', 'high', 'inherit']).optional()
1409
+ .describe('本集配乐音量档:off静音/low轻(-28dB)/auto自适应/high强(-16dB)/inherit跟随整剧'),
1410
+ bgm_volume_db: z.number().min(-60).max(0).nullable().optional()
1411
+ .describe('本集自定义配乐音量(dB,-60~0),覆盖档位并关自适应;null=清除、跟随整剧'),
1412
+ }, async ({ episode_id, ...rest }) => jsonResult(await client.producePut(`/episodes/${episode_id}/audio`, rest)));
1413
+ server.tool('list_bgm_cues', '列出本集的配乐段(AI 配乐按情绪分幕,每段覆盖一段镜号 sb_from~sb_to):id、覆盖范围、gain_db(null=跟随音量档)、fade_in_ms / fade_out_ms。' +
1414
+ 'episode_id 为 null 的是**整剧共用段**,改它会影响所有集。免费。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/bgm-cues`)));
1415
+ server.tool('update_bgm_cue', '调某一段配乐的音量与淡入淡出(免费)。只改这三项;换曲目或改覆盖范围用 generate_bgm 重新生成。' +
1416
+ '★例:配乐进得太突兀→加大 fade_in_ms;某段压对白→降 gain_db。改完 compose_episode 重新合成才生效。', {
1417
+ episode_id: z.number().int().positive(),
1418
+ cue_id: z.number().int().positive().describe('来自 list_bgm_cues'),
1419
+ gain_db: z.number().min(-60).max(0).nullable().optional().describe('这段配乐的音量(dB,-60~0),设了就覆盖音量档;null=恢复跟随本集/整剧音量档'),
1420
+ fade_in_ms: z.number().int().min(0).max(15000).optional().describe('淡入毫秒(整数,0~15000)'),
1421
+ fade_out_ms: z.number().int().min(0).max(15000).optional().describe('淡出毫秒(整数,0~15000)'),
1422
+ }, async ({ episode_id, cue_id, ...rest }) => jsonResult(await client.producePut(`/episodes/${episode_id}/bgm-cues/${cue_id}`, rest)));
1397
1423
  server.tool('get_bgm_prompt_guide', '取「AI 配乐提示词」的书写规范:两个档位怎么选、该写哪些维度(附可照抄的示例)、' +
1398
1424
  '哪些是写了也不会生效的硬限制(纯器乐/时长/不做音效/不复刻具体曲目)、常见写坏的方式。' +
1399
1425
  '免费,纯静态,与具体剧目无关——写 generate_bgm 的 prompt 之前先读它,别自己猜。' +
@@ -1801,11 +1827,15 @@ export function registerProduceTools(server, client) {
1801
1827
  '\n★选哪一镜:该角色**独自说话、台词较长、没有背景音乐和别人插话**的镜;start_s/dur_s 可只截其中一段(不传则取默认窗口,时长会按各引擎上限自动钳制)。' +
1802
1828
  '\n★只对**之后**生成的视频生效。锁之前已经出好的镜会出现在 get_pipeline_status 的 native_voice_anchor.stale_shots 里,' +
1803
1829
  '用 regenerate_shot_video 重出才会统一。所以最省的做法是:每个说话角色先出一镜、选定声线,再批量出其余镜。' +
1830
+ '\n★台词栏为空也能用:以实际音频为准——平台用已标定的人声探测确认所选区间里有人声,并把转写文字当锚文本;' +
1831
+ '探测不到人声、或转写不出可用文字就拒(锚选错会污染此后所有镜的嗓音,宁拒不猜)。响应里 text_source 标明文本来自台词还是转写。' +
1832
+ '\n★先 preview:true 试听:只截取并返回 preview_url 与锚文本,**不写入角色**;听着对再去掉 preview、用同样的 start_s/dur_s 正式提交。' +
1804
1833
  '\n★有客户授权的外部音源时改用 clone_voice + set_character_voice;两者二选一,后设的覆盖先设的。', {
1805
1834
  character_id: z.number().int().positive(),
1806
- storyboard_id: z.number().int().positive().describe('本剧里有该角色台词、已出视频的镜'),
1835
+ storyboard_id: z.number().int().positive().describe('本剧里已出视频、该角色在里面说话的镜(台词栏为空时以实际音频为准)'),
1807
1836
  start_s: z.number().min(0).optional().describe('可选:从该镜第几秒开始截'),
1808
1837
  dur_s: z.number().positive().optional().describe('可选:截多长(秒)'),
1838
+ preview: z.boolean().optional().describe('true=只截取试听、返回 preview_url 与锚文本,不写入角色。建议先试听再正式提交'),
1809
1839
  }, async ({ character_id, ...rest }) => jsonResult(await client.producePost(`/characters/${character_id}/voice-anchor-from-shot`, rest)));
1810
1840
  // ── 素材交接包:客户自己拼片的通道 ──────────────────────────────────────
1811
1841
  // 与 compose_episode 的分工:compose_episode = 「平台替你拼」;本组工具 = 「素材给你,
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.111",
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.111 tool surface (operationIds match MCP tool names 1:1)."
5
+ "version": "0.1.113",
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.113 tool surface (operationIds match MCP tool names 1:1)."
7
7
  },
8
8
  "servers": [
9
9
  {
@@ -567,7 +567,7 @@
567
567
  "post": {
568
568
  "operationId": "set_voice_anchor_from_shot",
569
569
  "summary": "从本剧某一镜选定角色的声线(声音基准)",
570
- "description": "从本剧某一镜选定角色的声线(声音基准)。免费。不需要客户提供外部音源——就用片子里这个角色已经念出来的声音。\n★★【原声剧(use_clip_audio=true,默认)里这就是「锁声线」】选定后,之后生成的视频会把这段声音交给视频厂商当参考音频,同一角色前后镜的嗓音跟它走;不锁的话每镜由厂商各自采样,前后镜声线会漂。\n★选哪一镜:该角色**独自说话、台词较长、没有背景音乐和别人插话**的镜;start_s/dur_s 可只截其中一段(不传则取默认窗口,时长会按各引擎上限自动钳制)。\n★只对**之后**生成的视频生效。锁之前已经出好的镜会出现在 get_pipeline_status 的 native_voice_anchor.stale_shots 里,用 regenerate_shot_video 重出才会统一。所以最省的做法是:每个说话角色先出一镜、选定声线,再批量出其余镜。\n★有客户授权的外部音源时改用 clone_voice + set_character_voice;两者二选一,后设的覆盖先设的。",
570
+ "description": "从本剧某一镜选定角色的声线(声音基准)。免费。不需要客户提供外部音源——就用片子里这个角色已经念出来的声音。\n★★【原声剧(use_clip_audio=true,默认)里这就是「锁声线」】选定后,之后生成的视频会把这段声音交给视频厂商当参考音频,同一角色前后镜的嗓音跟它走;不锁的话每镜由厂商各自采样,前后镜声线会漂。\n★选哪一镜:该角色**独自说话、台词较长、没有背景音乐和别人插话**的镜;start_s/dur_s 可只截其中一段(不传则取默认窗口,时长会按各引擎上限自动钳制)。\n★只对**之后**生成的视频生效。锁之前已经出好的镜会出现在 get_pipeline_status 的 native_voice_anchor.stale_shots 里,用 regenerate_shot_video 重出才会统一。所以最省的做法是:每个说话角色先出一镜、选定声线,再批量出其余镜。\n★台词栏为空也能用:以实际音频为准——平台用已标定的人声探测确认所选区间里有人声,并把转写文字当锚文本;探测不到人声、或转写不出可用文字就拒(锚选错会污染此后所有镜的嗓音,宁拒不猜)。响应里 text_source 标明文本来自台词还是转写。\n★先 preview:true 试听:只截取并返回 preview_url 与锚文本,**不写入角色**;听着对再去掉 preview、用同样的 start_s/dur_s 正式提交。\n★有客户授权的外部音源时改用 clone_voice + set_character_voice;两者二选一,后设的覆盖先设的。",
571
571
  "tags": [
572
572
  "characters"
573
573
  ],
@@ -592,7 +592,7 @@
592
592
  "storyboard_id": {
593
593
  "type": "integer",
594
594
  "exclusiveMinimum": 0,
595
- "description": "本剧里有该角色台词、已出视频的镜"
595
+ "description": "本剧里已出视频、该角色在里面说话的镜(台词栏为空时以实际音频为准)"
596
596
  },
597
597
  "start_s": {
598
598
  "type": "number",
@@ -601,6 +601,9 @@
601
601
  "dur_s": {
602
602
  "type": "number",
603
603
  "exclusiveMinimum": 0
604
+ },
605
+ "preview": {
606
+ "type": "boolean"
604
607
  }
605
608
  },
606
609
  "required": [
@@ -816,6 +819,11 @@
816
819
  "bgm_volume_db": {
817
820
  "type": "number"
818
821
  },
822
+ "lufs_target": {
823
+ "type": "number",
824
+ "minimum": -23,
825
+ "maximum": -10
826
+ },
819
827
  "use_clip_audio": {
820
828
  "type": "boolean"
821
829
  },
@@ -1151,6 +1159,11 @@
1151
1159
  "bgm_volume_db": {
1152
1160
  "type": "number"
1153
1161
  },
1162
+ "lufs_target": {
1163
+ "type": "number",
1164
+ "minimum": -23,
1165
+ "maximum": -10
1166
+ },
1154
1167
  "use_clip_audio": {
1155
1168
  "type": "boolean"
1156
1169
  },
@@ -3259,6 +3272,80 @@
3259
3272
  }
3260
3273
  }
3261
3274
  },
3275
+ "/episodes/{episode_id}/audio": {
3276
+ "put": {
3277
+ "operationId": "set_episode_audio",
3278
+ "summary": "设置**本集**配乐音量(覆盖整剧设定,免费)",
3279
+ "description": "设置**本集**配乐音量(覆盖整剧设定,免费)。整剧统一的用 update_project_settings。★只改设置:成片要 compose_episode 重新合成才变(rerender_episode 用旧时间线,不带上)。★想调某一段配乐的音量或淡入淡出,用 list_bgm_cues + update_bgm_cue。",
3280
+ "tags": [
3281
+ "episodes"
3282
+ ],
3283
+ "parameters": [
3284
+ {
3285
+ "name": "episode_id",
3286
+ "in": "path",
3287
+ "required": true,
3288
+ "schema": {
3289
+ "type": "integer",
3290
+ "exclusiveMinimum": 0
3291
+ }
3292
+ }
3293
+ ],
3294
+ "requestBody": {
3295
+ "required": false,
3296
+ "content": {
3297
+ "application/json": {
3298
+ "schema": {
3299
+ "type": "object",
3300
+ "properties": {
3301
+ "bgm_volume_preset": {
3302
+ "type": "string",
3303
+ "enum": [
3304
+ "off",
3305
+ "low",
3306
+ "auto",
3307
+ "high",
3308
+ "inherit"
3309
+ ]
3310
+ },
3311
+ "bgm_volume_db": {
3312
+ "type": "number",
3313
+ "minimum": -60,
3314
+ "maximum": 0
3315
+ }
3316
+ }
3317
+ }
3318
+ }
3319
+ }
3320
+ },
3321
+ "responses": {
3322
+ "200": {
3323
+ "description": "StarReel envelope",
3324
+ "content": {
3325
+ "application/json": {
3326
+ "schema": {
3327
+ "type": "object",
3328
+ "properties": {
3329
+ "code": {
3330
+ "type": "integer"
3331
+ },
3332
+ "message": {
3333
+ "type": "string"
3334
+ },
3335
+ "data": {
3336
+ "description": "Operation result payload"
3337
+ }
3338
+ }
3339
+ }
3340
+ }
3341
+ }
3342
+ },
3343
+ "402": {
3344
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
3345
+ }
3346
+ }
3347
+ }
3348
+ },
3262
3349
  "/episodes/{episode_id}/audit-seams": {
3263
3350
  "post": {
3264
3351
  "operationId": "audit_seams",
@@ -3440,6 +3527,137 @@
3440
3527
  }
3441
3528
  }
3442
3529
  },
3530
+ "/episodes/{episode_id}/bgm-cues": {
3531
+ "get": {
3532
+ "operationId": "list_bgm_cues",
3533
+ "summary": "列出本集的配乐段(AI 配乐按情绪分幕,每段覆盖一段镜号 sb_from~sb_to):id、覆盖范围、gain_db(null=跟随音量档)、fade_in_ms / fade_out_ms",
3534
+ "description": "列出本集的配乐段(AI 配乐按情绪分幕,每段覆盖一段镜号 sb_from~sb_to):id、覆盖范围、gain_db(null=跟随音量档)、fade_in_ms / fade_out_ms。episode_id 为 null 的是**整剧共用段**,改它会影响所有集。免费。",
3535
+ "tags": [
3536
+ "episodes"
3537
+ ],
3538
+ "parameters": [
3539
+ {
3540
+ "name": "episode_id",
3541
+ "in": "path",
3542
+ "required": true,
3543
+ "schema": {
3544
+ "type": "integer",
3545
+ "exclusiveMinimum": 0
3546
+ }
3547
+ }
3548
+ ],
3549
+ "responses": {
3550
+ "200": {
3551
+ "description": "StarReel envelope",
3552
+ "content": {
3553
+ "application/json": {
3554
+ "schema": {
3555
+ "type": "object",
3556
+ "properties": {
3557
+ "code": {
3558
+ "type": "integer"
3559
+ },
3560
+ "message": {
3561
+ "type": "string"
3562
+ },
3563
+ "data": {
3564
+ "description": "Operation result payload"
3565
+ }
3566
+ }
3567
+ }
3568
+ }
3569
+ }
3570
+ },
3571
+ "402": {
3572
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
3573
+ }
3574
+ }
3575
+ }
3576
+ },
3577
+ "/episodes/{episode_id}/bgm-cues/{cue_id}": {
3578
+ "put": {
3579
+ "operationId": "update_bgm_cue",
3580
+ "summary": "调某一段配乐的音量与淡入淡出(免费)",
3581
+ "description": "调某一段配乐的音量与淡入淡出(免费)。只改这三项;换曲目或改覆盖范围用 generate_bgm 重新生成。★例:配乐进得太突兀→加大 fade_in_ms;某段压对白→降 gain_db。改完 compose_episode 重新合成才生效。",
3582
+ "tags": [
3583
+ "episodes"
3584
+ ],
3585
+ "parameters": [
3586
+ {
3587
+ "name": "episode_id",
3588
+ "in": "path",
3589
+ "required": true,
3590
+ "schema": {
3591
+ "type": "integer",
3592
+ "exclusiveMinimum": 0
3593
+ }
3594
+ },
3595
+ {
3596
+ "name": "cue_id",
3597
+ "in": "path",
3598
+ "required": true,
3599
+ "schema": {
3600
+ "type": "integer",
3601
+ "exclusiveMinimum": 0,
3602
+ "description": "来自 list_bgm_cues"
3603
+ }
3604
+ }
3605
+ ],
3606
+ "requestBody": {
3607
+ "required": false,
3608
+ "content": {
3609
+ "application/json": {
3610
+ "schema": {
3611
+ "type": "object",
3612
+ "properties": {
3613
+ "gain_db": {
3614
+ "type": "number",
3615
+ "minimum": -60,
3616
+ "maximum": 0
3617
+ },
3618
+ "fade_in_ms": {
3619
+ "type": "integer",
3620
+ "minimum": 0,
3621
+ "maximum": 15000
3622
+ },
3623
+ "fade_out_ms": {
3624
+ "type": "integer",
3625
+ "minimum": 0,
3626
+ "maximum": 15000
3627
+ }
3628
+ }
3629
+ }
3630
+ }
3631
+ }
3632
+ },
3633
+ "responses": {
3634
+ "200": {
3635
+ "description": "StarReel envelope",
3636
+ "content": {
3637
+ "application/json": {
3638
+ "schema": {
3639
+ "type": "object",
3640
+ "properties": {
3641
+ "code": {
3642
+ "type": "integer"
3643
+ },
3644
+ "message": {
3645
+ "type": "string"
3646
+ },
3647
+ "data": {
3648
+ "description": "Operation result payload"
3649
+ }
3650
+ }
3651
+ }
3652
+ }
3653
+ }
3654
+ },
3655
+ "402": {
3656
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
3657
+ }
3658
+ }
3659
+ }
3660
+ },
3443
3661
  "/episodes/{episode_id}/bgm-status": {
3444
3662
  "get": {
3445
3663
  "operationId": "get_bgm_status",
@@ -6623,7 +6841,7 @@
6623
6841
  "get": {
6624
6842
  "operationId": "audit_silent_shot_audio",
6625
6843
  "summary": "查**无台词镜里的异常发声**:本该沉默的反应镜,音轨却比同场说话镜还响——成片里的表现是「有人在画外乱说话」",
6626
- "description": "查**无台词镜里的异常发声**:本该沉默的反应镜,音轨却比同场说话镜还响——成片里的表现是「有人在画外乱说话」。免费。\n★用在**原声剧**上(use_clip_audio=true,即直接用 AI 视频自带声音那种)。走 TTS 配音的片子不会有这个问题。\n★**很慢**:每镜要完整解码音轨,实测 6~10 秒/镜(后端限并发 4),整集几十镜要等几分钟。别在产线中途反复调,放在成片前查一次。\n★shots_probe_failed 是**没测成**的镜数,不代表那些镜有问题。",
6844
+ "description": "查**无台词镜里的异常发声**:本该沉默的反应镜,音轨却比同场说话镜还响——成片里的表现是「有人在画外乱说话」。免费。\n★用在**原声剧**上(use_clip_audio=true,即直接用 AI 视频自带声音那种)。走 TTS 配音的片子不会有这个问题。\n★**很慢**:每镜要完整解码音轨,实测 6~10 秒/镜(后端限并发 4),整集几十镜要等几分钟。别在产线中途反复调,放在成片前查一次。\n★shots_probe_failed 是**没测成**的镜数,不代表那些镜有问题。\n★★probe_speech:true 再对**台词栏为空**的镜跑人声检测(已标定判据):厂商在无台词镜里自己念出一句话时,响度比测不出来,这个能——命中的镜列在 unexpected_speech,text 是念出的内容。更慢(每镜下载+转写),一次最多 20 镜,skipped_by_limit 是剩下的、再调一次接着扫。只报不改:由客户决定 mute_only 静掉还是重生成。",
6627
6845
  "tags": [
6628
6846
  "episodes"
6629
6847
  ],
@@ -6636,6 +6854,14 @@
6636
6854
  "type": "integer",
6637
6855
  "exclusiveMinimum": 0
6638
6856
  }
6857
+ },
6858
+ {
6859
+ "name": "probe_speech",
6860
+ "in": "query",
6861
+ "required": false,
6862
+ "schema": {
6863
+ "type": "string"
6864
+ }
6639
6865
  }
6640
6866
  ],
6641
6867
  "responses": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@starreel/mcp",
3
- "version": "0.1.111",
3
+ "version": "0.1.113",
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.111",
5
+ "version": "0.1.113",
6
6
  "websiteUrl": "https://starreel.ai",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "@starreel/mcp",
11
- "version": "0.1.111",
11
+ "version": "0.1.113",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  },