cerevox 3.0.0-alpha.2 → 3.0.0-alpha.20

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.
@@ -45,7 +45,7 @@
45
45
  * 台词:使用人物名称或角色标识,如"小明:妈妈,这个玩具真好玩!" 或 "顾客:这个效果太棒了!"
46
46
  * **画面 ("start_frame"字段):** 为每个分镜构思详细的首帧画面。画风必须贴合用户诉求、商品定位和故事氛围。描述需包含构图、光影、色彩、角色神态、商品展示等关键视觉要素,达到可直接用于图片生成的标准。注意画面描述必须与文案紧密贴合,共同服务于情绪传递和商品展示。
47
47
  * **动画 ("video_prompt"字段):** 为每个分镜构思详细的动画描述。动画必须与画面作为首帧,描述紧密贴合,共同服务于情绪传递和商品展示。动画必须具备专业的镜头感和视觉效果,如镜头语言、运动、情感、动作等,也要考虑商品的展示效果。
48
- 9. 分镜整合输出: `get-schema` 获取分镜规范 → 整合以上内容,创建初始 storyboard.json
48
+ 9. 分镜整合输出: `get-schema(type: storyboard)` 获取分镜规范 → 整合以上内容,创建初始 storyboard.json
49
49
  10. **素材生成(根据选择的模式):**
50
50
  **模式一:批量图片生成**
51
51
  * 分组场景图片 `generate-image-serials` (一次性生成所有分镜图片)
@@ -58,7 +58,7 @@
58
58
  * 配音 `generate-scene-tts` (⚠️ 务必严格采用storyboard中场景的script或dialog作为配音输入文本)
59
59
  * 视频 `generate-video`
60
60
  * 背景音乐 `generate-music`
61
- 11. 技术规范 → 调用 `get-schema` 获取draft_content规范 → 根据规范创建 draft_content.json
61
+ 11. 技术规范 → 调用 `get-schema(type: draft_content)` 获取draft_content规范 → 根据规范创建 draft_content.json
62
62
  12. 执行渲染 → `compile-and-run` 输出成品并自动下载到本地
63
63
  13. 关闭项目 → `project-close`
64
64
 
@@ -36,7 +36,7 @@
36
36
 
37
37
  **Action**
38
38
  1) 与用户确认思路是否正确且符合需求
39
- 2) 调用`get-schema`获取分镜规范
39
+ 2) 调用`get-schema(type: storyboard)`获取分镜规范
40
40
  3) 根据确认结果创建项目目录下的 storyboard.json 文件
41
41
  4) Review 生成的 storyboard.json 文件,对其进行初步优化
42
42
  你可以做的优化动作:
@@ -167,7 +167,7 @@
167
167
 
168
168
  **Action**
169
169
  1) 将检查结果与用户确认,必要时更新 storyboard.json
170
- 2) 调用 `get-schema` 获取 draft_content 规范
170
+ 2) 调用 `get-schema(type: draft_content)` 获取 draft_content 规范
171
171
  3) 根据确认的结果创建 draft_content.json 文件(务必要先获取 schema)
172
172
  4) 将当前的执行结果记录在 action_logs.json 中
173
173
  5) 调用 `compile-and-run` 最终合成视频并下载
@@ -87,7 +87,7 @@
87
87
 
88
88
  ### 分镜构思
89
89
 
90
- - 如果用户和你讨论视频剧情,或者已经有明确的场景想法,你使用 `'get-schema` 工具来获知如何创建故事板,然后用故事板来帮助用户构思视频分镜
90
+ - 如果用户和你讨论视频剧情,或者已经有明确的场景想法,你使用 `'get-schema(type: storyboard)` 工具来获知如何创建故事板,然后用故事板来帮助用户构思视频分镜
91
91
  - 在所有和剧情、设定有关的问题时,你都要先理解用户想法然后更新故事板,并与用户确认
92
92
  - 尤其是在生成素材前,能更新故事板就及时更新,以免后续遗忘信息,造成不一致
93
93
 
@@ -118,7 +118,7 @@
118
118
  #### 后期制作和视频处理工具
119
119
  - `generate-music`:你可以用这个工具生成适合视频内容风格的BGM
120
120
  - `audio-video-sync`:音画(唇形)同步工具,你可以使用这个工具合并音频视频,或者为人物对口型
121
- - `get-schema`:你执行这个工具获取视频剪辑合成的JSON格式规范,用该规范创建 draft_content.json 文件,然后通过这个文件进行视频合成
121
+ - `get-schema(type: draft_content)`:你执行这个工具获取视频剪辑合成的JSON格式规范,用该规范创建 draft_content.json 文件,然后通过这个文件进行视频合成
122
122
  - `compile-and-run`:你执行这个工具编译并运行 draft_content.json 文件,生成视频
