mulmocast 1.2.64 → 1.2.65

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.
@@ -5,15 +5,16 @@ import { listLocalizedAudioPaths } from "./audio.js";
5
5
  import { imagePreprocessAgent } from "./image_agents.js";
6
6
  import { mkdir } from "../utils/file.js";
7
7
  import { ZipBuilder } from "../utils/zip.js";
8
+ import { bundleTargetLang } from "../utils/const.js";
8
9
  const beatImage = (context) => {
9
10
  return async (beat, index) => {
10
11
  try {
11
12
  const res = await imagePreprocessAgent({ context, beat, index, imageRefs: {} });
12
13
  if ("htmlPrompt" in res) {
13
- return { htmlImageFile: res.htmlImageFile, imagePath: res.imagePath };
14
+ return { htmlImageSource: res.htmlImageFile, imageSource: res.imagePath };
14
15
  }
15
16
  const { imagePath, movieFile, lipSyncFile } = res;
16
- return { imagePath, movieFile, lipSyncFile };
17
+ return { imageSource: imagePath, videoSource: movieFile, videoWithAudioSource: lipSyncFile };
17
18
  }
18
19
  catch (e) {
19
20
  GraphAILogger.log(e);
@@ -21,32 +22,37 @@ const beatImage = (context) => {
21
22
  }
22
23
  };
23
24
  };
25
+ // TODO reference
24
26
  const viewJsonFileName = "mulmo_view.json";
25
27
  const zipFileName = "mulmo.zip";
26
28
  export const mulmoViewerBundle = async (context) => {
27
29
  const isZip = true;
28
- const audios = listLocalizedAudioPaths(context);
29
- const images = await Promise.all(context.studio.script.beats.map(beatImage(context)));
30
30
  const dir = path.resolve(context.fileDirs.fileName);
31
31
  mkdir(dir);
32
32
  const zipper = new ZipBuilder(path.resolve(dir, zipFileName));
33
33
  const resultJson = [];
34
- audios.forEach((audio) => {
35
- if (audio) {
36
- const fileName = path.basename(audio ?? "");
37
- resultJson.push({ audio: fileName });
38
- if (fs.existsSync(audio)) {
39
- fs.copyFileSync(audio, path.resolve(dir, fileName));
40
- zipper.addFile(audio, fileName);
41
- }
42
- }
43
- else {
44
- resultJson.push({});
45
- }
34
+ context.studio.script.beats.forEach((beat) => {
35
+ resultJson.push({ text: beat.text, duration: beat.duration, audioSources: {}, multiLinguals: {} });
46
36
  });
37
+ for (const lang of bundleTargetLang) {
38
+ const audios = listLocalizedAudioPaths({ ...context, lang });
39
+ audios.forEach((audio, index) => {
40
+ if (audio) {
41
+ const fileName = path.basename(audio ?? "");
42
+ if (resultJson[index] && resultJson[index].audioSources) {
43
+ resultJson[index].audioSources[lang] = fileName;
44
+ }
45
+ if (fs.existsSync(audio)) {
46
+ fs.copyFileSync(audio, path.resolve(dir, fileName));
47
+ zipper.addFile(audio, fileName);
48
+ }
49
+ }
50
+ });
51
+ }
52
+ const images = await Promise.all(context.studio.script.beats.map(beatImage(context)));
47
53
  images.forEach((image, index) => {
48
54
  const data = resultJson[index];
49
- const keys = ["htmlImageFile", "imagePath", "movieFile", "lipSyncFile"];
55
+ const keys = ["htmlImageSource", "imageSource", "videoSource", "videoWithAudioSource"];
50
56
  keys.forEach((key) => {
51
57
  const value = image[key];
52
58
  if (value) {
@@ -58,7 +64,14 @@ export const mulmoViewerBundle = async (context) => {
58
64
  }
59
65
  });
60
66
  });
61
- fs.writeFileSync(path.resolve(dir, viewJsonFileName), JSON.stringify(resultJson, null, 2));
67
+ context.multiLingual.forEach((beat, index) => {
68
+ bundleTargetLang.forEach((lang) => {
69
+ if (resultJson[index] && resultJson[index].multiLinguals) {
70
+ resultJson[index].multiLinguals[lang] = beat.multiLingualTexts[lang].text;
71
+ }
72
+ });
73
+ });
74
+ fs.writeFileSync(path.resolve(dir, viewJsonFileName), JSON.stringify({ beats: resultJson, bgmSource: context.studio?.script.audioParams?.bgm }, null, 2));
62
75
  zipper.addFile(path.resolve(dir, viewJsonFileName));
63
76
  if (isZip) {
64
77
  await zipper.finalize();
@@ -70,8 +70,10 @@ export const imagePreprocessAgent = async (namedInputs) => {
70
70
  // ImagePluginPreprocessAgentResponse
71
71
  return {
72
72
  ...returnValue,
73
- imagePath: isTypeMovie ? undefined : pluginPath,
73
+ // imagePath: isTypeMovie ? undefined : pluginPath,
74
+ imagePath: isTypeMovie ? imagePath : pluginPath,
74
75
  movieFile: isTypeMovie ? pluginPath : undefined,
76
+ imageFromMovie: isTypeMovie,
75
77
  referenceImageForMovie: pluginPath,
76
78
  markdown,
77
79
  html,
@@ -4,14 +4,14 @@ import puppeteer from "puppeteer";
4
4
  import { GraphAILogger, sleep } from "graphai";
5
5
  import { MulmoPresentationStyleMethods } from "../methods/index.js";
6
6
  import { localizedText, isHttp } from "../utils/utils.js";
7
- import { getOutputPdfFilePath, writingMessage, getHTMLFile } from "../utils/file.js";
7
+ import { getOutputPdfFilePath, writingMessage, getHTMLFile, mulmoCreditPath } from "../utils/file.js";
8
8
  import { interpolate } from "../utils/markdown.js";
9
9
  import { MulmoStudioContextMethods } from "../methods/mulmo_studio_context.js";
10
10
  const isCI = process.env.CI === "true";
11
11
  const getPdfSize = (pdfSize) => {
12
12
  return pdfSize === "a4" ? "A4" : "Letter";
13
13
  };
14
- const loadImage = async (imagePath) => {
14
+ const loadImage = async (imagePath, index) => {
15
15
  try {
16
16
  const imageData = isHttp(imagePath) ? Buffer.from(await (await fetch(imagePath)).arrayBuffer()) : fs.readFileSync(imagePath);
17
17
  const ext = path.extname(imagePath).toLowerCase().replace(".", "");
@@ -19,8 +19,8 @@ const loadImage = async (imagePath) => {
19
19
  return `data:image/${mimeType};base64,${imageData.toString("base64")}`;
20
20
  }
21
21
  catch (error) {
22
- GraphAILogger.info("loadImage failed", error);
23
- const placeholderData = fs.readFileSync("assets/images/mulmocast_credit.png");
22
+ GraphAILogger.info(`loadImage failed: file: ${imagePath} index: ${index}`, error);
23
+ const placeholderData = fs.readFileSync(mulmoCreditPath());
24
24
  return `data:image/png;base64,${placeholderData.toString("base64")}`;
25
25
  }
26
26
  };
@@ -100,9 +100,9 @@ const generatePDFHTML = async (context, pdfMode, pdfSize) => {
100
100
  const { studio, multiLingual, lang = "en" } = context;
101
101
  const { width: imageWidth, height: imageHeight } = MulmoPresentationStyleMethods.getCanvasSize(context.presentationStyle);
102
102
  const isLandscapeImage = imageWidth > imageHeight;
103
- const imagePaths = studio.beats.map((beat) => beat.imageFile);
103
+ const imageFiles = studio.beats.map((beat) => beat.htmlImageFile ?? beat.imageFile);
104
104
  const texts = studio.script.beats.map((beat, index) => localizedText(beat, multiLingual?.[index], lang));
105
- const imageDataUrls = await Promise.all(imagePaths.map(loadImage));
105
+ const imageDataUrls = await Promise.all(imageFiles.map(loadImage));
106
106
  const defaultPageSize = `${getPdfSize(pdfSize)} ${isLandscapeImage ? "landscape" : "portrait"}`;
107
107
  const pageSize = pdfMode === "handout" ? `${getPdfSize(pdfSize)} portrait` : defaultPageSize;
108
108
  const pagesHTML = generatePagesHTML(pdfMode, imageDataUrls, texts);
@@ -1,10 +1,14 @@
1
- import { mulmoViewerBundle, audio, images } from "../../../actions/index.js";
2
- import { initializeContext, runTranslateIfNeeded } from "../../helpers.js";
1
+ import { mulmoViewerBundle, audio, images, translate } from "../../../actions/index.js";
2
+ import { initializeContext } from "../../helpers.js";
3
+ import { bundleTargetLang } from "../../../utils/const.js";
3
4
  export const handler = async (argv) => {
4
5
  const context = await initializeContext(argv);
5
6
  if (!context) {
6
7
  process.exit(1);
7
8
  }
8
- await runTranslateIfNeeded(context, true);
9
+ await translate(context, { targetLangs: bundleTargetLang });
10
+ for (const lang of bundleTargetLang.filter((_lang) => _lang !== context.lang)) {
11
+ await audio({ ...context, lang });
12
+ }
9
13
  await audio(context).then(images).then(mulmoViewerBundle);
10
14
  };
@@ -10,3 +10,4 @@ export declare const storyToScriptGenerateMode: {
10
10
  stepWise: string;
11
11
  oneStep: string;
12
12
  };
13
+ export declare const bundleTargetLang: string[];
@@ -10,3 +10,4 @@ export const storyToScriptGenerateMode = {
10
10
  stepWise: "step_wise",
11
11
  oneStep: "one_step",
12
12
  };
13
+ export const bundleTargetLang = ["ja", "en"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast",
3
- "version": "1.2.64",
3
+ "version": "1.2.65",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.node.js",
@@ -84,7 +84,7 @@
84
84
  "@graphai/vanilla_node_agents": "^2.0.4",
85
85
  "@inquirer/input": "^4.2.5",
86
86
  "@inquirer/select": "^4.4.0",
87
- "@modelcontextprotocol/sdk": "^1.20.0",
87
+ "@modelcontextprotocol/sdk": "^1.20.1",
88
88
  "@mozilla/readability": "^0.6.0",
89
89
  "@tavily/core": "^0.5.11",
90
90
  "archiver": "^7.0.1",
@@ -93,10 +93,10 @@
93
93
  "fluent-ffmpeg": "^2.1.3",
94
94
  "graphai": "^2.0.16",
95
95
  "jsdom": "^27.0.0",
96
- "marked": "^16.4.0",
96
+ "marked": "^16.4.1",
97
97
  "mulmocast-vision": "^1.0.4",
98
98
  "ora": "^9.0.0",
99
- "puppeteer": "^24.24.1",
99
+ "puppeteer": "^24.25.0",
100
100
  "replicate": "^1.3.0",
101
101
  "yaml": "^2.8.1",
102
102
  "yargs": "^18.0.0",
@@ -109,7 +109,7 @@
109
109
  "@types/fluent-ffmpeg": "^2.1.26",
110
110
  "@types/jsdom": "^27.0.0",
111
111
  "@types/yargs": "^17.0.33",
112
- "eslint": "^9.37.0",
112
+ "eslint": "^9.38.0",
113
113
  "eslint-config-prettier": "^10.1.8",
114
114
  "eslint-plugin-prettier": "^5.5.4",
115
115
  "eslint-plugin-sonarjs": "^3.0.5",