mulmocast 2.6.6 → 2.6.7

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.
@@ -1,12 +1,11 @@
1
1
  import dotenv from "dotenv";
2
- import { GraphAI, TaskManager, GraphAILogger } from "graphai";
2
+ import { GraphAI, GraphAILogger } from "graphai";
3
3
  import * as agents from "@graphai/vanilla";
4
4
  import { fileWriteAgent } from "@graphai/vanilla_node_agents";
5
5
  import { ttsOpenaiAgent, ttsGoogleAgent, ttsGeminiAgent, ttsElevenlabsAgent, ttsKotodamaAgent, addBGMAgent, combineAudioFilesAgent, mediaMockAgent, } from "../agents/index.js";
6
- import { text2SpeechProviderSchema } from "../types/index.js";
7
- import { fileCacheAgentFilter } from "../utils/filters.js";
6
+ import { audioGraphOption } from "./graph_option.js";
8
7
  import { getAudioArtifactFilePath, getAudioFilePath, getGroupedAudioFilePath, getOutputStudioFilePath, resolveDirPath, defaultBGMPath, mkdir, writingMessage, } from "../utils/file.js";
9
- import { localizedText, settings2GraphAIConfig } from "../utils/utils.js";
8
+ import { localizedText } from "../utils/utils.js";
10
9
  import { text2hash } from "../utils/utils_node.js";
11
10
  import { provider2TTSAgent } from "../types/provider2agent.js";
12
11
  import { invalidAudioSourceError } from "../utils/error_cause.js";
@@ -210,21 +209,6 @@ export const audio_graph_data = {
210
209
  },
211
210
  },
212
211
  };
