mulmocast 1.1.0 → 1.1.2

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.
Files changed (87) hide show
  1. package/assets/templates/akira_comic.json +1 -1
  2. package/assets/templates/ani.json +3 -3
  3. package/assets/templates/ani_ja.json +3 -3
  4. package/assets/templates/business.json +1 -1
  5. package/assets/templates/characters.json +1 -1
  6. package/assets/templates/children_book.json +1 -1
  7. package/assets/templates/coding.json +1 -1
  8. package/assets/templates/comic_strips.json +1 -1
  9. package/assets/templates/drslump_comic.json +1 -1
  10. package/assets/templates/ghibli_comic.json +1 -1
  11. package/assets/templates/ghibli_image_only.json +1 -1
  12. package/assets/templates/ghibli_shorts.json +1 -1
  13. package/assets/templates/ghost_comic.json +1 -1
  14. package/assets/templates/html.json +1 -1
  15. package/assets/templates/onepiece_comic.json +1 -1
  16. package/assets/templates/portrait_movie.json +1 -1
  17. package/assets/templates/realistic_movie.json +1 -1
  18. package/assets/templates/sensei_and_taro.json +1 -1
  19. package/assets/templates/shorts.json +1 -1
  20. package/assets/templates/text_and_image.json +1 -1
  21. package/assets/templates/text_only.json +1 -1
  22. package/assets/templates/trailer.json +1 -1
  23. package/lib/actions/image_agents.d.ts +24 -0
  24. package/lib/actions/image_agents.js +9 -0
  25. package/lib/actions/images.js +35 -6
  26. package/lib/actions/movie.js +3 -2
  27. package/lib/agents/index.d.ts +2 -1
  28. package/lib/agents/index.js +2 -1
  29. package/lib/agents/lipsync_replicate_agent.d.ts +5 -0
  30. package/lib/agents/lipsync_replicate_agent.js +72 -0
  31. package/lib/agents/movie_replicate_agent.js +10 -1
  32. package/lib/cli/commands/tool/prompt/builder.js +2 -2
  33. package/lib/cli/commands/tool/scripting/builder.js +2 -2
  34. package/lib/cli/commands/tool/story_to_script/builder.js +2 -2
  35. package/lib/data/index.d.ts +2 -0
  36. package/lib/data/index.js +2 -0
  37. package/lib/data/promptTemplates.d.ts +449 -0
  38. package/lib/data/promptTemplates.js +571 -0
  39. package/lib/data/scriptTemplates.d.ts +657 -0
  40. package/lib/data/scriptTemplates.js +1099 -0
  41. package/lib/index.browser.d.ts +2 -1
  42. package/lib/index.browser.js +2 -1
  43. package/lib/index.common.d.ts +1 -0
  44. package/lib/index.common.js +1 -0
  45. package/lib/methods/index.d.ts +0 -1
  46. package/lib/methods/index.js +0 -1
  47. package/lib/methods/mulmo_presentation_style.d.ts +10 -0
  48. package/lib/methods/mulmo_presentation_style.js +8 -1
  49. package/lib/methods/mulmo_script_template.d.ts +2 -2
  50. package/lib/tools/create_mulmo_script_from_url.js +14 -2
  51. package/lib/tools/create_mulmo_script_interactively.js +2 -1
  52. package/lib/tools/dump_prompt.js +1 -1
  53. package/lib/tools/story_to_script.js +5 -4
  54. package/lib/types/agent.d.ts +10 -0
  55. package/lib/types/schema.d.ts +322 -92
  56. package/lib/types/schema.js +11 -2
  57. package/lib/types/type.d.ts +4 -4
  58. package/lib/utils/context.d.ts +21 -6
  59. package/lib/utils/context.js +1 -0
  60. package/lib/utils/file.d.ts +5 -5
  61. package/lib/utils/file.js +36 -33
  62. package/lib/utils/inquirer.js +2 -2
  63. package/lib/utils/preprocess.d.ts +16 -6
  64. package/lib/utils/prompt.d.ts +1 -2
  65. package/lib/utils/prompt.js +0 -14
  66. package/lib/utils/provider2agent.d.ts +13 -0
  67. package/lib/utils/provider2agent.js +32 -0
  68. package/lib/utils/system_prompt.d.ts +1 -0
  69. package/lib/utils/system_prompt.js +1 -0
  70. package/lib/utils/templates.d.ts +3 -0
  71. package/lib/utils/templates.js +46 -0
  72. package/lib/utils/utils.js +3 -0
  73. package/package.json +8 -4
  74. package/scripts/templates/business.json +1 -1
  75. package/scripts/templates/children_book.json +1 -1
  76. package/scripts/templates/coding.json +1 -1
  77. package/scripts/templates/html.json +1 -1
  78. package/scripts/templates/image_prompt_only_template.json +1 -1
  79. package/scripts/templates/image_prompts_template.json +1 -1
  80. package/scripts/templates/image_refs.json +1 -1
  81. package/scripts/templates/movie_prompts_no_text_template.json +1 -1
  82. package/scripts/templates/movie_prompts_template.json +1 -1
  83. package/scripts/templates/presentation.json +1 -1
  84. package/scripts/templates/sensei_and_taro.json +1 -1
  85. package/scripts/templates/shorts_template.json +1 -1
  86. package/scripts/templates/text_only_template.json +1 -1
  87. package/scripts/templates/voice_over.json +1 -1
