mulmocast 1.2.68 → 1.3.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.
@@ -21,6 +21,9 @@ export declare const beat_graph_data: {
21
21
  forceSoundEffect: {
22
22
  value: boolean;
23
23
  };
24
+ withBackup: {
25
+ value: boolean;
26
+ };
24
27
  preprocessor: {
25
28
  agent: (namedInputs: {
26
29
  context: MulmoStudioContext;
@@ -181,6 +184,7 @@ export declare const beat_graph_data: {
181
184
  };
182
185
  cache: {
183
186
  force: string[];
187
+ withBackup: string[];
184
188
  file: string;
185
189
  index: string;
186
190
  id: string;
@@ -229,6 +233,7 @@ export declare const beat_graph_data: {
229
233
  referenceImages: string;
230
234
  cache: {
231
235
  force: string[];
236
+ withBackup: string[];
232
237
  file: string;
233
238
  index: string;
234
239
  id: string;
@@ -255,6 +260,7 @@ export declare const beat_graph_data: {
255
260
  movieFile: string;
256
261
  cache: {
257
262
  force: string[];
263
+ withBackup: string[];
258
264
  file: string;
259
265
  index: string;
260
266
  id: string;
@@ -313,6 +319,7 @@ export declare const beat_graph_data: {
313
319
  };
314
320
  cache: {
315
321
  force: string[];
322
+ withBackup: string[];
316
323
  file: string;
317
324
  index: string;
318
325
  id: string;
@@ -363,6 +370,7 @@ export declare const beat_graph_data: {
363
370
  };
364
371
  cache: {
365
372
  force: string[];
373
+ withBackup: string[];
366
374
  file: string;
367
375
  index: string;
368
376
  id: string;
@@ -415,6 +423,7 @@ export declare const generateBeatImage: (inputs: {
415
423
  forceImage?: boolean;
416
424
  forceLipSync?: boolean;
417
425
  forceSoundEffect?: boolean;
426
+ withBackup?: boolean;
418
427
  };
419
428
  }) => Promise<void>;
420
429
  export {};
@@ -58,6 +58,7 @@ export const beat_graph_data = {
58
58
  forceImage: { value: false },
59
59
  forceLipSync: { value: false },
60
60
  forceSoundEffect: { value: false },
61
+ withBackup: { value: false },
61
62
  preprocessor: {
62
63
  agent: imagePreprocessAgent,
63
64
  inputs: {
@@ -92,6 +93,7 @@ export const beat_graph_data = {
92
93
  },
93
94
  cache: {
94
95
  force: [":context.force", ":forceImage"],
96
+ withBackup: [":context.backup", ":withBackup"],
95
97
  file: ":preprocessor.htmlPath",
96
98
  index: ":__mapIndex",
97
99
  id: ":beat.id",
@@ -135,6 +137,7 @@ export const beat_graph_data = {
135
137
  referenceImages: ":preprocessor.referenceImages",
136
138
  cache: {
137
139
  force: [":context.force", ":forceImage"],
140
+ withBackup: [":context.backup", ":withBackup"],
138
141
  file: ":preprocessor.imagePath",
139
142
  index: ":__mapIndex",
140
143
  id: ":beat.id",
@@ -151,7 +154,7 @@ export const beat_graph_data = {
151
154
  defaultValue: {},
152
155
  },
153
156
  movieGenerator: {
154
- if: ":preprocessor.movieFile",
157
+ if: ":beat.moviePrompt",
155
158
  agent: ":preprocessor.movieAgentInfo.agent",
156
159
  inputs: {
157
160
  media: "movie",
@@ -161,6 +164,7 @@ export const beat_graph_data = {
161
164
  movieFile: ":preprocessor.movieFile", // for google genai agent
162
165
  cache: {
163
166
  force: [":context.force", ":forceMovie"],
167
+ withBackup: [":context.backup", ":withBackup"],
164
168
  file: ":preprocessor.movieFile",
165
169
  index: ":__mapIndex",
166
170
  id: ":beat.id",
@@ -231,6 +235,7 @@ export const beat_graph_data = {
231
235
  },
232
236
  cache: {
233
237
  force: [":context.force", ":forceSoundEffect"],
238
+ withBackup: [":context.backup", ":withBackup"],
234
239
  file: ":preprocessor.soundEffectFile",
235
240
  index: ":__mapIndex",
236
241
  id: ":beat.id",
@@ -278,6 +283,7 @@ export const beat_graph_data = {
278
283
  },
279
284
  cache: {
280
285
  force: [":context.force", ":forceLipSync"],
286
+ withBackup: [":context.backup", ":withBackup"],
281
287
  file: ":preprocessor.lipSyncFile",
282
288
  index: ":__mapIndex",
283
289
  id: ":beat.id",
@@ -481,7 +487,7 @@ export const images = async (context, args) => {
481
487
  export const generateBeatImage = async (inputs) => {
482
488
  try {
483
489
  const { index, context, args } = inputs;
484
- const { settings, callbacks, forceMovie, forceImage, forceLipSync, forceSoundEffect } = args ?? {};
490
+ const { settings, callbacks, forceMovie, forceImage, forceLipSync, forceSoundEffect, withBackup } = args ?? {};
485
491
  const options = await graphOption(context, settings);
486
492
  const injections = await prepareGenerateImages(context);
487
493
  const graph = new GraphAI(beat_graph_data, defaultAgents, options);
@@ -496,6 +502,7 @@ export const generateBeatImage = async (inputs) => {
496
502
  graph.injectValue("forceImage", forceImage ?? false);
497
503
  graph.injectValue("forceLipSync", forceLipSync ?? false);
498
504
  graph.injectValue("forceSoundEffect", forceSoundEffect ?? false);
505
+ graph.injectValue("withBackup", withBackup ?? false);
499
506
  if (callbacks) {
500
507
  callbacks.forEach((callback) => {
501
508
  graph.registerCallback(callback);
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<import("yargs").Omit<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const commonOptions: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ backup: boolean;
10
12
  } & {
11
13
  p: string | undefined;
12
14
  } & {
package/lib/cli/common.js CHANGED
@@ -25,6 +25,11 @@ export const commonOptions = (yargs) => {
25
25
  describe: "Force regenerate",
26
26
  type: "boolean",
27
27
  default: false,
28
+ })
29
+ .option("backup", {
30
+ describe: "create backup media file",
31
+ type: "boolean",
32
+ default: false,
28
33
  })
29
34
  .option("p", {
30
35
  alias: "presentationStyle",
@@ -83,5 +83,5 @@ export const initializeContext = async (argv, raiseError = false) => {
83
83
  file: argv.file ?? "",
84
84
  });
85
85
  setGraphAILogger(Boolean(argv.v), { files });
86
- return await initializeContextFromFiles(files, raiseError, Boolean(argv.f), argv.c, argv.l);
86
+ return await initializeContextFromFiles(files, raiseError, Boolean(argv.f), Boolean(argv.backup), argv.c, argv.l);
87
87
  };
@@ -313,7 +313,7 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
313
313
  export declare const fetchScript: (isHttpPath: boolean, mulmoFilePath: string, fileOrUrl: string) => Promise<MulmoScript | null>;
314
314
  export declare const getMultiLingual: (multilingualFilePath: string, beats: MulmoStudioBeat[]) => MulmoStudioMultiLingual;
315
315
  export declare const getPresentationStyle: (presentationStylePath: string | undefined) => MulmoPresentationStyle | null;
316
- export declare const initializeContextFromFiles: (files: FileObject, raiseError: boolean, force?: boolean, captionLang?: string, targetLang?: string, index?: number) => Promise<{
316
+ export declare const initializeContextFromFiles: (files: FileObject, raiseError: boolean, force?: boolean, withBackup?: boolean, captionLang?: string, targetLang?: string, index?: number) => Promise<{
317
317
  studio: {
318
318
  beats: {
319
319
  duration?: number | undefined;
@@ -767,5 +767,6 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
767
767
  };
768
768
  };
769
769
  force: boolean;
770
+ backup: boolean;
770
771
  lang: string;
771
772
  } | null>;
@@ -112,7 +112,7 @@ export const getPresentationStyle = (presentationStylePath) => {
112
112
  const jsonData = readMulmoScriptFile(presentationStylePath, "ERROR: File does not exist " + presentationStylePath)?.mulmoData ?? null;
113
113
  return mulmoPresentationStyleSchema.parse(jsonData);
114
114
  };
115
- export const initializeContextFromFiles = async (files, raiseError, force, captionLang, targetLang, index) => {
115
+ export const initializeContextFromFiles = async (files, raiseError, force, withBackup, captionLang, targetLang, index) => {
116
116
  const { fileName, isHttpPath, fileOrUrl, mulmoFilePath, presentationStylePath, outputMultilingualFilePath } = files;
117
117
  const mulmoScript = await fetchScript(isHttpPath, mulmoFilePath, fileOrUrl);
118
118
  if (!mulmoScript) {
@@ -133,6 +133,7 @@ export const initializeContextFromFiles = async (files, raiseError, force, capti
133
133
  presentationStyle: presentationStyle ?? studio.script,
134
134
  sessionState: initSessionState(),
135
135
  force: Boolean(force),
136
+ backup: Boolean(withBackup),
136
137
  lang: targetLang ?? studio.script.lang, // This lang is target Language. studio.lang is default Language
137
138
  };
138
139
  }
@@ -2,3 +2,4 @@ import type { AgentFilterFunction } from "graphai";
2
2
  export declare const nijovoiceTextAgentFilter: AgentFilterFunction;
3
3
  export declare const fileCacheAgentFilter: AgentFilterFunction;
4
4
  export declare const browserlessCacheGenerator: (cacheDir: string) => AgentFilterFunction;
5
+ export declare const getBackupFilePath: (originalPath: string) => string;
@@ -1,6 +1,6 @@
1
1
  import dotenv from "dotenv";
2
- import fs from "fs";
3
- import path from "path";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
4
  import fsPromise from "fs/promises";
5
5
  import { GraphAILogger } from "graphai";
6
6
  import { writingMessage, isFile } from "./file.js";
@@ -16,7 +16,7 @@ export const nijovoiceTextAgentFilter = async (context, next) => {
16
16
  return next(context);
17
17
  };
18
18
  export const fileCacheAgentFilter = async (context, next) => {
19
- const { force, file, index, mulmoContext, sessionType, id } = context.namedInputs.cache;
19
+ const { force, file, index, mulmoContext, sessionType, id, withBackup } = context.namedInputs.cache;
20
20
  const shouldUseCache = async () => {
21
21
  if (force && force.some((element) => element)) {
22
22
  return false;
@@ -33,6 +33,7 @@ export const fileCacheAgentFilter = async (context, next) => {
33
33
  GraphAILogger.debug(`cache: ${path.basename(file)}`);
34
34
  return true;
35
35
  }
36
+ const backup = withBackup && withBackup.some((element) => element);
36
37
  try {
37
38
  MulmoStudioContextMethods.setBeatSessionState(mulmoContext, sessionType, index, id, true);
38
39
  const output = (await next(context)) || undefined;
@@ -43,11 +44,17 @@ export const fileCacheAgentFilter = async (context, next) => {
43
44
  if (buffer) {
44
45
  writingMessage(file);
45
46
  await fsPromise.writeFile(file, buffer);
47
+ if (backup) {
48
+ await fsPromise.writeFile(getBackupFilePath(file), buffer);
49
+ }
46
50
  return true;
47
51
  }
48
52
  else if (text) {
49
53
  writingMessage(file);
50
54
  await fsPromise.writeFile(file, text, "utf-8");
55
+ if (backup) {
56
+ await fsPromise.writeFile(getBackupFilePath(file), text, "utf-8");
57
+ }
51
58
  return true;
52
59
  }
53
60
  else if (saved) {
@@ -76,3 +83,16 @@ export const browserlessCacheGenerator = (cacheDir) => {
76
83
  };
77
84
  return browserlessCache;
78
85
  };
86
+ export const getBackupFilePath = (originalPath) => {
87
+ const { dir, name, ext } = path.parse(originalPath);
88
+ const now = new Date();
89
+ const ts = [
90
+ now.getFullYear(),
91
+ String(now.getMonth() + 1).padStart(2, "0"),
92
+ String(now.getDate()).padStart(2, "0"),
93
+ String(now.getHours()).padStart(2, "0"),
94
+ String(now.getMinutes()).padStart(2, "0"),
95
+ String(now.getSeconds()).padStart(2, "0"),
96
+ ].join("");
97
+ return path.join(dir, `${name}-${ts}${ext}`);
98
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast",
3
- "version": "1.2.68",
3
+ "version": "1.3.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.node.js",
@@ -61,6 +61,8 @@
61
61
  "deep_research": "npx tsx ./src/tools/deep_research.ts",
62
62
  "template": "npx tsx batch/template2tsobject.ts && yarn run format",
63
63
  "mcp_server": "npx tsx ./src/mcp/server.ts",
64
+ "voice": "npx tsx batch/openai_sample.ts && yarn run movie scripts/samples/openai_voice.json",
65
+ "nijivoice": "npx tsx batch/niji_sample.ts && yarn run movie scripts/samples/niji_voice.json",
64
66
  "generate_action_docs": "npx tsx ./automation/generate_actions_docs/generate_action_docs.ts"
65
67
  },
66
68
  "repository": "git+ssh://git@github.com/receptron/mulmocast-cli.git",
@@ -71,8 +73,8 @@
71
73
  },
72
74
  "homepage": "https://github.com/receptron/mulmocast-cli#readme",
73
75
  "dependencies": {
74
- "@google-cloud/text-to-speech": "^6.3.1",
75
- "@google/genai": "^1.25.0",
76
+ "@google-cloud/text-to-speech": "^6.4.0",
77
+ "@google/genai": "^1.29.0",
76
78
  "@graphai/anthropic_agent": "^2.0.11",
77
79
  "@graphai/browserless_agent": "^2.0.1",
78
80
  "@graphai/gemini_agent": "^2.0.1",
@@ -84,7 +86,7 @@
84
86
  "@graphai/vanilla_node_agents": "^2.0.4",
85
87
  "@inquirer/input": "^4.2.5",
86
88
  "@inquirer/select": "^4.4.0",
87
- "@modelcontextprotocol/sdk": "^1.20.1",
89
+ "@modelcontextprotocol/sdk": "^1.21.0",
88
90
  "@mozilla/readability": "^0.6.0",
89
91
  "@tavily/core": "^0.5.11",
90
92
  "archiver": "^7.0.1",
@@ -92,12 +94,12 @@
92
94
  "dotenv": "^17.2.3",
93
95
  "fluent-ffmpeg": "^2.1.3",
94
96
  "graphai": "^2.0.16",
95
- "jsdom": "^27.0.1",
96
- "marked": "^16.4.1",
97
+ "jsdom": "^27.1.0",
98
+ "marked": "^17.0.0",
97
99
  "mulmocast-vision": "^1.0.4",
98
100
  "ora": "^9.0.0",
99
- "puppeteer": "^24.25.0",
100
- "replicate": "^1.3.0",
101
+ "puppeteer": "^24.29.1",
102
+ "replicate": "^1.3.1",
101
103
  "yaml": "^2.8.1",
102
104
  "yargs": "^18.0.0",
103
105
  "zod": "^3.25.76",
@@ -105,18 +107,18 @@
105
107
  },
106
108
  "devDependencies": {
107
109
  "@receptron/test_utils": "^2.0.3",
108
- "@types/archiver": "^6.0.3",
109
- "@types/fluent-ffmpeg": "^2.1.26",
110
+ "@types/archiver": "^7.0.0",
111
+ "@types/fluent-ffmpeg": "^2.1.28",
110
112
  "@types/jsdom": "^27.0.0",
111
- "@types/yargs": "^17.0.33",
112
- "eslint": "^9.38.0",
113
+ "@types/yargs": "^17.0.34",
114
+ "eslint": "^9.39.1",
113
115
  "eslint-config-prettier": "^10.1.8",
114
116
  "eslint-plugin-prettier": "^5.5.4",
115
117
  "eslint-plugin-sonarjs": "^3.0.5",
116
118
  "prettier": "^3.6.2",
117
119
  "tsx": "^4.20.6",
118
120
  "typescript": "^5.9.3",
119
- "typescript-eslint": "^8.46.2"
121
+ "typescript-eslint": "^8.46.3"
120
122
  },
121
123
  "engines": {
122
124
  "node": ">=20.0.0"