213
- const agentFilters = [
214
- {
215
- name: "fileCacheAgentFilter",
216
- agent: fileCacheAgentFilter,
217
- nodeIds: ["tts"],
218
- },
219
- ];
220
- const getConcurrency = (context) => {
221
- // Check if any speaker uses elevenlabs or kotodama (providers that require concurrency = 1)
222
- const hasLimitedConcurrencyProvider = Object.values(context.presentationStyle.speechParams.speakers).some((speaker) => {
223
- const provider = text2SpeechProviderSchema.parse(speaker.provider);
224
- return provider2TTSAgent[provider].hasLimitedConcurrency;
225
- });
226
- return hasLimitedConcurrencyProvider ? 1 : 8;
227
- };
228
212
  const audioAgents = {
229
213
  ...vanillaAgents,
230
214
  fileWriteAgent,
@@ -246,9 +230,8 @@ export const generateBeatAudio = async (index, context, args) => {
246
230
  const audioSegmentDirPath = context.fileDirs.grouped ? audioDirPath : resolveDirPath(audioDirPath, fileName);
247
231
  mkdir(outDirPath);
248
232
  mkdir(audioSegmentDirPath);
249
- const config = settings2GraphAIConfig(settings);
250
- const taskManager = new TaskManager(getConcurrency(context));
251
- const graph = new GraphAI(langs ? graph_tts_map : graph_tts, audioAgents, { agentFilters, taskManager, config });
233
+ const graph = new GraphAI(langs ? graph_tts_map : graph_tts, audioAgents, await audioGraphOption(context, settings));
234
+ callbacks?.forEach((callback) => graph.registerCallback(callback));
252
235
  graph.injectValue("__mapIndex", index);
253
236
  graph.injectValue("beat", context.studio.script.beats[index]);
254
237
  graph.injectValue("studioBeat", context.studio.beats[index]);
@@ -260,11 +243,6 @@ export const generateBeatAudio = async (index, context, args) => {
260
243
  else {
261
244
  graph.injectValue("lang", context.lang);
262
245
  }
263
- if (callbacks) {
264
- callbacks.forEach((callback) => {
265
- graph.registerCallback(callback);
266
- });
267
- }
268
246
  await graph.run();
269
247
  }
270
248
  catch (error) {
@@ -288,19 +266,13 @@ export const audio = async (context, args) => {
288
266
  const outputStudioFilePath = getOutputStudioFilePath(outDirPath, fileName);
289
267
  mkdir(outDirPath);
290
268
  mkdir(audioSegmentDirPath);
291
- const config = settings2GraphAIConfig(settings, process.env);
292
- const taskManager = new TaskManager(getConcurrency(context));
293
- const graph = new GraphAI(audio_graph_data, audioAgents, { agentFilters, taskManager, config });
269
+ const graph = new GraphAI(audio_graph_data, audioAgents, await audioGraphOption(context, settings));
270
+ callbacks?.forEach((callback) => graph.registerCallback(callback));
294
271
  graph.injectValue("context", context);
295
272
  graph.injectValue("audioArtifactFilePath", audioArtifactFilePath);
296
273
  graph.injectValue("audioCombinedFilePath", audioCombinedFilePath);
297
274
  graph.injectValue("outputStudioFilePath", outputStudioFilePath);
298
275
  graph.injectValue("musicFile", MulmoMediaSourceMethods.resolve(context.presentationStyle.audioParams.bgm, context) ?? process.env.PATH_BGM ?? defaultBGMPath());
299
- if (callbacks) {
300
- callbacks.forEach((callback) => {
301
- graph.registerCallback(callback);
302
- });
303
- }
304
276
  const result = await graph.run();
305
277
  writingMessage(audioCombinedFilePath);
306
278
  MulmoStudioContextMethods.setSessionState(context, "audio", false, true);
@@ -1,3 +1,4 @@
1
1
  import type { GraphOptions } from "graphai";
2
2
  import { MulmoStudioContext } from "../types/index.js";
3
- export declare const graphOption: (context: MulmoStudioContext, settings?: Record<string, string>) => Promise<GraphOptions>;
3
+ export declare const imageGraphOption: (context: MulmoStudioContext, settings?: Record<string, string>) => Promise<GraphOptions>;
4
+ export declare const audioGraphOption: (context: MulmoStudioContext, settings?: Record<string, string>) => Promise<GraphOptions>;
@@ -2,17 +2,18 @@ import { TaskManager } from "graphai";
2
2
  import { MulmoPresentationStyleMethods } from "../methods/index.js";
3
3
  import { fileCacheAgentFilter } from "../utils/filters.js";
4
4
  import { settings2GraphAIConfig } from "../utils/utils.js";
5
- export const graphOption = async (context, settings) => {
6
- const options = {
7
- agentFilters: [
8
- {
9
- name: "fileCacheAgentFilter",
10
- agent: fileCacheAgentFilter,
11
- nodeIds: ["imageGenerator", "movieGenerator", "htmlImageAgent", "soundEffectGenerator", "lipSyncGenerator", "AudioTrimmer"],
12
- },
13
- ],
14
- taskManager: new TaskManager(MulmoPresentationStyleMethods.getConcurrency(context.presentationStyle)),
15
- config: settings2GraphAIConfig(settings, process.env),
16
- };
17
- return options;
18
- };
5
+ const createGraphOption = (concurrency, cacheNodeIds, settings) => ({
6
+ agentFilters: [
7
+ {
8
+ name: "fileCacheAgentFilter",
9
+ agent: fileCacheAgentFilter,
10
+ nodeIds: cacheNodeIds,
11
+ },
12
+ ],
13
+ taskManager: new TaskManager(concurrency),
14
+ config: settings2GraphAIConfig(settings, process.env),
15
+ });
16
+ const IMAGE_CACHE_NODE_IDS = ["imageGenerator", "movieGenerator", "htmlImageAgent", "soundEffectGenerator", "lipSyncGenerator", "AudioTrimmer"];
17
+ const AUDIO_CACHE_NODE_IDS = ["tts"];
18
+ export const imageGraphOption = async (context, settings) => createGraphOption(MulmoPresentationStyleMethods.getImageConcurrency(context.presentationStyle), IMAGE_CACHE_NODE_IDS, settings);
19
+ export const audioGraphOption = async (context, settings) => createGraphOption(MulmoPresentationStyleMethods.getAudioConcurrency(context.presentationStyle), AUDIO_CACHE_NODE_IDS, settings);
@@ -1,6 +1,6 @@
1
1
  import { GraphAI, GraphAILogger } from "graphai";
2
2
  import { getReferenceImagePath } from "../utils/file.js";
3
- import { graphOption } from "./graph_option.js";
3
+ import { imageGraphOption } from "./graph_option.js";
4
4
  import { MulmoPresentationStyleMethods, MulmoMediaSourceMethods } from "../methods/index.js";
5
5
  import { imageOpenaiAgent, mediaMockAgent, imageGenAIAgent, imageReplicateAgent, movieGenAIAgent, movieReplicateAgent } from "../agents/index.js";
6
6
  import { agentGenerationError, imageReferenceAction, imageFileTarget, movieFileTarget } from "../utils/error_cause.js";
@@ -41,7 +41,7 @@ export const generateReferenceImage = async (inputs) => {
41
41
  },
42
42
  };
43
43
  try {
44
- const options = await graphOption(context);
44
+ const options = await imageGraphOption(context);
45
45
  const graph = new GraphAI(image_graph_data, { imageGenAIAgent, imageOpenaiAgent, mediaMockAgent, imageReplicateAgent }, options);
46
46
  await graph.run();
47
47
  return imagePath;
@@ -126,7 +126,7 @@ const generateReferenceMovie = async (inputs) => {
126
126
  },
127
127
  };
128
128
  try {
129
- const options = await graphOption(context);
129
+ const options = await imageGraphOption(context);
130
130
  const graph = new GraphAI(movie_graph_data, { movieGenAIAgent, movieReplicateAgent, mediaMockAgent }, options);
131
131
  await graph.run();
132
132
  return moviePath;
@@ -463,7 +463,7 @@ export declare const beat_graph_data: {
463
463
  };
464
464
  };
465
465
  export declare const images_graph_data: GraphData;
466
- export { graphOption } from "./graph_option.js";
466
+ export { imageGraphOption } from "./graph_option.js";
467
467
  type ImageOptions = {
468
468
  imageAgents: Record<string, unknown>;
469
469
  };
@@ -14,7 +14,7 @@ import { audioCheckerError } from "../utils/error_cause.js";
14
14
  import { extractImageFromMovie, ffmpegGetMediaDuration, trimMusic } from "../utils/ffmpeg_utils.js";
15
15
  import { getMediaRefs, resolveBeatLocalRefs } from "./image_references.js";
16
16
  import { imagePreprocessAgent, imagePluginAgent, htmlImageGeneratorAgent } from "./image_agents.js";
17
- import { graphOption } from "./graph_option.js";
17
+ import { imageGraphOption } from "./graph_option.js";
18
18
  const vanillaAgents = vanilla.default ?? vanilla;
19
19
  const imageAgents = {
20
20
  imageGenAIAgent,
@@ -431,8 +431,7 @@ export const images_graph_data = {
431
431
  },
432
432
  },
433
433
  };
434
- // graphOption moved to graph_option.ts to break circular dependency with image_references.ts
435
- export { graphOption } from "./graph_option.js";
434
+ export { imageGraphOption } from "./graph_option.js";
436
435
  const prepareGenerateImages = async (context) => {
437
436
  const fileName = MulmoStudioContextMethods.getFileName(context);
438
437
  const imageProjectDirPath = MulmoStudioContextMethods.getImageProjectDirPath(context);
@@ -459,7 +458,7 @@ const generateImages = async (context, args) => {
459
458
  ...defaultAgents,
460
459
  ...optionImageAgents,
461
460
  };
462
- const graph = new GraphAI(images_graph_data, graphaiAgent, await graphOption(context, settings));
461
+ const graph = new GraphAI(images_graph_data, graphaiAgent, await imageGraphOption(context, settings));
463
462
  Object.keys(injections).forEach((key) => {
464
463
  graph.injectValue(key, injections[key]);
465
464
  });
@@ -499,7 +498,7 @@ export const generateBeatImage = async (inputs) => {
499
498
  try {
500
499
  const { index, context, args } = inputs;
501
500
  const { settings, callbacks, forceMovie, forceImage, forceLipSync, forceSoundEffect, withBackup } = args ?? {};
502
- const options = await graphOption(context, settings);
501
+ const options = await imageGraphOption(context, settings);
503
502
  const injections = await prepareGenerateImages(context);
504
503
  const graph = new GraphAI(beat_graph_data, defaultAgents, options);
505
504
  Object.keys(injections).forEach((key) => {
@@ -179,6 +179,7 @@ export declare const MulmoPresentationStyleMethods: {
179
179
  imageName: string;
180
180
  referenceType: "ASSET" | "STYLE";
181
181
  }[] | undefined;
182
+ concurrency?: number | undefined;
182
183
  speed?: number | undefined;
183
184
  };
184
185
  keyName: string;
@@ -204,7 +205,10 @@ export declare const MulmoPresentationStyleMethods: {
204
205
  image?: string;
205
206
  }>;
206
207
  };
207
- getConcurrency(presentationStyle: MulmoPresentationStyle): 4 | 16;
208
+ /** Concurrency for image/movie generation graph (uses min of imageParams/movieParams) */
209
+ getImageConcurrency(presentationStyle: MulmoPresentationStyle): number;
210
+ /** Concurrency for audio/TTS generation graph */
211
+ getAudioConcurrency(presentationStyle: MulmoPresentationStyle): number;
208
212
  getHtmlImageAgentInfo(presentationStyle: MulmoPresentationStyle): Text2HtmlAgentInfo;
209
213
  getImageType(_: MulmoPresentationStyle, beat: MulmoBeat): BeatMediaType;
210
214
  };
@@ -6,10 +6,10 @@
6
6
  import { isNull } from "graphai";
7
7
  import { userAssert } from "../utils/utils.js";
8
8
  import { text2ImageProviderSchema, text2HtmlImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoCanvasDimensionSchema, mulmoTransitionSchema, } from "../types/schema.js";
9
- import { provider2ImageAgent, provider2MovieAgent, provider2LLMAgent, provider2SoundEffectAgent, provider2LipSyncAgent, defaultProviders, } from "../types/provider2agent.js";
9
+ import { provider2ImageAgent, provider2MovieAgent, provider2LLMAgent, provider2TTSAgent, provider2SoundEffectAgent, provider2LipSyncAgent, defaultProviders, } from "../types/provider2agent.js";
10
10
  const defaultTextSlideStyles = [
11
11
  '*,*::before,*::after{box-sizing:border-box}body,h1,h2,h3,h4,p,figure,blockquote,dl,dd{margin:0}ul[role="list"],ol[role="list"]{list-style:none}html:focus-within{scroll-behavior:smooth}body{min-height:100vh;text-rendering:optimizeSpeed;line-height:1.5}a:not([class]){text-decoration-skip-ink:auto}img,picture{max-width:100%;display:block}input,button,textarea,select{font:inherit}@media(prefers-reduced-motion:reduce){html:focus-within{scroll-behavior:auto}*,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important;scroll-behavior:auto !important}}',
12
- "body { margin: 60px; margin-top: 40px; color:#333; font-size: 30px; font-family: Arial, sans-serif; box-sizing: border-box; height: 100vh }",
12
+ "body { margin: 60px; margin-top: 40px; color:#333; background-color:#fff; font-size: 30px; font-family: Arial, sans-serif; box-sizing: border-box; height: 100vh }",
13
13
  "h1 { font-size: 56px; margin-bottom: 20px; text-align: center }",
14
14
  "h2 { font-size: 48px; text-align: center }",
15
15
  "h3 { font-size: 36px }",
@@ -119,7 +119,17 @@ export const MulmoPresentationStyleMethods = {
119
119
  const agentInfo = provider2LipSyncAgent[lipSyncProvider];
120
120
  return agentInfo;
121
121
  },
122
- getConcurrency(presentationStyle) {
122
+ /** Concurrency for image/movie generation graph (uses min of imageParams/movieParams) */
123
+ getImageConcurrency(presentationStyle) {
124
+ const imageConcurrency = presentationStyle.imageParams?.concurrency;
125
+ const movieConcurrency = presentationStyle.movieParams?.concurrency;
126
+ // User-specified concurrency takes precedence.
127
+ // Use the smaller of imageParams/movieParams since they share the same graph.
128
+ if (imageConcurrency !== undefined || movieConcurrency !== undefined) {
129
+ const values = [imageConcurrency, movieConcurrency].filter((v) => v !== undefined);
130
+ return Math.min(...values);
131
+ }
132
+ // Fallback: provider-based auto-detection
123
133
  const imageAgentInfo = MulmoPresentationStyleMethods.getImageAgentInfo(presentationStyle);
124
134
  if (imageAgentInfo.imageParams.provider === "openai") {
125
135
  // NOTE: Here are the rate limits of OpenAI's text2image API (1token = 32x32 patch).
@@ -131,6 +141,20 @@ export const MulmoPresentationStyleMethods = {
131
141
  }
132
142
  return 4;
133
143
  },
144
+ /** Concurrency for audio/TTS generation graph */
145
+ getAudioConcurrency(presentationStyle) {
146
+ // User-specified concurrency takes precedence
147
+ const userConcurrency = presentationStyle.audioParams?.concurrency;
148
+ if (userConcurrency !== undefined) {
149
+ return userConcurrency;
150
+ }
151
+ // Fallback: provider-based auto-detection
152
+ const hasLimitedConcurrencyProvider = Object.values(presentationStyle.speechParams.speakers).some((speaker) => {
153
+ const provider = text2SpeechProviderSchema.parse(speaker.provider);
154
+ return provider2TTSAgent[provider].hasLimitedConcurrency;
155
+ });
156
+ return hasLimitedConcurrencyProvider ? 1 : 8;
157
+ },
134
158
  getHtmlImageAgentInfo(presentationStyle) {
135
159
  const provider = text2HtmlImageProviderSchema.parse(presentationStyle.htmlImageParams?.provider);
136
160
  const defaultConfig = provider2LLMAgent[provider];
@@ -3299,6 +3299,7 @@ export declare const mulmoImageParamsSchema: z.ZodObject<{
3299
3299
  }>>;
3300
3300
  opacity: z.ZodOptional<z.ZodNumber>;
3301
3301
  }, z.core.$strip>]>>>;
3302
+ concurrency: z.ZodOptional<z.ZodNumber>;
3302
3303
  }, z.core.$strict>;
3303
3304
  export declare const textSlideParamsSchema: z.ZodObject<{
3304
3305
  cssStyles: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
@@ -3398,6 +3399,7 @@ export declare const audioParamsSchema: z.ZodObject<{
3398
3399
  ducking: z.ZodOptional<z.ZodObject<{
3399
3400
  ratio: z.ZodOptional<z.ZodNumber>;
3400
3401
  }, z.core.$strip>>;
3402
+ concurrency: z.ZodOptional<z.ZodNumber>;
3401
3403
  }, z.core.$strict>;
3402
3404
  export declare const htmlPromptParamsSchema: z.ZodObject<{
3403
3405
  systemPrompt: z.ZodDefault<z.ZodOptional<z.ZodString>>;
@@ -3688,6 +3690,7 @@ export declare const mulmoMovieParamsSchema: z.ZodObject<{
3688
3690
  STYLE: "STYLE";
3689
3691
  }>;
3690
3692
  }, z.core.$strip>>>;
3693
+ concurrency: z.ZodOptional<z.ZodNumber>;
3691
3694
  }, z.core.$strip>;
3692
3695
  export declare const mulmoBeatSchema: z.ZodObject<{
3693
3696
  speaker: z.ZodOptional<z.ZodString>;
@@ -6581,6 +6584,7 @@ export declare const mulmoBeatSchema: z.ZodObject<{
6581
6584
  STYLE: "STYLE";
6582
6585
  }>;
6583
6586
  }, z.core.$strip>>>;
6587
+ concurrency: z.ZodOptional<z.ZodNumber>;
6584
6588
  speed: z.ZodOptional<z.ZodNumber>;
6585
6589
  }, z.core.$strip>>;
6586
6590
  soundEffectParams: z.ZodOptional<z.ZodObject<{
@@ -6829,6 +6833,7 @@ export declare const mulmoPresentationStyleSchema: z.ZodObject<{
6829
6833
  }>>;
6830
6834
  opacity: z.ZodOptional<z.ZodNumber>;
6831
6835
  }, z.core.$strip>]>>>;
6836
+ concurrency: z.ZodOptional<z.ZodNumber>;
6832
6837
  }, z.core.$strict>>>;
6833
6838
  movieParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
6834
6839
  provider: z.ZodOptional<z.ZodEnum<{
@@ -7068,6 +7073,7 @@ export declare const mulmoPresentationStyleSchema: z.ZodObject<{
7068
7073
  STYLE: "STYLE";
7069
7074
  }>;
7070
7075
  }, z.core.$strip>>>;
7076
+ concurrency: z.ZodOptional<z.ZodNumber>;
7071
7077
  }, z.core.$strip>>>;
7072
7078
  soundEffectParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
7073
7079
  provider: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
@@ -7191,6 +7197,7 @@ export declare const mulmoPresentationStyleSchema: z.ZodObject<{
7191
7197
  ducking: z.ZodOptional<z.ZodObject<{
7192
7198
  ratio: z.ZodOptional<z.ZodNumber>;
7193
7199
  }, z.core.$strip>>;
7200
+ concurrency: z.ZodOptional<z.ZodNumber>;
7194
7201
  }, z.core.$strict>>;
7195
7202
  }, z.core.$strip>;
