cerevox 2.28.0 → 2.30.0
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/dist/core/ai.d.ts +5 -0
- package/dist/core/ai.d.ts.map +1 -1
- package/dist/core/ai.js +232 -13
- package/dist/core/ai.js.map +1 -1
- package/dist/mcp/servers/prompts/rules/anime-series.md +2 -2
- package/dist/mcp/servers/prompts/rules/creative-ad.md +2 -2
- package/dist/mcp/servers/prompts/rules/freeform.md +185 -0
- package/dist/mcp/servers/prompts/rules/general-video.md +2 -2
- package/dist/mcp/servers/prompts/rules/music-video.md +1 -1
- package/dist/mcp/servers/prompts/rules/professional.md +1 -1
- package/dist/mcp/servers/prompts/rules/stage-play.md +1 -1
- package/dist/mcp/servers/prompts/rules/story-telling.md +3 -3
- package/dist/mcp/servers/prompts/zerocut-core.md +3 -4
- package/dist/mcp/servers/zerocut.d.ts.map +1 -1
- package/dist/mcp/servers/zerocut.js +28 -212
- package/dist/mcp/servers/zerocut.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# 自由创作
|
|
2
|
+
|
|
3
|
+
在这个模式下,你没有固定的工作流程,而是响应用户需求,遵循指令,使用合适的工具进行自由创作,帮助用户达成目标。
|
|
4
|
+
|
|
5
|
+
## 行为模式
|
|
6
|
+
|
|
7
|
+
在自由创作模式下,你不要自动化完成工作,而是分步骤,跟用户讨论并充分理解用户需求,然后**一步一步**进行工作,一次只调用一个或一组相关工具完成一个步骤任务即可。
|
|
8
|
+
|
|
9
|
+
在每一步中,需要按照过程质量保障的要求创建或更新相关文件。
|
|
10
|
+
|
|
11
|
+
### 过程质量保障
|
|
12
|
+
|
|
13
|
+
* 记录 creation-journal.json (重要‼️)
|
|
14
|
+
- 你应当在每一轮对话结束时总结并记录当前对话中的关键信息和完成的工作。
|
|
15
|
+
- 请将内容以JSON格式,按照**聊天**数组记录在 `creation-journal.json` 文件中。
|
|
16
|
+
- 这样可以为后续创建上下文提供参考,也可以帮助你更好地组织和管理创作过程。
|
|
17
|
+
|
|
18
|
+
#### creation-journal 例子
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
[
|
|
22
|
+
{
|
|
23
|
+
index: 1,
|
|
24
|
+
requirement: "用户交给我的原始需求",
|
|
25
|
+
reasoning: "针对这个需求的思考过程",
|
|
26
|
+
action: "具体执行的操作",
|
|
27
|
+
feedback: "执行结果反馈",
|
|
28
|
+
next: "后续可进行动作的思考"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
* 记录 learned-skill.json (重要‼️)
|
|
34
|
+
- 你应当在每一轮对话结束时总结并记录当前对话中学习到的技能和知识。
|
|
35
|
+
- 请将内容以JSON格式,按照**聊天**数组记录在 `learned-skill.json` 文件中。
|
|
36
|
+
- 这样可以为后续创建上下文提供参考,也可以帮助你更好地组织和管理创作过程。
|
|
37
|
+
|
|
38
|
+
#### learned-skill 例子
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
name: "将音乐和视频对口型",
|
|
44
|
+
reasoning: "针对这个技能的思考过程",
|
|
45
|
+
steps: [
|
|
46
|
+
{
|
|
47
|
+
index: 1,
|
|
48
|
+
action: "查找media-logs.json中视频对应的时长,计算时间轴,根据视频时长和配音时长,确定音频截取的时间点",
|
|
49
|
+
details: "视频时长为 ceil(配音时长) 秒数",
|
|
50
|
+
feedback: "对齐成功"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
index: 2,
|
|
54
|
+
action: "根据步骤1的结果,运行`run-ffmpeg`命令,截取对应时间的音频",
|
|
55
|
+
details: "ffmpeg 命令为...",
|
|
56
|
+
feedback: "音频截取成功"
|
|
57
|
+
}
|
|
58
|
+
...
|
|
59
|
+
],
|
|
60
|
+
feedback: "技能完成,成功匹配口型,文件保存于`sc01_lipsync.mp4`,接下来可以使用生成结果进行视频合成"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
* 保持上下文
|
|
66
|
+
- 在你认为需要的时刻,随时通过`retrieve-rules-context`召回规则上下文。
|
|
67
|
+
|
|
68
|
+
## 有用的上下文参考文件
|
|
69
|
+
|
|
70
|
+
在执行过程中,你会生成或得到一些有用的上下文参考文件:
|
|
71
|
+
|
|
72
|
+
- media-logs.json 一旦有任何视频或音频素材资源被生成,素材元数据会自动记录在该文件中,你可以通过查找这个文件快速找到某个素材的元数据。用户自行上传的素材也会在上传后记录到该文件中。
|
|
73
|
+
|
|
74
|
+
- xxxx.captions.json 这类文件通常是AI生成的带人声的歌曲,或者使用 media-analyze 工具分析过的音频素材自动生成的字幕文件。你可以通过查找这个文件快速找到某个音频素材的字幕信息。
|
|
75
|
+
|
|
76
|
+
## 关键能力
|
|
77
|
+
|
|
78
|
+
你拥有并掌握以下能力:
|
|
79
|
+
|
|
80
|
+
### 开启和关闭会话
|
|
81
|
+
|
|
82
|
+
在具体执行中,你第一次接到用户需求后,需要开启新的会话,但**不必**每次单步执行后都关闭会话,只有你判断任务已经圆满完成或者用户明确让你关闭会话时,你才主动关闭会话。
|
|
83
|
+
|
|
84
|
+
### 分镜构思
|
|
85
|
+
|
|
86
|
+
- 如果用户和你讨论视频剧情,或者已经有明确的场景想法,你使用 `'get-storyboard-schema` 工具来获知如何创建故事板,然后用故事板来帮助用户构思视频分镜。
|
|
87
|
+
- 在所有和剧情、设定有关的问题时,你都要先理解用户想法然后更新故事板,并与用户确认。
|
|
88
|
+
- 尤其是在生成素材前,能更新故事板就及时更新,以免后续遗忘信息,造成不一致。
|
|
89
|
+
|
|
90
|
+
### 素材生成
|
|
91
|
+
|
|
92
|
+
一般来说影视素材包括图片、配音、视频和BGM等,你拥有一系列工具可以帮助用户来制作素材。
|
|
93
|
+
|
|
94
|
+
#### 故事板优化工具
|
|
95
|
+
- `do-storyboard-optimization`:你可以用这个工具获取故事板优化规则和要领,帮助用户更加专业地设计分镜场景。
|
|
96
|
+
|
|
97
|
+
#### 图片工具
|
|
98
|
+
- `generate-character-image`:你拥有根据用户描述生成人物角色三视图的能力,这对于视频创作保持人物一致性非常重要,你可以建议用户在创作连续场景时采用这个工具生成角色三视图。
|
|
99
|
+
- `generate-line-sketch`: 你拥有根据用户描述生成主体或环境线稿的能力,这对于AI视频分镜场景创作十分重要,尤其是对场景一致性要求很高的场合,主体线稿能够确保多主体的站位、姿势或者关键内容一致,而背景线稿能保证场景关键元素的一致。你可以在处理用户诉求时推荐用户使用线稿工具。
|
|
100
|
+
- `generate-image`: 通用图片生成工具,你可以根据用户描述生成任意图片,而且可以使用多张参考图(支持主体角色、主体物品和背景),这在创作场景中非常有用。
|
|
101
|
+
- `edit-image`:图片局部编辑工具,你可以根据用户描述局部编辑已有的图片。
|
|
102
|
+
- `image-aligner`:图片优化工具,你可以根据分析结果调整提示词,待用户确认后,修改story_board,重新生成图片。
|
|
103
|
+
|
|
104
|
+
#### 配音工具和音频处理工具
|
|
105
|
+
- `search-voice`:你可以根据用户描述搜索并推荐合适的配音音色。
|
|
106
|
+
- `generate-scene-tts`:你可以根据用户描述生成场景的语音,你知晓何时该使用旁白,何时该使用人物对话。
|
|
107
|
+
- `generate-music`: 你可以使用这个工具让 AI 创作一首歌曲
|
|
108
|
+
- `generate-sound-effect`:你可以使用这个工具让 AI 创作音效
|
|
109
|
+
|
|
110
|
+
#### 视频工具
|
|
111
|
+
- `generate-video`:你可以根据用户描述生成视频,这个工具主要用于根据首帧或首尾帧生成视频,连续性可通过一镜到底(连续镜头)保障。
|
|
112
|
+
- `generate-video-by-ref`:你可以根据用户描述和参考图生成视频,这个工具主要用于根据参考图生成视频,连续性可通过镜头自然延伸或`extend-video-duration`保障。
|
|
113
|
+
- `extend-video-duration`:你可以根据用户描述和已有的视频延长视频时长,这个工具主要用于在已有的视频基础上延长视频时长。
|
|
114
|
+
|
|
115
|
+
#### 后期制作和视频处理工具
|
|
116
|
+
- `generate-music`:你可以用这个工具生成适合视频内容风格的BGM
|
|
117
|
+
- `lip-sync`:唇形同步工具,你可以使用这个工具为人物对口型
|
|
118
|
+
- `get-video-project-schema`:你执行这个工具获取视频剪辑合成的JSON格式规范,用该规范创建 draft_content.json 文件,然后通过这个文件进行视频合成
|
|
119
|
+
- `compile-and-run`:你执行这个工具编译并运行 draft_content.json 文件,生成视频。
|
|
120
|
+
- `run-ffmpeg`:你可以使用这个工具执行任意ffmpeg命令,这在需要对视频进行更复杂处理时非常有用。
|
|
121
|
+
|
|
122
|
+
#### 其他工具
|
|
123
|
+
- `media-analyzer`: 你可以使用这个工具分析视频、图片等素材,获取素材的元数据和内容信息,它支持分析图片、语音以及视频。
|
|
124
|
+
- `upload-custom-meterials`:你可以使用这个工具上传自定义素材,包括图片、视频、音频等,这些素材将被存储在materials/目录下,上传后,你可以使用操作素材的任意工具像处理AI生成的素材一样处理你的自定义素材,也可以在draft_content.json中引用这些素材。
|
|
125
|
+
|
|
126
|
+
## 专业技能与术语
|
|
127
|
+
|
|
128
|
+
- 你已熟知“首(尾)帧生视频”、“参考图生视频”、“一镜到底(连续镜头)”、“镜头自然延伸”等视频创建概念和技巧。
|
|
129
|
+
- 你知晓并能运用基础镜头语言来创作视频,包括推进、拉远、变焦推进、变焦拉远、左摇、右摇、上摇、下摇、左移、右移、上升、下降、跟随、晃动、固定、穿过等镜头动作。
|
|
130
|
+
- 你知晓美学风格,包括传统美学、现代美学、抽象美学等,能够根据用户需求选择合适的美学风格。
|
|
131
|
+
|
|
132
|
+
## 镜头知识
|
|
133
|
+
|
|
134
|
+
### 基础镜头语言
|
|
135
|
+
|
|
136
|
+
镜头语言包括以下这些类型,可组合使用:
|
|
137
|
+
|
|
138
|
+
* 推进、拉远
|
|
139
|
+
- 摄像机水平向前或向后移动,适合突出商品细节或展示整体场景
|
|
140
|
+
* 变焦推进,变焦拉远
|
|
141
|
+
- 呈现为画面等比例放大或缩小,常用于商品特写展示
|
|
142
|
+
* 左摇、右摇
|
|
143
|
+
- 摄相机本身位置不变,拍摄角度水平向左或向右转动,适合展示商品全貌
|
|
144
|
+
* 上摇、下摇
|
|
145
|
+
- 摄相机本身位置不变,拍摄角度垂直向上或向下转动
|
|
146
|
+
* 左移、右移
|
|
147
|
+
- 摄相机向左或向右移动拍摄,适合展示商品的不同侧面
|
|
148
|
+
* 上升、下降
|
|
149
|
+
- 摄像机垂直上升或下降拍摄,创造视觉冲击力
|
|
150
|
+
* 跟随
|
|
151
|
+
- 摄像机捕捉某一对象的动作进行运动,跟随对象在画面中位置基本稳定,适合展示商品使用过程
|
|
152
|
+
* 晃动
|
|
153
|
+
- 摄像机不规则运动或抖动,可以伴随其他运动同时发生,用以营造激烈氛围
|
|
154
|
+
* 固定
|
|
155
|
+
- 摄像机固定不动,适合稳定展示商品特性
|
|
156
|
+
* 穿过
|
|
157
|
+
- 摄像机镜头向前推,穿过前景主体,创造层次感
|
|
158
|
+
|
|
159
|
+
## 美学词典
|
|
160
|
+
|
|
161
|
+
可选择的画面美学专业词汇:
|
|
162
|
+
|
|
163
|
+
### 风格响应
|
|
164
|
+
|
|
165
|
+
古早风 | 民国 | 虚幻引擎5 | 克苏鲁 | 新艺术 | 城市摄影 | 纪实摄影 | 轻胶感 | 野生动物摄影 | 构成主义 | 抽象主义 | 电影质感 | 定格动画
|
|
166
|
+
|
|
167
|
+
### 美学风格
|
|
168
|
+
|
|
169
|
+
暖色调 | 过度曝光 | 侧光 | 侧逆光 | backlighting | 暖光源 | top lighting | 窗光 | soft lighting | 发丝光 | self-illumination | 火光 | 底光 | 轮廓光 | stage lighting | 高饱和 | high-angle shot | 丁达尔光 | 近景 | 中景 | 远景 | 深景深 | full body shot | 动态模糊 | 浅景深 | 斜侧视角 | 正面光 | back view | 侧面视角 | 四分之三视角 | 极端特写 | 特写 | 鸟瞰 | enclosed composition | 居中构图 | 冷光源 | 弱光 | 冷色调 | 低角度视角 | 强光 | 双性照明 | dark-toned | 低对比度 | 亮调 | 低饱和 | high-contrast | 硬光 | 闪光灯
|
|
170
|
+
|
|
171
|
+
### 摄影
|
|
172
|
+
|
|
173
|
+
古风摄影 | CCD | 柯达拍摄 | 胶片 | 人文摄影 | 户外摄影 | 富士拍摄 | 单色摄影 | 小清新 | 写真摄影 | fashion photograph | 街头摄影 | 老照片 | 汽车摄影 | 夜景摄影 | 风景摄影
|
|
174
|
+
|
|
175
|
+
### 潮流
|
|
176
|
+
|
|
177
|
+
Riso | 皮影 | 盲盒 | 故障风 | 分格漫画 | Q版 | 美式复古 | BJD| 千禧 | 国风 | 魂系游戏 | 蒸汽朋克 | 波西米亚 | 黑暗恐怖 | 中世纪 | 超级英雄 | 蜡笔画 | 90年代游戏 | 港风 | 赛博朋克
|
|
178
|
+
|
|
179
|
+
### 艺术
|
|
180
|
+
|
|
181
|
+
山水画 | 皴法 | 花鸟画 | 仕女图 | 绢本画 | 工笔画 | 浮世绘 | 文艺复兴 | 巴洛克风格 | 新古典主义 | 古典主义 | 象征主义 | 洛可可风格 | 浮雕 | 大师素描 | 速写 | 雕塑 | 肖像画 | 印象派 | 拼贴艺术 | 大师版画 | 超写实主义 | 立体主义 | 孟菲斯
|
|
182
|
+
|
|
183
|
+
### 材质
|
|
184
|
+
|
|
185
|
+
sisal | 亚麻绳 | 灯芯绒 | 亚麻布 | wicker | 竹编 | 棉花 | 草编 | 牛仔布 | 沙子 | 毛绒 | 颗粒纹理 | 木头 | 植绒 | 羽毛 | 皮革 | velvet | 火山熔岩 | 树脂 | gel | 超轻粘土 | 粘土 | 泡沫 | felt | 磨砂 | 薄纱 | 海绵 | lace | 羊毛 | 塑料 | 石膏 | 大理石 | 陶瓷 | 亚克力 | 透明 | 玻璃 | 水泥 | 石头 | 砖块 | 混凝土 | 金属 | 沥青
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
1) 配音 `generate-scene-tts`
|
|
15
15
|
2) 图片 `generate-image` + 视频 `generate-video`
|
|
16
16
|
或 `generate-video-by-ref` 参考图生视频
|
|
17
|
-
3) 背景音乐 `generate-
|
|
17
|
+
3) 背景音乐 `generate-music`
|
|
18
18
|
6. 技术规范 → 调用`get-video-project-schema`获取最新规范 → 根据规范创建 draft_content.json
|
|
19
19
|
7. 执行渲染 → `compile-and-run` 输出成品并自动下载到本地
|
|
20
20
|
8. 关闭项目 → `zerocut-project-close`
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
* 方式二(story_board 的当前 scene 设置 video_type: references):
|
|
52
52
|
1) `generate-scene-tts`生成配音(确定时长:接口返回数据中durationMs为配音时长)
|
|
53
53
|
2) `generate-video-by-ref`参考图生视频
|
|
54
|
-
5. `generate-
|
|
54
|
+
5. `generate-music`生成背景音乐
|
|
55
55
|
6. 创建`draft_content.json`:
|
|
56
56
|
- ⚠️ 必须包含完整的VideoProject结构
|
|
57
57
|
- 除非用户明确拒绝,否则`draft_content.json`中必须包含字幕:
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
1. 确保项目已启动 → `zerocut-project-open`
|
|
8
8
|
2. 资料收集(可选)→ 使用搜索工具收集相关资料
|
|
9
9
|
3. 音乐创作 → 根据主题构思音乐氛围 → 创作歌词 lyrics.txt
|
|
10
|
-
4. 音乐生成 → 根据 lyrics.txt 调用 `generate-
|
|
10
|
+
4. 音乐生成 → 根据 lyrics.txt 调用 `generate-music` → 获得歌曲和 captions
|
|
11
11
|
5. 分析歌曲 → 创建 timeline_analysis.json 得到 captions 的时间线
|
|
12
12
|
6. 设计分镜场景 → `get-storyboard-schema` 获取分镜场景规范 → 创建初始 story_board.json
|
|
13
13
|
7. 主要角色形象塑造 → `generate-character-image` → 生成主要角色形象参考图(三视图)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
1. 确保项目已启动 → `zerocut-project-open`
|
|
8
8
|
2. 音乐剧创作 → 根据主题构思音乐氛围 → 创作歌词 lyrics.txt
|
|
9
|
-
3. 音乐生成 → 根据 lyrics.txt 调用 `generate-
|
|
9
|
+
3. 音乐生成 → 根据 lyrics.txt 调用 `generate-music` → 获得歌曲和 captions
|
|
10
10
|
4. 分析歌曲 → 创建 timeline_analysis.json 得到 captions 的时间线
|
|
11
11
|
5. 设计分镜场景 → `get-storyboard-schema` 获取分镜场景规范 → 创建初始 story_board.json
|
|
12
12
|
6. 角色形象塑造 → `generate-character-image` → 生成角色形象参考图(三视图)
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
* 分组场景图片 `generate-image-serials` (一次性生成所有分镜图片)
|
|
26
26
|
* 配音 `generate-scene-tts` (⚠️ 务必严格采用story_board中场景的script或dialog作为配音输入文本)
|
|
27
27
|
* 视频 `generate-video`
|
|
28
|
-
* 背景音乐 `generate-
|
|
28
|
+
* 背景音乐 `generate-music`
|
|
29
29
|
**模式二:角色三视图生成**
|
|
30
30
|
* 角色三视图 `generate-character-image` (为主要角色生成三视图)
|
|
31
31
|
* 分镜图片 `generate-image` (依次生成各分镜图片,使用角色三视图作为参考)
|
|
32
32
|
* 配音 `generate-scene-tts` (⚠️ 务必严格采用story_board中场景的script或dialog作为配音输入文本)
|
|
33
33
|
* 视频 `generate-video`
|
|
34
|
-
* 背景音乐 `generate-
|
|
34
|
+
* 背景音乐 `generate-music`
|
|
35
35
|
10. 技术规范 → 调用`get-video-project-schema`获取最新规范 → 根据规范创建 draft_content.json
|
|
36
36
|
11. 执行渲染 → `compile-and-run` 输出成品并自动下载到本地
|
|
37
37
|
12. 关闭项目 → `zerocut-project-close`
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
- **配音同步:** 确保 `generate-scene-tts` 的输入文本与 story_board 中的 script 或 dialog 完全一致
|
|
56
56
|
- **时长规范:** 视频时长必须为整秒数,配音、音效等可以精确到毫秒,如有对应配音,默认视频时长为 ceil(配音时长) 秒数
|
|
57
57
|
- **内容一致性:** story_board 文案 script 和配音内容必须严格一致,如生成配音时修改了文案,必须及时更新 story_board
|
|
58
|
-
- **音画协调:** 背景音乐 `generate-
|
|
58
|
+
- **音画协调:** 背景音乐 `generate-music` 必须与故事情感基调和节奏相匹配
|
|
59
59
|
|
|
60
60
|
## 专业技巧
|
|
61
61
|
|
|
@@ -273,8 +273,9 @@ projects/<id>/
|
|
|
273
273
|
|
|
274
274
|
## 技巧及术语
|
|
275
275
|
|
|
276
|
-
0.
|
|
276
|
+
0. 专家模式和自由创作模式
|
|
277
277
|
- 若用户**明确指定**使用专家模式,召回规则上下文时须使用 purpose: professional,否则**不得使用**该模式
|
|
278
|
+
- 若用户**明确指定**使用自由创作模式,召回规则上下文时须使用 purpose: freeform,否则**不得使用**该模式
|
|
278
279
|
|
|
279
280
|
1. 生成视频的几种方式
|
|
280
281
|
- 首帧图生视频(默认采用):先根据 start_frame 生成首帧图片如 sc01_start.png,然后用该图片作为视频的第一帧,以 video_prompt 的提示词用 `generate-image` 生成视频
|
|
@@ -286,9 +287,7 @@ projects/<id>/
|
|
|
286
287
|
|
|
287
288
|
3. 镜头自然延伸:和“一镜到底”不同的连续画面技术,当用户说“镜头自然延伸”时,应当在生成视频时,设置saveLastFrameAs参数,将其返回的图片作为下一场景的首帧图片。
|
|
288
289
|
|
|
289
|
-
4.
|
|
290
|
-
|
|
291
|
-
5. 优化图片:当用户或工作流程要求优化图片时,可运行 `image-aligner` 工具,根据分析结果调整提示词,待用户确认后,修改story_board,重新生成图片。
|
|
290
|
+
4. 优化图片:当用户或工作流程要求优化图片时,可运行 `image-aligner` 工具,根据分析结果调整提示词,待用户确认后,修改story_board,重新生成图片。
|
|
292
291
|
|
|
293
292
|
## 工具优先级
|
|
294
293
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zerocut.d.ts","sourceRoot":"","sources":["../../../src/mcp/servers/zerocut.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"zerocut.d.ts","sourceRoot":"","sources":["../../../src/mcp/servers/zerocut.ts"],"names":[],"mappings":";AAy2KA,wBAAsB,GAAG,kBAKxB"}
|
|
@@ -447,6 +447,7 @@ server.registerTool('retrieve-rules-context', {
|
|
|
447
447
|
'story-telling',
|
|
448
448
|
'creative-ad',
|
|
449
449
|
'professional',
|
|
450
|
+
'freeform',
|
|
450
451
|
'custom',
|
|
451
452
|
])
|
|
452
453
|
.default('general-video')
|
|
@@ -476,7 +477,8 @@ server.registerTool('retrieve-rules-context', {
|
|
|
476
477
|
purpose !== 'anime-series' &&
|
|
477
478
|
purpose !== 'story-telling' &&
|
|
478
479
|
purpose !== 'creative-ad' &&
|
|
479
|
-
purpose !== 'professional'
|
|
480
|
+
purpose !== 'professional' &&
|
|
481
|
+
purpose !== 'freeform') {
|
|
480
482
|
return createErrorResponse(`Project rules file not found: ${projectRulesFile}`, 'retrieve-rules-context');
|
|
481
483
|
}
|
|
482
484
|
}
|
|
@@ -2301,135 +2303,45 @@ server.registerTool('generate-sound-effect', {
|
|
|
2301
2303
|
return createErrorResponse(error, 'generate-sound-effect');
|
|
2302
2304
|
}
|
|
2303
2305
|
});
|
|
2304
|
-
server.registerTool('generate-
|
|
2305
|
-
title: 'Generate
|
|
2306
|
-
description: 'Generate
|
|
2306
|
+
server.registerTool('generate-music', {
|
|
2307
|
+
title: 'Generate Music',
|
|
2308
|
+
description: 'Generate the music. Include background music or song.',
|
|
2307
2309
|
inputSchema: {
|
|
2310
|
+
prompt: zod_1.z.string().describe('The prompt to generate.'),
|
|
2308
2311
|
type: zod_1.z
|
|
2312
|
+
.enum(['bgm', 'song'])
|
|
2313
|
+
.describe('The type of music. Defaults to background music.')
|
|
2314
|
+
.default('bgm'),
|
|
2315
|
+
model: zod_1.z
|
|
2309
2316
|
.enum(['doubao', 'minimax'])
|
|
2310
|
-
.
|
|
2311
|
-
.describe('The model
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
- 完整歌词通常包括以下桥段:
|
|
2315
|
-
- 前奏: intro,歌曲开始的音乐部分,主要用于引导歌曲的整体氛围。
|
|
2316
|
-
- 主歌: verse,通常在前奏之后,歌曲中叙述歌曲故事或主题的部分。
|
|
2317
|
-
- 副歌: chorus,一般在主歌之后,旋律有记忆点和感染力,是整首歌的高潮,进一步强化歌曲的主题和情感。
|
|
2318
|
-
- 间奏: inst,歌曲中的纯音乐段落,用于连接不同的演唱部分。
|
|
2319
|
-
- 尾奏: outro,歌曲结束后的音乐段落,用于营造歌曲结束的氛围。
|
|
2320
|
-
- 桥段: bridge,通常出现在歌曲中段或接近结尾处,是一个过渡部分,用于连接不同的歌曲段落。
|
|
2321
|
-
|
|
2322
|
-
### 歌词示例 lyrics.txt
|
|
2323
|
-
|
|
2324
|
-
\`\`\`txt
|
|
2325
|
-
[intro]
|
|
2326
|
-
[verse]
|
|
2327
|
-
记得那一天 那一天我们相恋
|
|
2328
|
-
说好彼此都不说再见
|
|
2329
|
-
遵守诺言 用心去相恋
|
|
2330
|
-
我为你撑伞 你为我取暖
|
|
2331
|
-
[inst]
|
|
2332
|
-
[chorus]
|
|
2333
|
-
当我把心交给你的那一天
|
|
2334
|
-
你却消失在我的眼前
|
|
2335
|
-
事到如今已经过了好多年
|
|
2336
|
-
是否你还像从前
|
|
2337
|
-
[outro]
|
|
2338
|
-
\`\`\`
|
|
2339
|
-
`),
|
|
2317
|
+
.optional()
|
|
2318
|
+
.describe('The model to use. Defaults to doubao.')
|
|
2319
|
+
.default('doubao'),
|
|
2340
2320
|
duration: zod_1.z
|
|
2341
2321
|
.number()
|
|
2342
2322
|
.min(30)
|
|
2343
2323
|
.max(240)
|
|
2344
|
-
.describe('The duration of the
|
|
2345
|
-
genre: zod_1.z
|
|
2346
|
-
.enum([
|
|
2347
|
-
'Folk',
|
|
2348
|
-
'Pop',
|
|
2349
|
-
'Rock',
|
|
2350
|
-
'Chinese Style',
|
|
2351
|
-
'Hip Hop/Rap',
|
|
2352
|
-
'R&B/Soul',
|
|
2353
|
-
'Punk',
|
|
2354
|
-
'Electronic',
|
|
2355
|
-
'Jazz',
|
|
2356
|
-
'Reggae',
|
|
2357
|
-
'DJ',
|
|
2358
|
-
'Pop Punk',
|
|
2359
|
-
'Disco',
|
|
2360
|
-
'Future Bass',
|
|
2361
|
-
'Pop Rap',
|
|
2362
|
-
'Trap Rap',
|
|
2363
|
-
'R&B Rap',
|
|
2364
|
-
'Chinoiserie Electronic',
|
|
2365
|
-
'GuFeng Music',
|
|
2366
|
-
'Pop Rock',
|
|
2367
|
-
'Jazz Pop',
|
|
2368
|
-
'Bossa Nova',
|
|
2369
|
-
'Contemporary R&B',
|
|
2370
|
-
])
|
|
2371
|
-
.optional()
|
|
2372
|
-
.describe('The genre of the song.'),
|
|
2373
|
-
mood: zod_1.z
|
|
2374
|
-
.enum([
|
|
2375
|
-
'Happy',
|
|
2376
|
-
'Dynamic/Energetic',
|
|
2377
|
-
'Sentimental/Melancholic/Lonely',
|
|
2378
|
-
'Inspirational/Hopeful',
|
|
2379
|
-
'Nostalgic/Memory',
|
|
2380
|
-
'Excited',
|
|
2381
|
-
'Sorrow/Sad',
|
|
2382
|
-
'Chill',
|
|
2383
|
-
'Relaxing',
|
|
2384
|
-
'Romantic',
|
|
2385
|
-
'Miss',
|
|
2386
|
-
'Groovy/Funky',
|
|
2387
|
-
'Dreamy/Ethereal',
|
|
2388
|
-
'Calm/Relaxing',
|
|
2389
|
-
])
|
|
2390
|
-
.optional()
|
|
2391
|
-
.describe('The mood of the song.'),
|
|
2392
|
-
gender: zod_1.z
|
|
2393
|
-
.enum(['Female', 'Male'])
|
|
2394
|
-
.optional()
|
|
2395
|
-
.describe('The gender of the vocalist.'),
|
|
2396
|
-
timbre: zod_1.z
|
|
2397
|
-
.enum([
|
|
2398
|
-
'Warm',
|
|
2399
|
-
'Bright',
|
|
2400
|
-
'Husky',
|
|
2401
|
-
'Electrified voice',
|
|
2402
|
-
'Sweet_AUDIO_TIMBRE',
|
|
2403
|
-
'Cute_AUDIO_TIMBRE',
|
|
2404
|
-
'Loud and sonorous',
|
|
2405
|
-
'Powerful',
|
|
2406
|
-
'Sexy/Lazy',
|
|
2407
|
-
])
|
|
2408
|
-
.optional()
|
|
2409
|
-
.describe('The timbre/voice quality of the vocalist.'),
|
|
2324
|
+
.describe('The duration of the bgm or music.'),
|
|
2410
2325
|
skipCopyCheck: zod_1.z
|
|
2411
2326
|
.boolean()
|
|
2412
|
-
.optional()
|
|
2413
2327
|
.default(false)
|
|
2414
2328
|
.describe('Whether to skip copyright check.'),
|
|
2415
2329
|
saveToFileName: zod_1.z.string().describe('The filename to save.'),
|
|
2416
2330
|
},
|
|
2417
|
-
}, async ({ type
|
|
2331
|
+
}, async ({ prompt, type, model, duration, skipCopyCheck, saveToFileName }, context) => {
|
|
2418
2332
|
try {
|
|
2419
2333
|
// 验证session状态
|
|
2420
|
-
const currentSession = await validateSession('generate-
|
|
2334
|
+
const currentSession = await validateSession('generate-music');
|
|
2421
2335
|
const validatedFileName = validateFileName(saveToFileName);
|
|
2422
|
-
console.log(`Generating
|
|
2336
|
+
console.log(`Generating Music with prompt: ${prompt.substring(0, 100)}... (${duration}s)`);
|
|
2423
2337
|
const ai = currentSession.ai;
|
|
2424
2338
|
let progress = 0;
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
gender,
|
|
2432
|
-
timbre,
|
|
2339
|
+
if (type === 'bgm' && duration > 120) {
|
|
2340
|
+
throw new Error('BGM duration must be at most 120 seconds.');
|
|
2341
|
+
}
|
|
2342
|
+
const finalPrompt = `${prompt.trim()} ${type === 'bgm' ? `纯音乐无歌词,时长${duration}秒` : `时长${duration}秒,使用${model}模型`}`;
|
|
2343
|
+
const res = await ai.generateMusic({
|
|
2344
|
+
prompt: finalPrompt,
|
|
2433
2345
|
skipCopyCheck,
|
|
2434
2346
|
onProgress: async (metaData) => {
|
|
2435
2347
|
try {
|
|
@@ -2441,18 +2353,12 @@ server.registerTool('generate-song', {
|
|
|
2441
2353
|
},
|
|
2442
2354
|
});
|
|
2443
2355
|
if (!res) {
|
|
2444
|
-
throw new Error('Failed to generate
|
|
2356
|
+
throw new Error('Failed to generate BGM: no response from AI service');
|
|
2445
2357
|
}
|
|
2446
2358
|
if (res.url) {
|
|
2447
|
-
console.log('
|
|
2359
|
+
console.log('BGM generated successfully, saving to materials...');
|
|
2448
2360
|
const uri = await saveMaterial(currentSession, res.url, validatedFileName);
|
|
2449
|
-
|
|
2450
|
-
// 歌词获取失败,获取字幕
|
|
2451
|
-
res.captions = await ai.voiceToCaptions({
|
|
2452
|
-
url: res.url,
|
|
2453
|
-
});
|
|
2454
|
-
}
|
|
2455
|
-
const { url, duration: songDuration, captions, ...opts } = res;
|
|
2361
|
+
const { url, duration: bgmDuration, captions, ...opts } = res;
|
|
2456
2362
|
// 保存captions到本地
|
|
2457
2363
|
if (captions) {
|
|
2458
2364
|
const captionsText = JSON.stringify(captions, null, 2);
|
|
@@ -2461,103 +2367,13 @@ server.registerTool('generate-song', {
|
|
|
2461
2367
|
// 保存到本地
|
|
2462
2368
|
await (0, promises_1.writeFile)(localPath, captionsText);
|
|
2463
2369
|
}
|
|
2464
|
-
const result = {
|
|
2465
|
-
success: true,
|
|
2466
|
-
// source: url,
|
|
2467
|
-
uri,
|
|
2468
|
-
durationMs: Math.floor((songDuration || duration) * 1000),
|
|
2469
|
-
lyrics,
|
|
2470
|
-
requestedDuration: duration,
|
|
2471
|
-
genre,
|
|
2472
|
-
mood,
|
|
2473
|
-
gender,
|
|
2474
|
-
timbre,
|
|
2475
|
-
captions,
|
|
2476
|
-
timestamp: new Date().toISOString(),
|
|
2477
|
-
...opts,
|
|
2478
|
-
};
|
|
2479
|
-
// Update media_logs.json
|
|
2480
|
-
try {
|
|
2481
|
-
await updateMediaLogs(currentSession, validatedFileName, result, 'audio');
|
|
2482
|
-
}
|
|
2483
|
-
catch (error) {
|
|
2484
|
-
console.warn(`Failed to update media_logs.json for ${validatedFileName}:`, error);
|
|
2485
|
-
}
|
|
2486
|
-
return {
|
|
2487
|
-
content: [
|
|
2488
|
-
{
|
|
2489
|
-
type: 'text',
|
|
2490
|
-
text: JSON.stringify(result),
|
|
2491
|
-
},
|
|
2492
|
-
],
|
|
2493
|
-
};
|
|
2494
|
-
}
|
|
2495
|
-
else {
|
|
2496
|
-
console.warn('Song generation completed but no URL returned');
|
|
2497
|
-
return {
|
|
2498
|
-
content: [
|
|
2499
|
-
{
|
|
2500
|
-
type: 'text',
|
|
2501
|
-
text: JSON.stringify({
|
|
2502
|
-
success: false,
|
|
2503
|
-
error: 'No Song URL returned from AI service',
|
|
2504
|
-
response: res,
|
|
2505
|
-
timestamp: new Date().toISOString(),
|
|
2506
|
-
}),
|
|
2507
|
-
},
|
|
2508
|
-
],
|
|
2509
|
-
};
|
|
2510
|
-
}
|
|
2511
|
-
}
|
|
2512
|
-
catch (error) {
|
|
2513
|
-
return createErrorResponse(error, 'generate-song');
|
|
2514
|
-
}
|
|
2515
|
-
});
|
|
2516
|
-
server.registerTool('generate-bgm', {
|
|
2517
|
-
title: 'Generate BGM',
|
|
2518
|
-
description: 'Generate the bgm.',
|
|
2519
|
-
inputSchema: {
|
|
2520
|
-
prompt: zod_1.z.string().describe('The prompt to generate.'),
|
|
2521
|
-
duration: zod_1.z
|
|
2522
|
-
.number()
|
|
2523
|
-
.min(30)
|
|
2524
|
-
.max(120)
|
|
2525
|
-
.describe('The duration of the bgm.'),
|
|
2526
|
-
saveToFileName: zod_1.z.string().describe('The filename to save.'),
|
|
2527
|
-
},
|
|
2528
|
-
}, async ({ prompt, duration, saveToFileName }, context) => {
|
|
2529
|
-
try {
|
|
2530
|
-
// 验证session状态
|
|
2531
|
-
const currentSession = await validateSession('generate-bgm');
|
|
2532
|
-
const validatedFileName = validateFileName(saveToFileName);
|
|
2533
|
-
console.log(`Generating BGM with prompt: ${prompt.substring(0, 100)}... (${duration}s)`);
|
|
2534
|
-
const ai = currentSession.ai;
|
|
2535
|
-
let progress = 0;
|
|
2536
|
-
const res = await ai.generateBGM({
|
|
2537
|
-
prompt: prompt.trim(),
|
|
2538
|
-
duration,
|
|
2539
|
-
onProgress: async (metaData) => {
|
|
2540
|
-
try {
|
|
2541
|
-
await sendProgress(context, metaData.Result?.Progress ?? ++progress, metaData.Result?.Progress ? 100 : undefined, JSON.stringify(metaData));
|
|
2542
|
-
}
|
|
2543
|
-
catch (progressError) {
|
|
2544
|
-
console.warn('Failed to send progress update:', progressError);
|
|
2545
|
-
}
|
|
2546
|
-
},
|
|
2547
|
-
});
|
|
2548
|
-
if (!res) {
|
|
2549
|
-
throw new Error('Failed to generate BGM: no response from AI service');
|
|
2550
|
-
}
|
|
2551
|
-
if (res.url) {
|
|
2552
|
-
console.log('BGM generated successfully, saving to materials...');
|
|
2553
|
-
const uri = await saveMaterial(currentSession, res.url, validatedFileName);
|
|
2554
|
-
const { url, duration: bgmDuration, ...opts } = res;
|
|
2555
2370
|
const result = {
|
|
2556
2371
|
success: true,
|
|
2557
2372
|
// source: url,
|
|
2558
2373
|
uri,
|
|
2559
2374
|
durationMs: Math.floor((bgmDuration || duration) * 1000),
|
|
2560
2375
|
prompt,
|
|
2376
|
+
captions,
|
|
2561
2377
|
requestedDuration: duration,
|
|
2562
2378
|
timestamp: new Date().toISOString(),
|
|
2563
2379
|
...opts,
|