@@ -233,6 +233,10 @@ export const mulmoSoundEffectParamsSchema = z.object({
233
233
  provider: text2SoundEffectProviderSchema.optional(),
234
234
  model: z.string().optional(), // default: provider specific
235
235
  });
236
+ export const mulmoLipSyncParamsSchema = z.object({
237
+ provider: z.string().optional(), // lip sync provider
238
+ model: z.string().optional(), // default: provider specific
239
+ });
236
240
  export const mulmoBeatSchema = z
237
241
  .object({
238
242
  speaker: speakerIdSchema.optional(),
@@ -253,6 +257,7 @@ export const mulmoBeatSchema = z
253
257
  })
254
258
  .optional(),
255
259
  soundEffectParams: mulmoSoundEffectParamsSchema.optional(),
260
+ lipSyncParams: mulmoLipSyncParamsSchema.optional(),
256
261
  htmlImageParams: mulmoHtmlImageParamsSchema.optional(),
257
262
  speechOptions: speechOptionsSchema.optional(),
258
263
  textSlideParams: textSlideParamsSchema.optional(),
@@ -262,6 +267,7 @@ export const mulmoBeatSchema = z
262
267
  moviePrompt: z.string().optional(),
263
268
  soundEffectPrompt: z.string().optional(),
264
269
  htmlPrompt: htmlPromptParamsSchema.optional(),
270
+ enableLipSync: z.boolean().optional().describe("Enable lip sync generation for this beat"),
265
271
  })
266
272
  .strict();
267
273
  export const mulmoCanvasDimensionSchema = z
@@ -332,6 +338,7 @@ export const mulmoPresentationStyleSchema = z.object({
332
338
  soundEffectParams: mulmoSoundEffectParamsSchema.optional().default({
333
339
  provider: defaultProviders.soundEffect,
334
340
  }),
341
+ lipSyncParams: mulmoLipSyncParamsSchema.optional(),
335
342
  htmlImageParams: mulmoHtmlImageParamsSchema
336
343
  .extend({
337
344
  provider: text2HtmlImageProviderSchema,
@@ -381,6 +388,7 @@ export const mulmoStudioBeatSchema = z
381
388
  imageFile: z.string().optional(), // path to the image
382
389
  movieFile: z.string().optional(), // path to the movie file
383
390
  soundEffectFile: z.string().optional(), // path to the sound effect file
391
+ lipSyncFile: z.string().optional(), // path to the lip sync file
384
392
  captionFile: z.string().optional(), // path to the caption image
385
393
  })
386
394
  .strict();
@@ -406,6 +414,7 @@ export const mulmoSessionStateSchema = z.object({
406
414
  html: z.record(z.number().int(), z.boolean()),
407
415
  imageReference: z.record(z.number().int(), z.boolean()),
408
416
  soundEffect: z.record(z.number().int(), z.boolean()),
417
+ lipSync: z.record(z.number().int(), z.boolean()),
409
418
  }),
410
419
  });
411
420
  export const mulmoStudioSchema = z
@@ -415,7 +424,7 @@ export const mulmoStudioSchema = z
415
424
  beats: z.array(mulmoStudioBeatSchema).min(1),
416
425
  })
417
426
  .strict();
418
- export const mulmoScriptTemplateSchema = z
427
+ export const mulmoPromptTemplateSchema = z
419
428
  .object({
420
429
  title: z.string(),
421
430
  description: z.string(),
@@ -424,7 +433,7 @@ export const mulmoScriptTemplateSchema = z
424
433
  presentationStyle: mulmoPresentationStyleSchema.optional(),
425
434
  })
426
435
  .strict();