7196
7203
  export declare const mulmoReferenceSchema: z.ZodObject<{
@@ -7330,6 +7337,7 @@ export declare const mulmoScriptSchema: z.ZodObject<{
7330
7337
  }>>;
7331
7338
  opacity: z.ZodOptional<z.ZodNumber>;
7332
7339
  }, z.core.$strip>]>>>;
7340
+ concurrency: z.ZodOptional<z.ZodNumber>;
7333
7341
  }, z.core.$strict>>>;
7334
7342
  movieParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
7335
7343
  provider: z.ZodOptional<z.ZodEnum<{
@@ -7569,6 +7577,7 @@ export declare const mulmoScriptSchema: z.ZodObject<{
7569
7577
  STYLE: "STYLE";
7570
7578
  }>;
7571
7579
  }, z.core.$strip>>>;
7580
+ concurrency: z.ZodOptional<z.ZodNumber>;
7572
7581
  }, z.core.$strip>>>;
7573
7582
  soundEffectParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
7574
7583
  provider: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
@@ -7692,6 +7701,7 @@ export declare const mulmoScriptSchema: z.ZodObject<{
7692
7701
  ducking: z.ZodOptional<z.ZodObject<{
7693
7702
  ratio: z.ZodOptional<z.ZodNumber>;
7694
7703
  }, z.core.$strip>>;
7704
+ concurrency: z.ZodOptional<z.ZodNumber>;
7695
7705
  }, z.core.$strict>>;