123
123
  - `run-ffmpeg`:你可以使用这个工具执行任意ffmpeg命令,这在需要对视频进行更复杂处理时非常有用
124
124
 
@@ -8,14 +8,14 @@
8
8
 
9
9
  1. 确保项目已正确开启:`project-open` 已被调用
10
10
  2. 根据剧情设计选择语音 → 使用 `search-voices` 选择合适的配音音色,若用户指定了voice_id,则直接使用该音色ID,无需验证
11
- 3. 剧本规范 → 调用`get-schema`获取分镜规范 → 编写 storyboard.json(受众、脚本、风格、角色、场景)
11
+ 3. 剧本规范 → 调用`get-schema(type: storyboard)`获取分镜规范 → 编写 storyboard.json(受众、脚本、风格、角色、场景)
12
12
  4. 剧本润色 → 检查并修改剧本的角色,确保每个场景角色的外貌、妆造、衣着特征在 start_frame 中描述完整以保证一致性
13
13
  5. 素材生成(严格按顺序)
14
14
  1) 配音 `generate-scene-tts`
15
15
  2) 图片 `generate-image` + 视频 `generate-video`
16
16
  或 `generate-video-by-ref` 参考图生视频
17
17
  3) 背景音乐 `generate-music`
18
- 6. 技术规范 → 调用`get-schema`获取draft_content规范 → 根据规范创建 draft_content.json
18
+ 6. 技术规范 → 调用`get-schema(type: draft_content)`获取draft_content规范 → 根据规范创建 draft_content.json
19
19
  7. 执行渲染 → `compile-and-run` 输出成品并自动下载到本地
20
20
  8. 关闭项目 → `project-close`
21
21
 
@@ -19,7 +19,7 @@
19
19
  * **文案 ("script"字段):** 为每个分镜创作具备情感穿透力的文案。文案必须与画面描述紧密贴合,共同服务于情绪的传递。**禁止在文案中使用任何英文引号 ("")**。
20
20
  * **画面 ("start_frame"字段):** 为每个分镜构思详细的首帧画面。画风必须贴合用户诉求和故事氛围。描述需包含构图、光影、色彩、角色神态等关键视觉要素,达到可直接用于图片生成的标准。注意画面避免在运动、情感等处**锁死**,必须留有视频发挥的余地,比如人物哭泣,不要在一开始就让角色号啕大哭,动作、姿势、表情等也不要一开始就达到高潮,记住这只是首帧图片,需要为后续动画留有余地。
21
21
  * **动画 ("video_prompt"字段):** 为每个分镜构思详细的动画描述。动画必须与以画面作为首帧,描述紧密贴合,共同服务于情绪的传递。动画必须具备专业的镜头感和视觉效果,如镜头语言、运动、情感、动作等,也要考虑到光影和特效,且必须考虑到用户诉求和故事氛围。
22
- 8. 分镜整合输出: `get-schema` 获取分镜规范 → 整合以上内容,创建初始 storyboard.json
22
+ 8. 分镜整合输出: `get-schema(type: storyboard)` 获取分镜规范 → 整合以上内容,创建初始 storyboard.json
23
23
  9. **素材生成(根据选择的模式):**
24
24
  **模式一:批量图片生成**
25
25
  * 分组场景图片 `generate-image-serials` (一次性生成所有分镜图片)
@@ -32,7 +32,7 @@
32
32
  * 配音 `generate-scene-tts` (⚠️ 务必严格采用storyboard中场景的script或dialog作为配音输入文本)
33
33
  * 视频 `generate-video`
34
34
  * 背景音乐 `generate-music`
35
- 10. 技术规范 → 调用`get-schema`获取 draft_content 规范 → 根据规范创建 draft_content.json
35
+ 10. 技术规范 → 调用`get-schema(type: draft_content)`获取 draft_content 规范 → 根据规范创建 draft_content.json
36
36
  11. 执行渲染 → `compile-and-run` 输出成品并自动下载到本地
37
37
  12. 关闭项目 → `project-close`
38
38
 
@@ -13,14 +13,14 @@ description: 制作通用视频时,可以根据用户需求,按照这个流
13
13
 
14
14
  1. 确保项目已正确开启:`project-open` 已被调用
15
15
  2. 根据剧情设计选择语音 → 使用 `search-voices` 选择合适的配音音色,若用户指定了voice_id,则直接使用该音色ID,无需验证
16
- 3. 剧本规范 → 调用`get-schema`获取分镜规范 → 编写 storyboard.json(受众、脚本、风格、角色、场景)
16
+ 3. 剧本规范 → 调用`get-schema(type: storyboard)`获取分镜规范 → 编写 storyboard.json(受众、脚本、风格、角色、场景)
17
17
  4. 剧本润色 → 检查并修改剧本的角色,确保每个场景角色的外貌、妆造、衣着特征在 start_frame 中描述完整以保证一致性