427
- export const mulmoScriptTemplateFileSchema = mulmoScriptTemplateSchema.extend({
436
+ export const mulmoPromptTemplateFileSchema = mulmoPromptTemplateSchema.extend({
428
437
  filename: z.string(),
429
438
  });
430
439
  export const mulmoStoryboardSceneSchema = z
@@ -1,4 +1,4 @@
1
- import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualDataSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoImageParamsImagesSchema, mulmoFillOptionSchema, mulmoMovieParamsSchema, textSlideParamsSchema, speechOptionsSchema, speakerDataSchema, mulmoCanvasDimensionSchema, mulmoScriptTemplateSchema, mulmoScriptTemplateFileSchema, text2ImageProviderSchema, text2HtmlImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, multiLingualTextsSchema, mulmoImageAssetSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema, mulmoSessionStateSchema, mulmoOpenAIImageModelSchema, mulmoGoogleImageModelSchema, mulmoGoogleMovieModelSchema, mulmoReplicateMovieModelSchema, mulmoImagePromptMediaSchema } from "./schema.js";
1
+ import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualDataSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoImageParamsImagesSchema, mulmoFillOptionSchema, mulmoMovieParamsSchema, textSlideParamsSchema, speechOptionsSchema, speakerDataSchema, mulmoCanvasDimensionSchema, mulmoPromptTemplateSchema, mulmoPromptTemplateFileSchema, text2ImageProviderSchema, text2HtmlImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, multiLingualTextsSchema, mulmoImageAssetSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema, mulmoSessionStateSchema, mulmoOpenAIImageModelSchema, mulmoGoogleImageModelSchema, mulmoGoogleMovieModelSchema, mulmoReplicateMovieModelSchema, mulmoImagePromptMediaSchema } from "./schema.js";
2
2
  import { pdf_modes, pdf_sizes, storyToScriptGenerateMode } from "../utils/const.js";
3
3
  import type { LLM } from "../utils/provider2agent.js";
4
4
  import { z } from "zod";
@@ -24,8 +24,8 @@ export type MulmoStoryboard = z.infer<typeof mulmoStoryboardSchema>;
24
24
  export type MulmoStudioBeat = z.infer<typeof mulmoStudioBeatSchema>;
25
25
  export type MulmoMediaSource = z.infer<typeof mediaSourceSchema>;
26
26
  export type MulmoStudio = z.infer<typeof mulmoStudioSchema>;
27
- export type MulmoScriptTemplate = z.infer<typeof mulmoScriptTemplateSchema>;
28
- export type MulmoScriptTemplateFile = z.infer<typeof mulmoScriptTemplateFileSchema>;
27
+ export type MulmoPromptTemplate = z.infer<typeof mulmoPromptTemplateSchema>;
28
+ export type MulmoPromptTemplateFile = z.infer<typeof mulmoPromptTemplateFileSchema>;
29
29
  export type MulmoStudioMultiLingual = z.infer<typeof mulmoStudioMultiLingualSchema>;
30
30
  export type MulmoStudioMultiLingualData = z.infer<typeof mulmoStudioMultiLingualDataSchema>;
31
31
  export type MultiLingualTexts = z.infer<typeof multiLingualTextsSchema>;
@@ -91,7 +91,7 @@ export type Text2HtmlAgentInfo = {
91
91
  export type BeatMediaType = "movie" | "image";
92
92
  export type StoryToScriptGenerateMode = (typeof storyToScriptGenerateMode)[keyof typeof storyToScriptGenerateMode];
93
93
  export type SessionType = "audio" | "image" | "video" | "multiLingual" | "caption" | "pdf";
94
- export type BeatSessionType = "audio" | "image" | "multiLingual" | "caption" | "movie" | "html" | "imageReference" | "soundEffect";
94
+ export type BeatSessionType = "audio" | "image" | "multiLingual" | "caption" | "movie" | "html" | "imageReference" | "soundEffect" | "lipSync";
95
95
  export type SessionProgressEvent = {
96
96
  kind: "session";
97
97
  sessionType: SessionType;
@@ -17,6 +17,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
17
17
  imageFile?: string | undefined;
18
18
  movieFile?: string | undefined;
19
19
  soundEffectFile?: string | undefined;
20
+ lipSyncFile?: string | undefined;
20
21
  captionFile?: string | undefined;
21
22
  }[];
22
23
  script: {
@@ -209,12 +210,6 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
209
210
  type: "voice_over";
210
211
  startAt?: number | undefined;
211
212
  } | undefined;
212
- duration?: number | undefined;
213
- speechOptions?: {
214
- speed?: number | undefined;
215
- instruction?: string | undefined;
216
- } | undefined;
217
- id?: string | undefined;
218
213
  audio?: {
219
214
  type: "audio";
220
215
  source: {
@@ -234,6 +229,12 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
234
229
  type: "midi";
235
230
  source: string;
236
231
  } | undefined;
232
+ duration?: number | undefined;
233
+ speechOptions?: {
234
+ speed?: number | undefined;
235
+ instruction?: string | undefined;
236
+ } | undefined;
237
+ id?: string | undefined;
237
238
  imagePrompt?: string | undefined;
238
239
  speaker?: string | undefined;
239
240
  description?: string | undefined;
@@ -278,6 +279,10 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
278
279
  provider?: string | undefined;
279
280
  model?: string | undefined;
280
281
  } | undefined;
282
+ lipSyncParams?: {
283
+ provider?: string | undefined;
284
+ model?: string | undefined;
285
+ } | undefined;
281
286
  htmlImageParams?: {
282
287
  model?: string | undefined;
283
288
  } | undefined;
@@ -297,10 +302,15 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
297
302
  images?: Record<string, any> | undefined;
298
303
  systemPrompt?: string | undefined;
299
304
  } | undefined;
305
+ enableLipSync?: boolean | undefined;
300
306
  }[];