7696
7706
  title: z.ZodOptional<z.ZodString>;
7697
7707
  description: z.ZodOptional<z.ZodString>;
@@ -10600,6 +10610,7 @@ export declare const mulmoScriptSchema: z.ZodObject<{
10600
10610
  STYLE: "STYLE";
10601
10611
  }>;
10602
10612
  }, z.core.$strip>>>;
10613
+ concurrency: z.ZodOptional<z.ZodNumber>;
10603
10614
  speed: z.ZodOptional<z.ZodNumber>;
10604
10615
  }, z.core.$strip>>;
10605
10616
  soundEffectParams: z.ZodOptional<z.ZodObject<{
@@ -10923,6 +10934,7 @@ export declare const mulmoStudioSchema: z.ZodObject<{
10923
10934
  }>>;
10924
10935
  opacity: z.ZodOptional<z.ZodNumber>;
10925
10936
  }, z.core.$strip>]>>>;
10937
+ concurrency: z.ZodOptional<z.ZodNumber>;
10926
10938
  }, z.core.$strict>>>;
10927
10939
  movieParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
10928
10940
  provider: z.ZodOptional<z.ZodEnum<{
@@ -11162,6 +11174,7 @@ export declare const mulmoStudioSchema: z.ZodObject<{
11162
11174
  STYLE: "STYLE";
11163
11175
  }>;
11164
11176
  }, z.core.$strip>>>;