18
18
  5. 素材生成(严格按顺序)
19
19
  1) 配音 `generate-scene-tts`
20
20
  2) 图片 `generate-image` + 视频 `generate-video`
21
21
  或 `generate-video-by-ref` 参考图生视频
22
22
  3) 背景音乐 `generate-music`
23
- 6. 技术规范 → 调用`get-schema`获取 draft_content 规范 → 根据规范创建 draft_content.json
23
+ 6. 技术规范 → 调用`get-schema(type: draft_content)`获取 draft_content 规范 → 根据规范创建 draft_content.json
24
24
  7. 执行渲染 → `compile-and-run` 输出成品并自动下载到本地
25
25
  8. 关闭项目 → `project-close`
26
26
 
@@ -14,11 +14,11 @@ description: 创作专业音乐MV,基于 Zerocut 自主完成音乐MV成片的
14
14
  3. 音乐创作 → 根据主题构思音乐氛围 → 创作歌词 lyrics.txt
15
15
  4. 音乐生成 → 根据 lyrics.txt 调用 `generate-music` → 获得歌曲和 captions
16
16
  5. 分析歌曲 → 创建 timeline_analysis.json 得到 captions 的时间线
17
- 6. 设计分镜场景 → `get-schema` 获取分镜规范 → 创建初始 storyboard.json
17
+ 6. 设计分镜场景 → `get-schema(type: storyboard)` 获取分镜规范 → 创建初始 storyboard.json
18
18
  7. 主要角色形象塑造 → `generate-character-image` → 生成主要角色形象参考图(三视图)
19
19
  8. 分镜首帧生成 → `generate-image` → 生成各场景分镜首帧
20
20
  9. 首尾帧视频生成 → `generate-video` → **可选择使用连续镜头方式**:根据创意需要,可以选择以下一场景的 start_frame 作为上一场景的 end_frame 来实现场景间连续性,或采用独立场景切换方式,每段视频的实际时长应匹配 timeline_analysis 中 proposed_video_scenes 对应场景的 video_duration_s
21
- 10. 技术规范 → 调用`get-schema`获取 draft_content 规范 → 根据规范创建 draft_content.json
21
+ 10. 技术规范 → 调用`get-schema(type: draft_content)`获取 draft_content 规范 → 根据规范创建 draft_content.json
22
22
  11. 执行渲染 → `compile-and-run` 输出成品并自动下载到本地
23
23
  12. 关闭项目 → `project-close`
24
24
 
@@ -1 +1 @@
1
- {"version":3,"file":"zerocut.d.ts","sourceRoot":"","sources":["../../../src/mcp/servers/zerocut.ts"],"names":[],"mappings":";AA+5KA,wBAAsB,GAAG,kBAKxB"}
1
+ {"version":3,"file":"zerocut.d.ts","sourceRoot":"","sources":["../../../src/mcp/servers/zerocut.ts"],"names":[],"mappings":";AA4/KA,wBAAsB,GAAG,kBAKxB"}
@@ -55,7 +55,7 @@ const node_fs_1 = require("node:fs");
55
55
  const coze_1 = require("../../utils/coze");
56
56
  const mp3_duration_1 = __importDefault(require("mp3-duration"));
57
57
  const image_size_1 = __importDefault(require("image-size"));
58
- function createErrorResponse(error, operation) {
58
+ function createErrorResponse(error, operation, details) {
59
59
  const errorMessage = error instanceof Error ? error.message : String(error);
60
60
  console.error(`[${operation}] Error:`, error);
61
61
  return {
@@ -67,6 +67,7 @@ function createErrorResponse(error, operation) {
67
67
  error: errorMessage,
68
68
  operation,
69
69
  timestamp: new Date().toISOString(),
70
+ details,
70
71
  }),
71
72
  },
72
73
  ],