301
307
  lang?: string | undefined;
302
308
  title?: string | undefined;
303
309
  description?: string | undefined;
310
+ lipSyncParams?: {
311
+ provider?: string | undefined;
312
+ model?: string | undefined;
313
+ } | undefined;
304
314
  htmlImageParams?: {
305
315
  provider: string;
306
316
  model?: string | undefined;
@@ -344,6 +354,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
344
354
  html: {};
345
355
  imageReference: {};
346
356
  soundEffect: {};
357
+ lipSync: {};
347
358
  };
348
359
  };
349
360
  presentationStyle: {
@@ -430,6 +441,10 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
430
441
  model?: string | undefined;
431
442
  }>;
432
443
  };
444
+ lipSyncParams?: {
445
+ provider?: string | undefined;
446
+ model?: string | undefined;
447
+ } | undefined;
433
448
  htmlImageParams?: {
434
449
  provider: string;
435
450
  model?: string | undefined;
@@ -59,6 +59,7 @@ const initSessionState = () => {
59
59
  html: {},
60
60
  imageReference: {},
61
61
  soundEffect: {},
62
+ lipSync: {},
62
63
  },
63
64
  };
64
65
  };
@@ -1,4 +1,4 @@
1
- import type { MulmoScript, MulmoScriptTemplateFile, MulmoStudioContext } from "../types/index.js";
1
+ import type { MulmoScript, MulmoPromptTemplateFile, MulmoStudioContext } from "../types/index.js";
2
2
  import { PDFMode } from "../types/index.js";
3
3
  import { ZodSchema } from "zod";
4
4
  export declare const updateNpmRoot: (_npmRoot: string) => void;