11177
+ concurrency: z.ZodOptional<z.ZodNumber>;
11165
11178
  }, z.core.$strip>>>;
11166
11179
  soundEffectParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
11167
11180
  provider: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
@@ -11285,6 +11298,7 @@ export declare const mulmoStudioSchema: z.ZodObject<{
11285
11298
  ducking: z.ZodOptional<z.ZodObject<{
11286
11299
  ratio: z.ZodOptional<z.ZodNumber>;
11287
11300
  }, z.core.$strip>>;
11301
+ concurrency: z.ZodOptional<z.ZodNumber>;
11288
11302
  }, z.core.$strict>>;
11289
11303
  title: z.ZodOptional<z.ZodString>;
11290
11304
  description: z.ZodOptional<z.ZodString>;
@@ -14193,6 +14207,7 @@ export declare const mulmoStudioSchema: z.ZodObject<{
14193
14207
  STYLE: "STYLE";
14194
14208
  }>;
14195
14209
  }, z.core.$strip>>>;
14210
+ concurrency: z.ZodOptional<z.ZodNumber>;
14196
14211
  speed: z.ZodOptional<z.ZodNumber>;
14197
14212
  }, z.core.$strip>>;
14198
14213
  soundEffectParams: z.ZodOptional<z.ZodObject<{
@@ -14452,6 +14467,7 @@ export declare const mulmoPromptTemplateSchema: z.ZodObject<{
14452
14467
  }>>;
14453
14468
  opacity: z.ZodOptional<z.ZodNumber>;
14454
14469
  }, z.core.$strip>]>>>;