@@ -359,12 +360,11 @@ server.registerTool('retrieve-rules-context', {
359
360
  purpose: zod_1.z
360
361
  .enum([
361
362
  'general-video',
362
- 'music-video',
363
- 'stage-play',
364
363
  'story-telling',
365
364
  'creative-ad',
366
365
  'expert',
367
366
  'material-creation',
367
+ 'anim',
368
368
  'freeform',
369
369
  'custom',
370
370
  ])
@@ -372,12 +372,11 @@ server.registerTool('retrieve-rules-context', {
372
372
  .describe(`The purpose of the rules context to retrieve.
373
373
 
374
374
  - general-video 创建通用视频
375
- - music-video 创建音乐视频
376
- - stage-play 创建舞台播放视频
377
375
  - story-telling 创建故事讲述视频
378
376
  - creative-ad 创建创意广告视频
379
377
  - expert 以专家模式创建视频,必须用户主动要求才触发
380
378
  - material-creation 素材创作模式,必须用户主动要求才触发
379
+ - anim 漫剧创作模式,必须用户主动要求才触发
381
380
  - freeform 自由创作模式,必须用户主动要求才触发
382
381
  - custom 自定义模式`),
383
382
  },
@@ -400,12 +399,11 @@ server.registerTool('retrieve-rules-context', {
400
399
  // 当 projectRulesFile 不存在时,设置 checkStoryboardSubtitlesFlag 为 false
401
400
  checkStoryboardSubtitlesFlag = false;
402
401
  if (purpose !== 'general-video' &&
403
- purpose !== 'music-video' &&
404
- purpose !== 'stage-play' &&
405
402
  purpose !== 'story-telling' &&
406
403
  purpose !== 'creative-ad' &&
407
404
  purpose !== 'expert' &&
408
405
  purpose !== 'material-creation' &&
406
+ purpose !== 'anim' &&
409
407
  purpose !== 'freeform') {
410
408
  return createErrorResponse(`Project rules file not found: ${projectRulesFile}`, 'retrieve-rules-context');
411
409
  }
@@ -739,7 +737,10 @@ server.registerTool('generate-character-image', {
739
737
  title: 'Generate Character Image',
740
738
  description: 'Generate a turnaround image or portrait for any character.',
741
739
  inputSchema: {
742
- type: zod_1.z.enum(['banana', 'seedream']).optional().default('banana'),
740
+ type: zod_1.z
741
+ .enum(['banana', 'banana-pro', 'seedream'])
742
+ .optional()
743
+ .default('banana'),
743
744
  name: zod_1.z.string().describe('The name of the character.'),
744
745
  gender: zod_1.z
745
746
  .enum(['male', 'female'])
@@ -1069,7 +1070,10 @@ server.registerTool('generate-image', {
1069
1070
  title: 'Generate Image',
1070
1071
  description: `生成图片`,
1071
1072
  inputSchema: {
1072
- type: zod_1.z.enum(['banana', 'seedream']).optional().default('seedream'),
1073
+ type: zod_1.z
1074
+ .enum(['banana', 'banana-pro', 'seedream'])
1075
+ .optional()
1076
+ .default('seedream'),
1073
1077
  prompt: zod_1.z
1074
1078
  .string()
1075
1079
  .describe('The prompt to generate. 一般要严格对应 storyboard 中当前场景的 start_frame 或 end_frame 中的字段描述'),
@@ -1434,6 +1438,11 @@ server.registerTool('edit-image', {
1434
1438
  description: 'Edit the image.',
1435
1439
  inputSchema: {
1436
1440
  prompt: zod_1.z.string().describe('要编辑图片的中文提示词'),
1441
+ type: zod_1.z
1442
+ .enum(['banana-pro', 'banana', 'seedream'])
1443
+ .optional()
1444
+ .default('seedream')
1445
+ .describe('The type of image model to use.'),
1437
1446
  sourceImageFileName: zod_1.z.string().describe('The source image file name.'),
1438
1447
  saveToFileName: zod_1.z.string().describe('The filename to save.'),
1439
1448
  size: zod_1.z
@@ -1477,7 +1486,7 @@ server.registerTool('edit-image', {
1477
1486
  .default(false)
1478
1487
  .describe('Whether to add watermark to the image.'),
1479
1488
  },
1480
- }, async ({ prompt, sourceImageFileName, saveToFileName, size, watermark }) => {
1489
+ }, async ({ prompt, type, sourceImageFileName, saveToFileName, size, watermark, }) => {
1481
1490
  try {
1482
1491
  // 验证session状态
1483
1492
  const currentSession = await validateSession('edit-image');
@@ -1503,8 +1512,9 @@ server.registerTool('edit-image', {
1503
1512
  const base64String = `data:${mimeType};base64,${imageBuffer.toString('base64')}`;
1504
1513
  imageBase64Array.push(base64String);
1505
1514
  const ai = currentSession.ai;
1506
- const processedPrompt = `转绘参考图片,${prompt}`;
1515
+ const processedPrompt = `转绘我提供的参考图片,${prompt}`;
1507
1516
  const res = await ai.generateImage({
1517
+ type,
1508
1518
  prompt: processedPrompt,
1509
1519
  size,
1510
1520
  watermark,
@@ -2761,7 +2771,9 @@ server.registerTool('get-schema', {
2761
2771
  title: 'Get Storyboard Schema or Draft Content Schema',
2762
2772
  description: 'Get the complete Storyboard or Draft Content JSON Schema definition. Use this schema to validate storyboard.json or draft_content.json files.',
2763
2773
  inputSchema: {
2764
- type: zod_1.z.enum(['storyboard', 'draft_content']),
2774
+ type: zod_1.z
2775
+ .enum(['storyboard', 'draft_content'])
2776
+ .describe('The type of schema to retrieve. Must be either "storyboard" or "draft_content". 用 type: storyboard 的 schema 生成 storyboard.json;用 type: draft_content 的 schema 生成 draft_content.json'),
2765
2777
  },
2766
2778
  }, async ({ type }) => {
2767
2779
  try {
@@ -2795,34 +2807,6 @@ server.registerTool('get-schema', {
2795
2807
  return createErrorResponse(error, 'get-schema');
2796
2808
  }
2797
2809
  });
2798
- server.registerTool('do-storyboard-optimization', {
2799
- title: 'Do Storyboard Optimization',
2800
- description: 'Get storyboard optimization guidelines and action instructions.',
2801
- inputSchema: {},
2802
- }, async () => {
2803
- try {
2804
- // 调用 do-storyboard-optimization 工具时,设置 checkStoryboardFlag 为 true
2805
- checkStoryboardFlag = true;
2806
- const guidelinePath = (0, node_path_1.resolve)(__dirname, './prompts/actions/storyboard_optimization.md');
2807
- const storyboardOptimizationGuidelines = await (0, promises_1.readFile)(guidelinePath, 'utf-8');
2808
- return {
2809
- content: [
2810
- {
2811
- type: 'text',
2812
- text: JSON.stringify({
2813
- content: {
2814
- guideline: storyboardOptimizationGuidelines,
2815
- action: '你应当根据guideline优化storyboard.json',
2816
- },
2817
- }),
2818
- },
2819
- ],
2820
- };
2821
- }
2822
- catch (error) {
2823
- return createErrorResponse(error, 'do-storyboard-optimization');
2824
- }
2825
- });
2826
2810
  server.registerTool('search-voices', {
2827
2811
  title: 'Search Voices',
2828
2812
  description: 'Search voices from doubao_voices_full based on scenes, emotions, languages, and gender.',
@@ -3551,6 +3535,11 @@ server.registerTool('generate-video-by-ref', {
3551
3535
  prompt: zod_1.z
3552
3536
  .string()
3553
3537
  .describe('The prompt to generate video with or without reference images.'),
3538
+ rewritePrompt: zod_1.z
3539
+ .boolean()
3540
+ .optional()
3541
+ .default(true)
3542
+ .describe('Whether to rewrite the prompt.'),
3554
3543
  referenceImages: zod_1.z
3555
3544
  .array(zod_1.z.object({
3556
3545
  name: zod_1.z
@@ -3571,7 +3560,12 @@ server.registerTool('generate-video-by-ref', {
3571
3560
  .optional()
3572
3561
  .default(5)
3573
3562
  .describe('The duration of the video in seconds.'),
3574
- size: zod_1.z.enum(['720x1280', '1280x720']).describe('The size of the video.'),
3563
+ aspectRatio: zod_1.z
3564
+ .enum(['16:9', '9:16'])
3565
+ .describe('The aspect ratio of the video.'),
3566
+ resolution: zod_1.z
3567
+ .enum(['720p', '1080p'])
3568
+ .describe('The resolution of the video.'),
3575
3569
  watermark: zod_1.z
3576
3570
  .boolean()
3577
3571
  .optional()
@@ -3614,7 +3608,7 @@ server.registerTool('generate-video-by-ref', {
3614
3608
  .default(false)
3615
3609
  .describe('Whether to optimize the prompt.'),
3616
3610
  },
3617
- }, async ({ prompt, referenceImages, duration, size, watermark, type, mute, saveToFileName, sceneIndex, storyBoardFile, skipConsistencyCheck, optimizePrompt, }, context) => {
3611
+ }, async ({ prompt, rewritePrompt, referenceImages, duration, aspectRatio, resolution, watermark, type, mute, saveToFileName, sceneIndex, storyBoardFile, skipConsistencyCheck, optimizePrompt, }, context) => {
3618
3612
  try {
3619
3613
  // 验证session状态
3620
3614
  const currentSession = await validateSession('generate-video-by-ref');
@@ -3656,6 +3650,9 @@ server.registerTool('generate-video-by-ref', {
3656
3650
  if (scene.is_continuous === true) {
3657
3651
  return createErrorResponse('连续镜头应使用首尾帧,请修改连续镜头设置,或将本场景改为首尾帧方式实现', 'generate-video-by-ref');
3658
3652
  }
3653
+ if (scene.video_type !== 'references') {
3654
+ return createErrorResponse(`场景 ${sceneIndex} 中的 video_type (${scene.video_type}) 未设置为 'references',不应当使用参考生视频,请使用图生视频 generate-video 方式生成`, 'generate-video-by-ref');
3655
+ }
3659
3656
  // 检查 use_video_model 与 type 参数的一致性
3660
3657
  if (scene.use_video_model &&
3661
3658
  type &&
@@ -3704,15 +3701,15 @@ server.registerTool('generate-video-by-ref', {
3704
3701
  }
3705
3702
  // 检查 storyBoard.orientation 与 size 参数的一致性
3706
3703
  if (storyBoard.orientation) {
3707
- const isLandscapeSize = size === '1280x720';
3708
- const isPortraitSize = size === '720x1280';
3704
+ const isLandscapeSize = aspectRatio === '16:9';
3705
+ const isPortraitSize = aspectRatio === '9:16';
3709
3706
  if (storyBoard.orientation === 'landscape' &&
3710
3707
  !isLandscapeSize) {
3711
- return createErrorResponse(`故事板设定为横屏模式(orientation: landscape),但视频尺寸 ${size} 为竖屏格式,请使用横屏尺寸 1280x720`, 'generate-video-by-ref');
3708
+ return createErrorResponse(`故事板设定为横屏模式(orientation: landscape),但视频为竖屏格式,请使用横屏尺寸 1280x720`, 'generate-video-by-ref');
3712
3709
  }
3713
3710
  if (storyBoard.orientation === 'portrait' &&
3714
3711
  !isPortraitSize) {
3715
- return createErrorResponse(`故事板设定为竖屏模式(orientation: portrait),但视频尺寸 ${size} 为横屏格式,请使用竖屏尺寸 720x1280`, 'generate-video-by-ref');
3712
+ return createErrorResponse(`故事板设定为竖屏模式(orientation: portrait),但视频为横屏格式,请使用竖屏尺寸 720x1280`, 'generate-video-by-ref');
3716
3713
  }
3717
3714
  }
3718
3715
  }
@@ -3781,17 +3778,21 @@ server.registerTool('generate-video-by-ref', {
3781
3778
  url: imageUrl,
3782
3779
  });
3783
3780
  console.log(`Added reference image URL: ${imageUrl} (name: ${imageRef.name}, type: ${imageRef.type})`);
3784
- promptPrefix += `参考“${imageRef.name}”(图${referenceImageUrls.length})${imageRef.type === 'subject' ? '主体形象' : '背景'}\n`;
3781
+ if (rewritePrompt) {
3782
+ promptPrefix += `参考“${imageRef.name}”(图${referenceImageUrls.length})${imageRef.type === 'subject' ? '主体形象' : '背景'}\n`;
3783
+ }
3785
3784
  }
3786
3785
  if (promptPrefix) {
3787
3786
  promptPrefix += '\n';
3788
3787
  }
3788
+ const finalPrompt = `${promptPrefix}${prompt}`;
3789
3789
  // 调用 referencesToVideo 函数
3790
3790
  const result = await currentSession.ai.referencesToVideo({
3791
- prompt: `${promptPrefix}${prompt}`,
3791
+ prompt: finalPrompt,
3792
3792
  reference_images: referenceImageUrls, // 使用URL数组而不是base64数组
3793
3793
  duration,
3794
- size,
3794
+ aspect_ratio: aspectRatio,
3795
+ resolution,
3795
3796
  watermark,
3796
3797
  type,
3797
3798
  mute,
@@ -3803,9 +3804,23 @@ server.registerTool('generate-video-by-ref', {
3803
3804
  if (result.error) {
3804
3805
  return createErrorResponse(result.error, 'generate-video-by-ref');
3805
3806
  }
3806
- if (!result.url) {
3807
+ if (!result.url && !result.taskUrl) {
3807
3808
  return createErrorResponse('Video generation failed: no video URL returned', 'generate-video-by-ref');
3808
3809
  }
3810
+ else if (result.taskUrl) {
3811
+ return {
3812
+ content: [
3813
+ {
3814
+ type: 'text',
3815
+ text: JSON.stringify({
3816
+ success: true,
3817
+ message: '该视频生成任务正在运行中,它是异步任务,且执行时间较长,你应立即调用工具 wait-for-task-finish 来等待任务结束,如该工具调用超时,你应立即再次重新调用直到任务结束。',
3818
+ taskUrl: result.taskUrl,
3819
+ }),
3820
+ },
3821
+ ],
3822
+ };
3823
+ }
3809
3824
  // 下载生成的视频
3810
3825
  await saveMaterial(currentSession, result.url, validatedFileName);
3811
3826
  // 更新媒体日志
@@ -3831,6 +3846,8 @@ server.registerTool('generate-video-by-ref', {
3831
3846
  ratio: result.ratio,
3832
3847
  url: result.url,
3833
3848
  last_frame_url: result.last_frame_url,
3849
+ referenceImageUrls,
3850
+ prompt: finalPrompt,
3834
3851
  }, null, 2),
3835
3852
  },
3836
3853
  ],
@@ -3854,6 +3871,10 @@ server.registerTool('extend-video-duration', {
3854
3871
  .max(7)
3855
3872
  .default(3)
3856
3873
  .describe('Duration to extend the video in seconds (1-7).'),
3874
+ resolution: zod_1.z
3875
+ .enum(['720p', '1080p'])
3876
+ .default('720p')
3877
+ .describe('The resolution of the video.'),
3857
3878
  prompt: zod_1.z
3858
3879
  .string()
3859
3880
  .optional()
@@ -3870,7 +3891,7 @@ server.registerTool('extend-video-duration', {
3870
3891
  .string()
3871
3892
  .describe('The filename to save the extended video.'),
3872
3893
  },
3873
- }, async ({ videoFileName, duration, prompt, type = 'turbo', endFrame, saveToFileName, }, context) => {
3894
+ }, async ({ videoFileName, duration, resolution, prompt, type = 'turbo', endFrame, saveToFileName, }, context) => {
3874
3895
  try {
3875
3896
  await validateSession('extend-video');
3876
3897
  validateFileName(videoFileName);
@@ -3899,6 +3920,7 @@ server.registerTool('extend-video-duration', {
3899
3920
  video_url: videoUri,
3900
3921
  prompt: finalPrompt,
3901
3922
  duration,
3923
+ resolution,
3902
3924
  end_frame: endFrameUri,
3903
3925
  onProgress: async (metaData) => {
3904
3926
  sendProgress(context, ++progress, undefined, `Extension progress: ${Math.round(progress * 100)}%`);
@@ -3952,49 +3974,71 @@ server.registerTool('extend-video-duration', {
3952
3974
  return createErrorResponse(error, 'extend-video');
3953
3975
  }
3954
3976
  });
3955
- server.registerTool('generate-video-by-template', {
3956
- title: 'Generate Video by Template',
3957
- description: 'Generate a video based on a template. The template must be a valid JSON string.',
3977
+ server.registerTool('use-template', {
3978
+ title: 'Use Template',
3979
+ description: 'Find a template that matches the user request, and use it to generate a new material.',
3958
3980
  inputSchema: {
3959
- purpose: zod_1.z
3960
- .string()
3961
- .describe('The prompt to generate the video. 自动根据意图匹配模板'),
3962
- text_prompts: zod_1.z
3963
- .array(zod_1.z.string().describe('Text prompt for the template to build video.'))
3964
- .optional()
3965
- .describe('Optional text prompts to use in the template.'),
3981
+ user_request: zod_1.z.string().describe('用户请求,根据意图自动匹配模板'),
3966
3982
  materials: zod_1.z
3967
3983
  .array(zod_1.z.string().describe('Material file name in materials directory.'))
3968
3984
  .optional()
3969
3985
  .describe('Optional materials to use in the template.'),
3970
3986
  saveToFileName: zod_1.z
3971
3987
  .string()
3972
- .describe('The filename to save the generated video.'),
3988
+ .describe('The filename to save the generated material.'),
3973
3989
  },
3974
- }, async ({ purpose, text_prompts, saveToFileName, materials }) => {
3990
+ }, async ({ user_request, saveToFileName, materials }) => {
3975
3991
  try {
3976
- const templates = {
3977
- '7569583728302817331': '宠物唱歌',
3978
- '7569605825011367976': '万圣节宠物弹吉他',
3979
- };
3992
+ const templates = [
3993
+ {
3994
+ id: '7576300661140209704',
3995
+ name: '视频编辑',
3996
+ descript: '根据用户的要求,替换视频内容中的主体或背景。',
3997
+ trigger: '将{A视频}中的{B主体}修改为{C主体}',
3998
+ },
3999
+ {
4000
+ id: '7569583728302817331',
4001
+ name: '宠物唱歌',
4002
+ description: '用一张宠物照片,生成一段宠物唱歌的视频。',
4003
+ trigger: '根据{A图片}生成一段{宠物A}唱歌的视频',
4004
+ },
4005
+ {
4006
+ id: '7569605825011367976',
4007
+ name: '万圣节宠物弹吉他',
4008
+ description: '用一张宠物照片,生成一段宠物弹吉他的视频。',
4009
+ trigger: '根据{A图片}生成一段{宠物A}弹吉他的视频',
4010
+ },
4011
+ {
4012
+ id: '7572443489834844223',
4013
+ name: '图生动作模仿视频',
4014
+ description: '用一张图片和动作视频,生成一段图片主体模仿该动作视频的新视频。',
4015
+ trigger: '生成{A图片}模仿{B视频}的视频',
4016
+ },
4017
+ {
4018
+ id: '7575160546555674670',
4019
+ name: '文生动作模仿视频',
4020
+ description: '用一段提示词和视频,生成一段模仿该视频的新视频。',
4021
+ trigger: '生成一段{提示词A}模仿{B视频}的视频',
4022
+ },
4023
+ ];
3980
4024
  const currentSession = await validateSession('generate-video-by-template');
3981
4025
  const validatedFileName = validateFileName(saveToFileName);
3982
4026
  const ai = currentSession.ai;
3983
4027
  let completion = await ai.getCompletions({
3984
- model: 'Doubao-Seed-1.6-flash',
4028
+ model: 'Doubao-Seed-1.6',
3985
4029
  messages: [
3986
4030
  {
3987
4031
  role: 'system',
3988
- content: `你根据用户需求,从以下模板中选择一个匹配的模板,返回模板ID:\n\n${JSON.stringify(templates)}\n\n**约束**:只输出模板ID,不需要其他解释。`,
4032
+ content: `你根据用户需求,从以下模板中选择一个匹配的模板,返回模板ID:\n\n${JSON.stringify(templates)}\n\n**约束**:只输出模板ID,不需要其他解释,如果没有匹配的模版,输出"无匹配模版"`,
3989
4033
  },
3990
4034
  {
3991
4035
  role: 'user',
3992
- content: `用户意图:${purpose}`,
4036
+ content: user_request,
3993
4037
  },
3994
4038
  ],
3995
4039
  });
3996
4040
  const templateId = completion.choices[0]?.message?.content.trim();
3997
- if (!templateId) {
4041
+ if (!templateId || templateId === '无匹配模版') {
3998
4042
  throw new Error('Failed to get template ID');
3999
4043
  }
4000
4044
  const workflowInfo = await ai.getCozeWorkflowInfo(templateId);
@@ -4017,11 +4061,12 @@ server.registerTool('generate-video-by-template', {
4017
4061
  ## **工作流输入 schema**:
4018
4062
  ${JSON.stringify(workflowInfo.data.workflow_detail.description)}
4019
4063
 
4020
- ## **prompt**:
4021
- ${text_prompts}
4064
+ ## **用户需求 prompt**:
4065
+ ${user_request}
4022
4066
 
4023
4067
  ## **materials**:
4024
4068
  ${JSON.stringify(materialUrls)}`;
4069
+ // console.log(prompt);
4025
4070
  completion = await ai.getCompletions({
4026
4071
  model: 'Doubao-Seed-1.6-flash',
4027
4072
  messages: [
@@ -4043,7 +4088,6 @@ ${JSON.stringify(materialUrls)}`;
4043
4088
  if (!parameters) {
4044
4089
  throw new Error('Failed to get parameters');
4045
4090
  }
4046
- console.log(parameters);
4047
4091
  const result = await ai.runCozeWorkflow(templateId, JSON.parse(parameters).parameters);
4048
4092
  if (result.url) {
4049
4093
  // 保存到项目材料目录
@@ -4075,7 +4119,7 @@ ${JSON.stringify(materialUrls)}`;
4075
4119
  };
4076
4120
  }
4077
4121
  catch (error) {
4078
- return createErrorResponse(error, 'generate-video-by-template');
4122
+ return createErrorResponse(error, 'use-template');
4079
4123
  }
4080
4124
  });
4081
4125
  server.registerTool('run-ffmpeg-command', {
@@ -4172,6 +4216,34 @@ server.registerTool('run-ffmpeg-command', {
4172
4216
  return createErrorResponse(error, 'run-ffmpeg-command');
4173
4217
  }
4174
4218
  });
4219
+ server.registerTool('do-storyboard-optimization', {
4220
+ title: 'Do Storyboard Optimization',
4221
+ description: 'Get storyboard optimization guidelines and action instructions.',
4222
+ inputSchema: {},
4223
+ }, async () => {
4224
+ try {
4225
+ // 调用 do-storyboard-optimization 工具时,设置 checkStoryboardFlag 为 true
4226
+ checkStoryboardFlag = true;
4227
+ const guidelinePath = (0, node_path_1.resolve)(__dirname, './prompts/actions/storyboard_optimization.md');
4228
+ const storyboardOptimizationGuidelines = await (0, promises_1.readFile)(guidelinePath, 'utf-8');
4229
+ return {
4230
+ content: [
4231
+ {
4232
+ type: 'text',
4233
+ text: JSON.stringify({
4234
+ content: {
4235
+ guideline: storyboardOptimizationGuidelines,
4236
+ action: '你应当根据guideline优化storyboard.json',
4237
+ },
4238
+ }),
4239
+ },
4240
+ ],
4241
+ };
4242
+ }
4243
+ catch (error) {
4244
+ return createErrorResponse(error, 'do-storyboard-optimization');
4245
+ }
4246
+ });
4175
4247
  server.registerTool('search-context', {
4176
4248
  title: 'Search Context',
4177
4249
  description: 'Search the context.',