cerevox 4.5.3 → 4.6.1

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.
@@ -1005,8 +1005,9 @@ server.registerTool('generate-image', {
1005
1005
  const startFrame = scene.start_frame;
1006
1006
  const endFrame = scene.end_frame;
1007
1007
  // 检查 prompt 是否严格等于 start_frame 或 end_frame
1008
- if (prompt !== startFrame && prompt !== endFrame) {
1009
- return createErrorResponse('图片提示词必须严格遵照storyboard的设定,内容完全一致,包括空格、回车、标点和特殊符号', 'generate-image');
1008
+ if (prompt.trim() !== startFrame?.trim() &&
1009
+ prompt.trim() !== endFrame?.trim()) {
1010
+ return createErrorResponse('图片提示词必须严格遵照storyboard的设定,内容完全一致,包括空格、回车、标点和特殊符号,检查传入的prompt参数与storyboard中的start_frame或end_frame是否完全一致', 'generate-image');
1010
1011
  }
1011
1012
  if (hasOutlineSheet &&
1012
1013
  (!referenceImages ||
@@ -1964,8 +1965,8 @@ server.registerTool('generate-video', {
1964
1965
  const scene = storyBoard.scenes[sceneIndex - 1]; // sceneIndex 从1开始,数组从0开始
1965
1966
  if (scene) {
1966
1967
  const videoPrompt = scene.video_prompt;
1967
- if (videoPrompt && prompt !== videoPrompt) {
1968
- return createErrorResponse('视频提示词必须严格遵照storyboard的设定,内容完全一致,包括空格、回车、标点和特殊符号', 'generate-video');
1968
+ if (videoPrompt && prompt.trim() !== videoPrompt?.trim()) {
1969
+ return createErrorResponse('视频提示词必须严格遵照storyboard的设定,内容完全一致,包括空格、回车、标点和特殊符号,检查传入的prompt参数与storyboard中的video_prompt是否完全一致', 'generate-video');
1969
1970
  }
1970
1971
  if (scene.is_continuous && !end_frame) {
1971
1972
  return createErrorResponse('连续分镜必须指定end_frame参数', 'generate-video');
@@ -2387,8 +2388,13 @@ server.registerTool('generate-video-by-ref', {
2387
2388
  .optional()
2388
2389
  .default(true)
2389
2390
  .describe('默认true,自动规范化镜头语言'),
2391
+ autoStoryboard: zod_1.z
2392
+ .boolean()
2393
+ .optional()
2394
+ .default(false)
2395
+ .describe('自动生成分镜宫格(智能分镜),默认不启用,除非用户明确要求使用'),
2390
2396
  },
2391
- }, async ({ prompt, referenceImages, duration, aspectRatio, resolution, type = 'vidu', audio = false, saveToFileName, sceneIndex, optimizeCameraMotion, seed, referenceVideo, }, context) => {
2397
+ }, async ({ prompt, referenceImages, duration, aspectRatio, resolution, type = 'vidu', audio = false, saveToFileName, sceneIndex, optimizeCameraMotion, seed, referenceVideo, autoStoryboard, }, context) => {
2392
2398
  try {
2393
2399
  const storyBoardFile = 'storyboard.json';
2394
2400
  // 验证session状态
@@ -2423,8 +2429,8 @@ server.registerTool('generate-video-by-ref', {
2423
2429
  const scene = storyBoard.scenes[sceneIndex - 1]; // sceneIndex 从1开始,数组从0开始
2424
2430
  if (scene) {
2425
2431
  const videoPrompt = scene.video_prompt;
2426
- if (videoPrompt && prompt !== videoPrompt) {
2427
- return createErrorResponse('视频提示词必须严格遵照storyboard的设定,内容完全一致,包括空格、回车、标点和特殊符号', 'generate-video-by-ref');
2432
+ if (videoPrompt && prompt.trim() !== videoPrompt?.trim()) {
2433
+ return createErrorResponse('视频提示词必须严格遵照storyboard的设定,内容完全一致,包括空格、回车、标点和特殊符号,检查传入的prompt参数与storyboard中的video_prompt是否完全一致', 'generate-video-by-ref');
2428
2434
  }
2429
2435
  // 检查 scene.is_continuous 是否为 true
2430
2436
  if (scene.is_continuous === true) {
@@ -2543,6 +2549,7 @@ server.registerTool('generate-video-by-ref', {
2543
2549
  ]
2544
2550
  : undefined;
2545
2551
  // 调用 referencesToVideo 函数
2552
+ let progress = 0;
2546
2553
  const result = await currentSession.ai.referencesToVideo({
2547
2554
  prompt: finalPrompt,
2548
2555
  reference_images: referenceImageUrls, // 使用URL数组而不是base64数组
@@ -2554,9 +2561,10 @@ server.registerTool('generate-video-by-ref', {
2554
2561
  seed,
2555
2562
  videos,
2556
2563
  optimizeCameraMotion,
2564
+ autoStoryboard,
2557
2565
  onProgress: metaData => {
2558
2566
  console.log('Video generation progress:', metaData);
2559
- sendProgress(context, metaData.progress || 0, 100, 'Generating video...');
2567
+ sendProgress(context, ++progress, undefined, JSON.stringify(metaData));
2560
2568
  },
2561
2569
  waitForFinish: CLIENT_TYPE !== '5ire',
2562
2570
  });
@@ -3016,82 +3024,97 @@ server.registerTool('audio-video-sync', {
3016
3024
  return createErrorResponse(error, 'lip-sync');
3017
3025
  }
3018
3026
  });
3019
- server.registerTool('add-subtitles', {
3020
- title: 'Add Subtitles to Video',
3021
- description: '给已有视频添加字幕',
3022
- inputSchema: {
3023
- videoFileName: zod_1.z.string().describe('材料目录中的视频文件名'),
3024
- subtitles: zod_1.z
3025
- .object({
3026
- text: zod_1.z.string().optional(),
3027
- style: zod_1.z
3028
- .object({
3029
- font_size: zod_1.z.number().optional(),
3030
- font_color: zod_1.z.string().optional(),
3031
- border_color: zod_1.z.string().optional(),
3032
- border_width: zod_1.z.number().optional(),
3033
- font_pos_config: zod_1.z
3034
- .object({
3035
- pos_x: zod_1.z.string().optional(),
3036
- pos_y: zod_1.z.string().optional(),
3037
- height: zod_1.z.string().optional(),
3038
- width: zod_1.z.string().optional(),
3039
- })
3040
- .optional(),
3041
- })
3042
- .optional(),
3043
- })
3044
- .optional(),
3045
- subtitlesContext: zod_1.z.string().optional(),
3046
- saveToFileName: zod_1.z.string().describe('应该是mp4文件'),
3047
- },
3048
- }, async ({ videoFileName, subtitles, subtitlesContext, saveToFileName }) => {
3049
- try {
3050
- const currentSession = await validateSession('add-subtitles');
3051
- const validatedFileName = validateFileName(saveToFileName);
3052
- const videoUrl = await getMaterialUri(currentSession, videoFileName);
3053
- const ai = currentSession.ai;
3054
- const res = await ai.addVideoSubtitles({
3055
- videoUrl,
3056
- subtitles,
3057
- subtitlesContext,
3058
- });
3059
- if (res.url) {
3060
- const video = await saveMaterial(currentSession, res.url, validatedFileName);
3061
- return {
3062
- content: [
3063
- {
3064
- type: 'text',
3065
- text: JSON.stringify({
3066
- success: true,
3067
- video,
3068
- filename: validatedFileName,
3069
- timestamp: new Date().toISOString(),
3070
- }),
3071
- },
3072
- ],
3073
- };
3074
- }
3075
- else {
3076
- return {
3077
- content: [
3078
- {
3079
- type: 'text',
3080
- text: JSON.stringify({
3081
- success: false,
3082
- error: 'No video URL returned from subtitles service',
3083
- response: res,
3084
- timestamp: new Date().toISOString(),
3085
- }),
3086
- },
3087
- ],
3088
- };
3089
- }
3090
- }
3091
- catch (error) {
3092
- return createErrorResponse(error, 'add-subtitles');
3093
- }
3094
- });
3027
+ // server.registerTool(
3028
+ // 'add-subtitles',
3029
+ // {
3030
+ // title: 'Add Subtitles to Video',
3031
+ // description:
3032
+ // '给已有视频添加字幕,audio-video-sync工具中可直接同步字幕,不需要这个工具',
3033
+ // inputSchema: {
3034
+ // videoFileName: z.string().describe('材料目录中的视频文件名'),
3035
+ // subtitles: z
3036
+ // .object({
3037
+ // text: z.string().optional(),
3038
+ // style: z
3039
+ // .object({
3040
+ // font_size: z.number().optional(),
3041
+ // font_color: z.string().optional(),
3042
+ // border_color: z.string().optional(),
3043
+ // border_width: z.number().optional(),
3044
+ // font_pos_config: z
3045
+ // .object({
3046
+ // pos_x: z.string().describe('只能用百分比格式'),
3047
+ // pos_y: z.string().describe('只能用百分比格式'),
3048
+ // height: z.string().describe('只能用百分比格式'),
3049
+ // width: z.string().describe('只能用百分比格式'),
3050
+ // })
3051
+ // .optional(),
3052
+ // })
3053
+ // .optional(),
3054
+ // })
3055
+ // .optional(),
3056
+ // subtitlesContext: z.string().optional(),
3057
+ // saveToFileName: z.string().describe('应该是mp4文件'),
3058
+ // },
3059
+ // },
3060
+ // async ({ videoFileName, subtitles, subtitlesContext, saveToFileName }) => {
3061
+ // try {
3062
+ // const currentSession = await validateSession('add-subtitles');
3063
+ // const validatedFileName = validateFileName(saveToFileName);
3064
+ // const videoUrl = await getMaterialUri(currentSession, videoFileName);
3065
+ // const ai = currentSession.ai;
3066
+ // if (subtitles?.style && !subtitles.style.font_pos_config) {
3067
+ // subtitles.style.font_pos_config = {
3068
+ // height: '15%',
3069
+ // pos_x: '5%',
3070
+ // pos_y: '85%',
3071
+ // width: '90%',
3072
+ // };
3073
+ // }
3074
+ // const res = await ai.addVideoSubtitles({
3075
+ // videoUrl,
3076
+ // subtitles,
3077
+ // subtitlesContext,
3078
+ // });
3079
+ // if (res.url) {
3080
+ // const video = await saveMaterial(
3081
+ // currentSession,
3082
+ // res.url,
3083
+ // validatedFileName
3084
+ // );
3085
+ // return {
3086
+ // content: [
3087
+ // {
3088
+ // type: 'text',
3089
+ // text: JSON.stringify({
3090
+ // success: true,
3091
+ // video,
3092
+ // filename: validatedFileName,
3093
+ // timestamp: new Date().toISOString(),
3094
+ // }),
3095
+ // },
3096
+ // ],
3097
+ // };
3098
+ // } else {
3099
+ // return {
3100
+ // content: [
3101
+ // {
3102
+ // type: 'text',
3103
+ // text: JSON.stringify({
3104
+ // success: false,
3105
+ // error: 'No video URL returned from subtitles service',
3106
+ // response: res,
3107
+ // timestamp: new Date().toISOString(),
3108
+ // }),
3109
+ // },
3110
+ // ],
3111
+ // };
3112
+ // }
3113
+ // } catch (error) {
3114
+ // return createErrorResponse(error, 'add-subtitles');
3115
+ // }
3116
+ // }
3117
+ // );
3095
3118
  server.registerTool('use-template', {
3096
3119
  title: 'Use Template',
3097
3120
  description: 'Find a template that matches the user request, and use it to generate a new material.',