14470
+ concurrency: z.ZodOptional<z.ZodNumber>;
14455
14471
  }, z.core.$strict>>>;
14456
14472
  movieParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
14457
14473
  provider: z.ZodOptional<z.ZodEnum<{
@@ -14691,6 +14707,7 @@ export declare const mulmoPromptTemplateSchema: z.ZodObject<{
14691
14707
  STYLE: "STYLE";
14692
14708
  }>;
14693
14709
  }, z.core.$strip>>>;
14710
+ concurrency: z.ZodOptional<z.ZodNumber>;
14694
14711
  }, z.core.$strip>>>;
14695
14712
  soundEffectParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
14696
14713
  provider: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
@@ -14814,6 +14831,7 @@ export declare const mulmoPromptTemplateSchema: z.ZodObject<{
14814
14831
  ducking: z.ZodOptional<z.ZodObject<{
14815
14832
  ratio: z.ZodOptional<z.ZodNumber>;
14816
14833
  }, z.core.$strip>>;
14834
+ concurrency: z.ZodOptional<z.ZodNumber>;
14817
14835
  }, z.core.$strict>>;
14818
14836
  }, z.core.$strip>>;
14819
14837
  }, z.core.$strict>;
@@ -14947,6 +14965,7 @@ export declare const mulmoPromptTemplateFileSchema: z.ZodObject<{
14947
14965
  }>>;
14948
14966
  opacity: z.ZodOptional<z.ZodNumber>;
14949
14967
  }, z.core.$strip>]>>>;
14968
+ concurrency: z.ZodOptional<z.ZodNumber>;
14950
14969
  }, z.core.$strict>>>;
14951
14970
  movieParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