@@ -28,20 +28,20 @@ export declare const getBeatPngImagePath: (context: MulmoStudioContext, index: n
28
28
  export declare const getBeatMoviePaths: (context: MulmoStudioContext, index: number) => {
29
29
  movieFile: string;
30
30
  soundEffectFile: string;
31
+ lipSyncFile: string;
31
32
  };
32
33
  export declare const getReferenceImagePath: (context: MulmoStudioContext, key: string, extension: string) => string;
33
34
  export declare const getCaptionImagePath: (context: MulmoStudioContext, index: number) => string;
34
35
  export declare const getOutputPdfFilePath: (outDirPath: string, fileName: string, pdfMode: PDFMode, lang?: string) => string;
35
- export declare const getTemplateFilePath: (templateName: string) => string;
36
+ export declare const getPromptTemplateFilePath: (promptTemplateName: string) => string;
36
37
  export declare const mkdir: (dirPath: string) => void;
37
38
  export declare const silent60secPath: () => string;
38
39
  export declare const defaultBGMPath: () => string;
39
40
  export declare const getHTMLFile: (filename: string) => string;
40
41
  export declare const getBaseDirPath: (basedir?: string) => string;
41
42
  export declare const getFullPath: (baseDirPath: string | undefined, file: string) => string;
42
- export declare const readScriptTemplateFile: (scriptName: string) => any;
43
- export declare const readTemplatePrompt: (templateName: string) => string;
44
- export declare const getAvailableTemplates: () => MulmoScriptTemplateFile[];
43
+ export declare const getAvailablePromptTemplates: (skipValidation?: boolean) => MulmoPromptTemplateFile[];
44
+ export declare const getAvailableScriptTemplates: () => MulmoScript[];
45
45
  export declare const writingMessage: (filePath: string) => void;
46
46
  export declare const readAndParseJson: <S extends ZodSchema<any>>(filePath: string, schema: S) => ReturnType<S["parse"]>;
47
47
  export declare const generateTimestampedFileName: (prefix: string) => string;
package/lib/utils/file.js CHANGED
@@ -3,8 +3,10 @@ import path from "path";
3
3
  import { parse as yamlParse } from "yaml";
4
4
  import { fileURLToPath } from "url";
5
5
  import { GraphAILogger } from "graphai";
6
- import { MulmoScriptTemplateMethods, MulmoStudioContextMethods } from "../methods/index.js";
7
- import { mulmoScriptTemplateSchema } from "../types/schema.js";
6
+ import { MulmoStudioContextMethods } from "../methods/index.js";
7
+ import { mulmoPromptTemplateSchema } from "../types/schema.js";
8
+ const promptTemplateDirName = "./assets/templates";
9
+ const scriptTemplateDirName = "./scripts/templates";
8
10
  const __filename = fileURLToPath(import.meta.url);
9
11
  const __dirname = path.dirname(__filename);
10
12
  let npmRoot = path.resolve(__dirname, "../../");
@@ -91,7 +93,11 @@ export const getBeatMoviePaths = (context, index) => {
91
93
  const imageProjectDirPath = MulmoStudioContextMethods.getImageProjectDirPath(context);
92
94
  const beat = context.studio.script.beats[index]; // beat could be undefined only in a test case.
93
95
  const filename = beat?.id ? `${beat.id}` : `${index}`;
94
- return { movieFile: `${imageProjectDirPath}/${filename}.mov`, soundEffectFile: `${imageProjectDirPath}/${filename}_sound.mov` };
96
+ return {
97
+ movieFile: `${imageProjectDirPath}/${filename}.mov`,
98
+ soundEffectFile: `${imageProjectDirPath}/${filename}_sound.mov`,
99
+ lipSyncFile: `${imageProjectDirPath}/${filename}_lipsync.mov`,
100
+ };
95
101
  };
96
102
  export const getReferenceImagePath = (context, key, extension) => {
97
103
  const imageProjectDirPath = MulmoStudioContextMethods.getImageProjectDirPath(context);
@@ -108,8 +114,8 @@ export const getOutputPdfFilePath = (outDirPath, fileName, pdfMode, lang) => {
108
114
  }
109
115
  return path.resolve(outDirPath, `${fileName}_${pdfMode}.pdf`);
110
116
  };
111
- export const getTemplateFilePath = (templateName) => {
112
- return path.resolve(npmRoot, "./assets/templates/" + templateName + ".json");
117
+ export const getPromptTemplateFilePath = (promptTemplateName) => {
118
+ return path.resolve(npmRoot, promptTemplateDirName, promptTemplateName + ".json");
113
119
  };
114
120
  export const mkdir = (dirPath) => {
115
121
  if (!fs.existsSync(dirPath)) {
@@ -144,41 +150,38 @@ export const getFullPath = (baseDirPath, file) => {
144
150
  }
145
151
  return path.resolve(file);
146
152
  };
147
- export const readScriptTemplateFile = (scriptName) => {
148
- const scriptPath = path.resolve(npmRoot, "./scripts/templates", scriptName);
149
- const scriptData = fs.readFileSync(scriptPath, "utf-8");
150
- // NOTE: We don't want to schema parse the script here to eliminate default values.
151
- return JSON.parse(scriptData);
152
- };
153
- export const readTemplatePrompt = (templateName) => {
154
- const templatePath = getTemplateFilePath(templateName);
155
- const templateData = fs.readFileSync(templatePath, "utf-8");
156
- // NOTE: We don't want to schema parse the template here to eliminate default values.
157
- const template = JSON.parse(templateData);
158
- const script = (() => {
159
- if (template.scriptName) {
160
- const scriptData = readScriptTemplateFile(template.scriptName);
161
- return { ...scriptData, ...(template.presentationStyle ?? {}) };
162
- }
163
- return undefined;
164
- })();
165
- const prompt = MulmoScriptTemplateMethods.getSystemPrompt(template, script);
166
- return prompt;
167
- };
168
- export const getAvailableTemplates = () => {
169
- const templatesDir = path.resolve(npmRoot, "./assets/templates");
153
+ // templates
154
+ const getPromptTemplates = (dirPath, schema) => {
155
+ const templatesDir = path.resolve(npmRoot, dirPath);
170
156
  if (!fs.existsSync(templatesDir)) {
171
157
  return [];
172
158
  }
173
159
  const files = fs.readdirSync(templatesDir);
174
160
  return files.map((file) => {
175
- const template = JSON.parse(fs.readFileSync(path.resolve(templatesDir, file), "utf-8"));
176
- return {
177
- ...mulmoScriptTemplateSchema.parse(template),
178
- filename: file.replace(/\.json$/, ""),
179
- };
161
+ try {
162
+ const promptTemplate = JSON.parse(fs.readFileSync(path.resolve(templatesDir, file), "utf-8"));
163
+ return {
164
+ ...(schema ? schema.parse(promptTemplate) : promptTemplate),
165
+ filename: file.replace(/\.json$/, ""),
166
+ };
167
+ }
168
+ catch (e) {
169
+ GraphAILogger.info("file: " + file);
170
+ GraphAILogger.info(e);
171
+ return {};
172
+ }
180
173
  });
181
174
  };
175
+ export const getAvailablePromptTemplates = (skipValidation) => {
176
+ if (skipValidation) {
177
+ return getPromptTemplates(promptTemplateDirName, null);
178
+ }
179
+ return getPromptTemplates(promptTemplateDirName, mulmoPromptTemplateSchema);
180
+ };
181
+ export const getAvailableScriptTemplates = () => {
182
+ return getPromptTemplates(scriptTemplateDirName, null);
183
+ };
184
+ // end of template
182
185
  export const writingMessage = (filePath) => {
183
186
  GraphAILogger.debug(`writing: ${filePath}`);
184
187
  };
@@ -1,7 +1,7 @@
1
1
  import inquirer from "inquirer";
2
- import { getAvailableTemplates } from "./file.js";
2
+ import { getAvailablePromptTemplates } from "./file.js";
3
3
  export const selectTemplate = async () => {
4
- const availableTemplates = getAvailableTemplates();
4
+ const availableTemplates = getAvailablePromptTemplates();
5
5
  const answers = await inquirer.prompt([
6
6
  {
7
7
  type: "list",
@@ -12,6 +12,7 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
12
12
  imageFile?: string | undefined;
13
13
  movieFile?: string | undefined;
14
14
  soundEffectFile?: string | undefined;
15
+ lipSyncFile?: string | undefined;
15
16
  captionFile?: string | undefined;
16
17
  }[];
17
18
  script: {
@@ -204,12 +205,6 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
204
205
  type: "voice_over";
205
206
  startAt?: number | undefined;
206
207
  } | undefined;
207
- duration?: number | undefined;
208
- speechOptions?: {
209
- speed?: number | undefined;
210
- instruction?: string | undefined;
211
- } | undefined;
212
- id?: string | undefined;
213
208
  audio?: {
214
209
  type: "audio";
215
210
  source: {
@@ -229,6 +224,12 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
229
224
  type: "midi";
230
225
  source: string;
231
226
  } | undefined;
227
+ duration?: number | undefined;
228
+ speechOptions?: {
229
+ speed?: number | undefined;
230
+ instruction?: string | undefined;
231
+ } | undefined;
232
+ id?: string | undefined;
232
233
  imagePrompt?: string | undefined;
233
234
  speaker?: string | undefined;
234
235
  description?: string | undefined;
@@ -273,6 +274,10 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
273
274
  provider?: string | undefined;
274
275
  model?: string | undefined;
275
276
  } | undefined;
277
+ lipSyncParams?: {
278
+ provider?: string | undefined;
279
+ model?: string | undefined;
280
+ } | undefined;
276
281
  htmlImageParams?: {
277
282
  model?: string | undefined;
278
283
  } | undefined;
@@ -292,10 +297,15 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
292
297
  images?: Record<string, any> | undefined;
293
298
  systemPrompt?: string | undefined;
294
299
  } | undefined;
300
+ enableLipSync?: boolean | undefined;
295
301
  }[];
296
302
  lang?: string | undefined;
297
303
  title?: string | undefined;
298
304
  description?: string | undefined;
305
+ lipSyncParams?: {
306
+ provider?: string | undefined;
307
+ model?: string | undefined;
308
+ } | undefined;
299
309
  htmlImageParams?: {
300
310
  provider: string;
301
311
  model?: string | undefined;
@@ -1,8 +1,7 @@
1
- import { MulmoBeat, MulmoScript, MulmoScriptTemplate, MulmoStoryboard, MulmoCanvasDimension } from "../types/index.js";
1
+ import { MulmoBeat, MulmoScript, MulmoStoryboard, MulmoCanvasDimension } from "../types/index.js";
2
2
  export declare const imagePrompt: (beat: MulmoBeat, style?: string) => string;
3
3
  export declare const graphDataScriptFromUrlPrompt: (sourceTextInput: string) => string;
4
4
  export declare const graphDataScriptGeneratePrompt: (scene: string) => string;
5
- export declare const getMulmoScriptTemplateSystemPrompt: (template: MulmoScriptTemplate, script?: MulmoScript) => string;
6
5
  export declare const interactiveClarificationPrompt = "If there are any unclear points, be sure to ask the user questions and clarify them before generating the script.";
7
6
  export declare const prefixPrompt = "Here is the web content that can be used as reference material for the script:";
8
7
  export declare const translateSystemPrompt = "Please translate the given text into the language specified in language (in locale format, like en, ja, fr, ch).";
@@ -1,5 +1,3 @@
1
- import { mulmoScriptSchema } from "../types/schema.js";
2
- import { zodToJsonSchema } from "zod-to-json-schema";
3
1
  export const imagePrompt = (beat, style) => {
4
2
  return (beat.imagePrompt || `generate image appropriate for the text. text: ${beat.text}`) + "\n" + (style || "");
5
3
  };
@@ -10,18 +8,6 @@ export const graphDataScriptFromUrlPrompt = (sourceTextInput) => {
10
8
  export const graphDataScriptGeneratePrompt = (scene) => {
11
9
  return `Please generate a script from the following scenes: ${scene}`;
12
10
  };
13
- export const getMulmoScriptTemplateSystemPrompt = (template, script) => {
14
- // script is provided, use it as a script template
15
- if (script) {
16
- return `${template.systemPrompt}\n\`\`\`JSON\n${JSON.stringify(script)}\n\`\`\``;
17
- }
18
- // script is not provided, use the default schema
19
- const defaultSchema = zodToJsonSchema(mulmoScriptSchema, {
20
- strictUnions: true,
21
- });
22
- const specificOutputPrompt = `The output should follow the JSON schema specified below. Please provide your response as valid JSON within \`\`\`json code blocks for clarity.`;
23
- return `${template.systemPrompt}\n\n${specificOutputPrompt}\n\n\`\`\`JSON\n${JSON.stringify(defaultSchema)}\n\`\`\``;
24
- };
25
11
  export const interactiveClarificationPrompt = `If there are any unclear points, be sure to ask the user questions and clarify them before generating the script.`;
26
12
  export const prefixPrompt = "Here is the web content that can be used as reference material for the script:";
27
13
  export const translateSystemPrompt = "Please translate the given text into the language specified in language (in locale format, like en, ja, fr, ch).";
@@ -61,6 +61,18 @@ export declare const provider2SoundEffectAgent: {
61
61
  }>;
62
62
  };
63
63
  };
64
+ export declare const provider2LipSyncAgent: {
65
+ replicate: {
66
+ agentName: string;
67
+ defaultModel: ReplicateModel;
68
+ models: ReplicateModel[];
69
+ modelParams: Record<ReplicateModel, {
70
+ identifier?: `${string}/${string}:${string}`;
71
+ video: string;
72
+ audio: string;
73
+ }>;
74
+ };
75
+ };
64
76
  export declare const provider2LLMAgent: {
65
77
  readonly openai: {
66
78
  readonly agentName: "openAIAgent";
@@ -90,6 +102,7 @@ export declare const defaultProviders: {
90
102
  text2Html: keyof typeof provider2LLMAgent;
91
103
  llm: keyof typeof provider2LLMAgent;
92
104
  soundEffect: keyof typeof provider2SoundEffectAgent;
105
+ lipSync: keyof typeof provider2LipSyncAgent;
93
106
  };
94
107
  export declare const llm: (keyof typeof provider2LLMAgent)[];
95
108
  export type LLM = keyof typeof provider2LLMAgent;
@@ -130,6 +130,37 @@ export const provider2SoundEffectAgent = {
130
130
  },
131
131
  },
132
132
  };
133
+ export const provider2LipSyncAgent = {
134
+ replicate: {
135
+ agentName: "lipSyncReplicateAgent",
136
+ defaultModel: "bytedance/latentsync",
137
+ models: ["bytedance/latentsync", "tmappdev/lipsync"],
138
+ modelParams: {
139
+ "bytedance/latentsync": {
140
+ identifier: "bytedance/latentsync:637ce1919f807ca20da3a448ddc2743535d2853649574cd52a933120e9b9e293",
141
+ video: "video",
142
+ audio: "audio",
143
+ },
144
+ "tmappdev/lipsync": {
145
+ identifier: "tmappdev/lipsync:c54ce2fe673ea59b857b91250b3d71a2cd304a78f2370687632805c8405fbf4c",
146
+ video: "video_input",
147
+ audio: "audio_input",
148
+ },
149
+ /* NOTE: This model does not work with large base64 urls.
150
+ "sync/lipsync-2": {
151
+ video: "video",
152
+ audio: "audio",
153
+ },
154
+ */
155
+ /* NOTE: This model does not work well for some unknown reason.
156
+ "kwaivgi/kling-lip-sync": {
157
+ video: "video_url",
158
+ audio: "audio_file",
159
+ },
160
+ */
161
+ },
162
+ },
163
+ };
133
164
  // : Record<LLM, { agent: string; defaultModel: string; max_tokens: number }>
134
165
  export const provider2LLMAgent = {
135
166
  openai: {
@@ -160,6 +191,7 @@ export const defaultProviders = {
160
191
  text2Html: "openai",
161
192
  llm: "openai",
162
193
  soundEffect: "replicate",
194
+ lipSync: "replicate",
163
195
  };
164
196
  export const llm = Object.keys(provider2LLMAgent);
165
197
  export const htmlLLMProvider = ["openai", "anthropic"];
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { MulmoScript } from "../types/type.js";
2
+ export declare const readScriptTemplateFile: (scriptTemplateFileName: string) => MulmoScript;
3
+ export declare const readTemplatePrompt: (promptTemplateFileName: string) => string;
@@ -0,0 +1,46 @@
1
+ import { mulmoScriptSchema } from "../types/schema.js";
2
+ import { promptTemplates, scriptTemplates } from "../data/index.js";
3
+ import { zodToJsonSchema } from "zod-to-json-schema";
4
+ // script and prompt template
5
+ export const readScriptTemplateFile = (scriptTemplateFileName) => {
6
+ // NOTE: We don't want to schema parse the script here to eliminate default values.
7
+ const scriptTemplate = scriptTemplates.find((template) => template.filename === scriptTemplateFileName);
8
+ if (!scriptTemplate) {
9
+ throw new Error(`Script template not found: ${scriptTemplateFileName}`);
10
+ }
11
+ const { filename: __, ...retValue } = scriptTemplate;
12
+ return retValue;
13
+ };
14
+ const readPromptTemplateFile = (promptTemplateFileName) => {
15
+ // NOTE: We don't want to schema parse the template here to eliminate default values.
16
+ const promptTemplate = promptTemplates.find((template) => template.filename === promptTemplateFileName);
17
+ if (!promptTemplate) {
18
+ throw new Error(`Prompt template not found: ${promptTemplateFileName}`);
19
+ }
20
+ return promptTemplate;
21
+ };
22
+ const mulmoScriptTemplate2Script = (scriptTemplate) => {
23
+ if (scriptTemplate.scriptName) {
24
+ const scriptTemplateData = readScriptTemplateFile(scriptTemplate.scriptName);
25
+ return { ...scriptTemplateData, ...(scriptTemplate.presentationStyle ?? {}) };
26
+ }
27
+ return undefined;
28
+ };
29
+ export const readTemplatePrompt = (promptTemplateFileName) => {
30
+ const promptTemplate = readPromptTemplateFile(promptTemplateFileName);
31
+ const script = mulmoScriptTemplate2Script(promptTemplate);
32
+ const prompt = getMulmoScriptTemplateSystemPrompt(promptTemplate, script);
33
+ return prompt;
34
+ };
35
+ const getMulmoScriptTemplateSystemPrompt = (template, script) => {
36
+ // script is provided, use it as a script template
37
+ if (script) {
38
+ return `${template.systemPrompt}\n\`\`\`JSON\n${JSON.stringify(script)}\n\`\`\``;
39
+ }
40
+ // script is not provided, use the default schema
41
+ const defaultSchema = zodToJsonSchema(mulmoScriptSchema, {
42
+ strictUnions: true,
43
+ });
44
+ const specificOutputPrompt = `The output should follow the JSON schema specified below. Please provide your response as valid JSON within \`\`\`json code blocks for clarity.`;
45
+ return `${template.systemPrompt}\n\n${specificOutputPrompt}\n\n\`\`\`JSON\n${JSON.stringify(defaultSchema)}\n\`\`\``;
46
+ };
@@ -76,6 +76,9 @@ export const settings2GraphAIConfig = (settings, env) => {
76
76
  soundEffectReplicateAgent: {
77
77
  apiKey: getKey("SOUND_EFFECT", "REPLICATE_API_TOKEN"),
78
78
  },
79
+ lipSyncReplicateAgent: {
80
+ apiKey: getKey("LIPSYNC", "REPLICATE_API_TOKEN"),
81
+ },
79
82
  // TODO
80
83
  // browserlessAgent
81
84
  // ttsGoogleAgent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.node.js",
@@ -12,6 +12,9 @@
12
12
  "./browser": {
13
13
  "types": "./lib/index.browser.d.ts",
14
14
  "default": "./lib/index.browser.js"
15
+ },
16
+ "./data": {
17
+ "default": "./lib/data/index.js"
15
18
  }
16
19
  },
17
20
  "bin": {
@@ -48,6 +51,7 @@
48
51
  "latest": "yarn upgrade-interactive --latest",
49
52
  "format": "prettier --write '{src,scripts,assets/templates,assets/styles,draft,ideason,scripts_mag2,proto,test,graphai,output,docs/scripts}/**/*.{ts,json,yaml}'",
50
53
  "deep_research": "npx tsx ./src/tools/deep_research.ts",
54
+ "template": "npx tsx batch/template2tsobject.ts && yarn run format",
51
55
  "fake_data": "npx tsx test/fake/sample.ts",
52
56
  "mcp_server": "npx tsx ./src/mcp/server.ts"
53
57
  },
@@ -73,14 +77,14 @@
73
77
  "@tavily/core": "^0.5.9",
74
78
  "canvas": "^3.1.2",
75
79
  "clipboardy": "^4.0.0",
76
- "dotenv": "^17.2.0",
80
+ "dotenv": "^17.2.1",
77
81
  "fluent-ffmpeg": "^2.1.3",
78
82
  "google-auth-library": "^10.1.0",
79
83
  "graphai": "^2.0.13",
80
84
  "inquirer": "^12.7.0",
81
85
  "marked": "^16.1.1",
82
86
  "ora": "^8.2.0",
83
- "puppeteer": "^24.14.0",
87
+ "puppeteer": "^24.15.0",
84
88
  "replicate": "^1.0.1",
85
89
  "yaml": "^2.8.0",
86
90
  "yargs": "^18.0.0",
@@ -93,7 +97,7 @@
93
97
  "@receptron/test_utils": "^2.0.0",
94
98
  "@types/fluent-ffmpeg": "^2.1.26",
95
99
  "@types/yargs": "^17.0.33",
96
- "eslint": "^9.31.0",
100
+ "eslint": "^9.32.0",
97
101
  "eslint-config-prettier": "^10.1.8",
98
102
  "eslint-plugin-prettier": "^5.5.3",
99
103
  "eslint-plugin-sonarjs": "^3.0.4",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$mulmocast": {
3
- "version": "1.0",
3
+ "version": "1.1",
4
4
  "credit": "closing"
5
5
  },
6
6
  "title": "Sample Title",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$mulmocast": {
3
- "version": "1.0",
3
+ "version": "1.1",
4
4
  "credit": "closing"
5
5
  },
6
6
  "title": "桃太郎",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$mulmocast": {
3
- "version": "1.0",
3
+ "version": "1.1",
4
4
  "credit": "closing"
5
5
  },
6
6
  "title": "Sample Title",