14952
14971
  provider: z.ZodOptional<z.ZodEnum<{
@@ -15186,6 +15205,7 @@ export declare const mulmoPromptTemplateFileSchema: z.ZodObject<{
15186
15205
  STYLE: "STYLE";
15187
15206
  }>;
15188
15207
  }, z.core.$strip>>>;
15208
+ concurrency: z.ZodOptional<z.ZodNumber>;
15189
15209
  }, z.core.$strip>>>;
15190
15210
  soundEffectParams: z.ZodDefault<z.ZodOptional<z.ZodObject<{
15191
15211
  provider: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
@@ -15309,6 +15329,7 @@ export declare const mulmoPromptTemplateFileSchema: z.ZodObject<{
15309
15329
  ducking: z.ZodOptional<z.ZodObject<{
15310
15330
  ratio: z.ZodOptional<z.ZodNumber>;
15311
15331
  }, z.core.$strip>>;
15332
+ concurrency: z.ZodOptional<z.ZodNumber>;
15312
15333
  }, z.core.$strict>>;
15313
15334
  }, z.core.$strip>>;
15314
15335
  filename: z.ZodString;
@@ -393,6 +393,7 @@ export const mulmoImageParamsSchema = mulmoBeatImageParamsSchema
393
393
  .extend({
394
394
  images: mulmoImageParamsImagesSchema.optional(),
395
395
  backgroundImage: backgroundImageSchema,
396
+ concurrency: z.number().int().positive().optional().describe("Max concurrent image generation requests"),
396
397
  })
397
398
  .strict();
398
399
  export const textSlideParamsSchema = z
@@ -436,6 +437,7 @@ export const audioParamsSchema = z
436
437
  })
437
438
  .optional()
438
439
  .describe("Auto-reduce movie audio when TTS is playing"),
440
+ concurrency: z.number().int().positive().optional().describe("Max concurrent TTS generation requests"),
439
441
  })
440
442
  .strict();
441
443
  export const htmlPromptParamsSchema = z
@@ -496,6 +498,7 @@ export const mulmoMovieParamsSchema = z.object({
496
498
  .array(movieReferenceImageSchema)
497
499
  .optional()
498
500
  .describe("Style/asset reference images (Veo 3.1). Mutually exclusive with imageName/lastFrameImageName"),
501
+ concurrency: z.number().int().positive().optional().describe("Max concurrent movie generation requests"),
499
502
  });
500
503
  export const mulmoBeatSchema = z
501
504
  .object({
@@ -115,6 +115,7 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
115
115
  size?: "contain" | "cover" | "fill" | "auto" | undefined;
116
116
  opacity?: number | undefined;
117
117
  } | null | undefined;
118
+ concurrency?: number | undefined;
118
119
  };
119
120
  movieParams: {
120
121
  provider?: string | undefined;
@@ -280,6 +281,7 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
280
281
  imageName: string;
281
282
  referenceType: "ASSET" | "STYLE";
282
283
  }[] | undefined;
284
+ concurrency?: number | undefined;
283
285
  };
284
286
  soundEffectParams: {
285
287
  provider?: string | undefined;
@@ -308,6 +310,7 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
308
310
  ducking?: {
309
311
  ratio?: number | undefined;
310
312
  } | undefined;
313
+ concurrency?: number | undefined;
311
314
  };
312
315
  lang: string;
313
316
  beats: {
@@ -2018,6 +2021,7 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
2018
2021
  imageName: string;
2019
2022
  referenceType: "ASSET" | "STYLE";
2020
2023
  }[] | undefined;
2024
+ concurrency?: number | undefined;
2021
2025
  speed?: number | undefined;
2022
2026
  } | undefined;
2023
2027
  soundEffectParams?: {
@@ -2347,6 +2351,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
2347
2351
  size?: "contain" | "cover" | "fill" | "auto" | undefined;
2348
2352
  opacity?: number | undefined;
2349
2353
  } | null | undefined;
2354
+ concurrency?: number | undefined;
2350
2355
  };
2351
2356
  movieParams: {
2352
2357
  provider?: string | undefined;
@@ -2512,6 +2517,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
2512
2517
  imageName: string;
2513
2518
  referenceType: "ASSET" | "STYLE";
2514
2519
  }[] | undefined;
2520
+ concurrency?: number | undefined;
2515
2521
  };
2516
2522
  soundEffectParams: {
2517
2523
  provider?: string | undefined;
@@ -2540,6 +2546,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
2540
2546
  ducking?: {
2541
2547
  ratio?: number | undefined;
2542
2548
  } | undefined;
2549
+ concurrency?: number | undefined;
2543
2550
  };
2544
2551
  lang: string;
2545
2552
  beats: {
@@ -4250,6 +4257,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
4250
4257
  imageName: string;
4251
4258
  referenceType: "ASSET" | "STYLE";
4252
4259
  }[] | undefined;
4260
+ concurrency?: number | undefined;
4253
4261
  speed?: number | undefined;
4254
4262
  } | undefined;
4255
4263
  soundEffectParams?: {
@@ -4586,6 +4594,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
4586
4594
  size?: "contain" | "cover" | "fill" | "auto" | undefined;
4587
4595
  opacity?: number | undefined;
4588
4596
  } | null | undefined;
4597
+ concurrency?: number | undefined;
4589
4598
  };
4590
4599
  movieParams: {
4591
4600
  provider?: string | undefined;
@@ -4751,6 +4760,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
4751
4760
  imageName: string;
4752
4761
  referenceType: "ASSET" | "STYLE";
4753
4762
  }[] | undefined;
4763
+ concurrency?: number | undefined;
4754
4764
  };
4755
4765
  soundEffectParams: {
4756
4766
  provider?: string | undefined;
@@ -4779,6 +4789,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
4779
4789
  ducking?: {
4780
4790
  ratio?: number | undefined;
4781
4791
  } | undefined;
4792
+ concurrency?: number | undefined;
4782
4793
  };
4783
4794
  lipSyncParams?: {
4784
4795
  provider?: string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast",
3
- "version": "2.6.6",
3
+ "version": "2.6.7",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.node.js",
@@ -24,8 +24,9 @@
24
24
  }
25
25
  },
26
26
  "resolutions": {
27
- "minimatch": "^10.2.4",
28
- "yauzl": "^3.2.1"
27
+ "minimatch": "^10.2.5",
28
+ "tar": "7.5.13",
29
+ "yauzl": "^3.3.0"
29
30
  },
30
31
  "bin": {
31
32
  "mulmo": "lib/cli/bin.js",
@@ -88,7 +89,7 @@
88
89
  "homepage": "https://github.com/receptron/mulmocast-cli#readme",
89
90
  "dependencies": {
90
91
  "@google-cloud/text-to-speech": "^6.4.0",
91
- "@google/genai": "^1.48.0",
92
+ "@google/genai": "^1.49.0",
92
93
  "@graphai/anthropic_agent": "^2.0.12",
93
94
  "@graphai/browserless_agent": "^2.0.2",
94
95
  "@graphai/gemini_agent": "^2.0.5",
@@ -98,18 +99,18 @@
98
99
  "@graphai/stream_agent_filter": "^2.0.3",
99
100
  "@graphai/vanilla": "^2.0.12",
100
101
  "@graphai/vanilla_node_agents": "^2.0.4",
101
- "@inquirer/input": "^5.0.10",
102
- "@inquirer/select": "^5.1.2",
102
+ "@inquirer/input": "^5.0.11",
103
+ "@inquirer/select": "^5.1.3",
103
104
  "@modelcontextprotocol/sdk": "^1.29.0",
104
105
  "@mozilla/readability": "^0.6.0",
105
106
  "@tavily/core": "^0.5.11",
106
107
  "archiver": "^7.0.1",
107
108
  "clipboardy": "^5.3.1",
108
- "dotenv": "^17.4.0",
109
+ "dotenv": "^17.4.2",
109
110
  "fluent-ffmpeg": "^2.1.3",
110
111
  "graphai": "^2.0.16",
111
- "jsdom": "^29.0.1",
112
- "marked": "^17.0.5",
112
+ "jsdom": "^29.0.2",
113
+ "marked": "^18.0.0",
113
114
  "mulmocast-vision": "^1.0.9",
114
115
  "ora": "^9.3.0",
115
116
  "puppeteer": "^24.40.0",
@@ -126,16 +127,16 @@
126
127
  "@types/jsdom": "^28.0.1",
127
128
  "@types/yargs": "^17.0.35",
128
129
  "cross-env": "^10.1.0",
129
- "eslint": "^10.1.0",
130
+ "eslint": "^10.2.0",
130
131
  "eslint-config-prettier": "^10.1.8",
131
132
  "eslint-plugin-import": "^2.32.0",
132
133
  "eslint-plugin-prettier": "^5.5.5",
133
134
  "eslint-plugin-sonarjs": "^4.0.2",
134
- "globals": "^17.4.0",
135
- "prettier": "^3.8.1",
135
+ "globals": "^17.5.0",
136
+ "prettier": "^3.8.2",
136
137
  "tsx": "^4.21.0",
137
138
  "typescript": "6.0.2",
138
- "typescript-eslint": "^8.58.0"
139
+ "typescript-eslint": "^8.58.1"
139
140
  },
140
141
  "engines": {
141
142
  "node": ">=22.0.0"