mulmocast 1.1.8 → 1.1.10
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.
- package/assets/images/mulmocast_credit.png +0 -0
- package/lib/actions/captions.js +4 -7
- package/lib/actions/translate.d.ts +6 -2
- package/lib/actions/translate.js +12 -26
- package/lib/index.common.d.ts +1 -0
- package/lib/index.common.js +1 -0
- package/lib/methods/mulmo_script.js +4 -0
- package/lib/utils/const.js +1 -1
- package/lib/utils/file.d.ts +1 -0
- package/lib/utils/file.js +4 -0
- package/lib/utils/provider2agent.js +1 -0
- package/lib/utils/string.d.ts +5 -0
- package/lib/utils/string.js +12 -0
- package/lib/utils/utils.d.ts +1 -1
- package/lib/utils/utils.js +6 -3
- package/package.json +5 -4
- package/scripts/test/test_hello.json +3 -0
|
Binary file
|
package/lib/actions/captions.js
CHANGED
|
@@ -2,6 +2,7 @@ import { mulmoCaptionParamsSchema } from "../types/index.js";
|
|
|
2
2
|
import { GraphAI, GraphAILogger } from "graphai";
|
|
3
3
|
import * as agents from "@graphai/vanilla";
|
|
4
4
|
import { getHTMLFile, getCaptionImagePath, getOutputStudioFilePath } from "../utils/file.js";
|
|
5
|
+
import { localizedText } from "../utils/utils.js";
|
|
5
6
|
import { renderHTMLToImage, interpolate } from "../utils/markdown.js";
|
|
6
7
|
import { MulmoStudioContextMethods, MulmoPresentationStyleMethods } from "../methods/index.js";
|
|
7
8
|
import { fileWriteAgent } from "@graphai/vanilla_node_agents";
|
|
@@ -30,14 +31,10 @@ const graph_data = {
|
|
|
30
31
|
const canvasSize = MulmoPresentationStyleMethods.getCanvasSize(context.presentationStyle);
|
|
31
32
|
const imagePath = getCaptionImagePath(context, index);
|
|
32
33
|
const template = getHTMLFile("caption");
|
|
33
|
-
|
|
34
|
-
const multiLingual = context.multiLingual;
|
|
35
|
-
if (captionParams.lang && multiLingual) {
|
|
36
|
-
return multiLingual[index].multiLingualTexts[captionParams.lang].text;
|
|
37
|
-
}
|
|
34
|
+
if (captionParams.lang && !context.multiLingual?.[index]?.multiLingualTexts?.[captionParams.lang]) {
|
|
38
35
|
GraphAILogger.warn(`No multiLingual caption found for beat ${index}, lang: ${captionParams.lang}`);
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
}
|
|
37
|
+
const text = localizedText(beat, context.multiLingual?.[index], captionParams.lang, context.studio.script.lang);
|
|
41
38
|
const htmlData = interpolate(template, {
|
|
42
39
|
caption: text,
|
|
43
40
|
width: `${canvasSize.width}`,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "dotenv/config";
|
|
2
2
|
import type { CallbackFunction } from "graphai";
|
|
3
|
-
import { LANG,
|
|
3
|
+
import type { LANG, MulmoStudioContext } from "../types/index.js";
|
|
4
4
|
export declare const translateTextGraph: {
|
|
5
5
|
version: number;
|
|
6
6
|
nodes: {
|
|
@@ -25,7 +25,7 @@ export declare const translateTextGraph: {
|
|
|
25
25
|
};
|
|
26
26
|
splitText: {
|
|
27
27
|
agent: (namedInputs: {
|
|
28
|
-
localizedText: LocalizedText;
|
|
28
|
+
localizedText: import("../types/type.js").LocalizedText;
|
|
29
29
|
targetLang: LANG;
|
|
30
30
|
}) => string[];
|
|
31
31
|
inputs: {
|
|
@@ -46,6 +46,10 @@ export declare const translateTextGraph: {
|
|
|
46
46
|
};
|
|
47
47
|
};
|
|
48
48
|
};
|
|
49
|
+
export declare const getOutputMultilingualFilePathAndMkdir: (context: MulmoStudioContext) => {
|
|
50
|
+
outputMultilingualFilePath: string;
|
|
51
|
+
outDirPath: string;
|
|
52
|
+
};
|
|
49
53
|
export declare const translateBeat: (index: number, context: MulmoStudioContext, targetLangs: string[], args?: {
|
|
50
54
|
settings?: Record<string, string>;
|
|
51
55
|
callbacks?: CallbackFunction[];
|
package/lib/actions/translate.js
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import "dotenv/config";
|
|
2
|
-
import { createHash } from "crypto";
|
|
3
2
|
import fs from "fs";
|
|
4
3
|
import { GraphAI, assert, isNull, GraphAILogger } from "graphai";
|
|
5
4
|
import * as agents from "@graphai/vanilla";
|
|
6
5
|
import { openAIAgent } from "@graphai/openai_agent";
|
|
7
6
|
import { fileWriteAgent } from "@graphai/vanilla_node_agents";
|
|
8
|
-
import {
|
|
7
|
+
import { splitText } from "../utils/string.js";
|
|
9
8
|
import { settings2GraphAIConfig } from "../utils/utils.js";
|
|
10
9
|
import { getMultiLingual } from "../utils/context.js";
|
|
11
10
|
import { currentMulmoScriptVersion } from "../utils/const.js";
|
|
12
|
-
import { getOutputMultilingualFilePath, mkdir, writingMessage } from "../utils/file.js";
|
|
11
|
+
import { getOutputMultilingualFilePath, mkdir, writingMessage, hashSHA256 } from "../utils/file.js";
|
|
13
12
|
import { translateSystemPrompt, translatePrompts } from "../utils/prompt.js";
|
|
14
13
|
import { MulmoStudioContextMethods } from "../methods/mulmo_studio_context.js";
|
|
15
14
|
const vanillaAgents = agents.default ?? agents;
|
|
16
|
-
const hashSHA256 = (text) => {
|
|
17
|
-
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
18
|
-
};
|
|
19
15
|
// 1. translateGraph / map each beats.
|
|
20
16
|
// 2. beatGraph / map each target lang.
|
|
21
17
|
// 3. translateTextGraph / translate text.
|
|
@@ -43,18 +39,7 @@ export const translateTextGraph = {
|
|
|
43
39
|
agent: "openAIAgent",
|
|
44
40
|
},
|
|
45
41
|
splitText: {
|
|
46
|
-
agent:
|
|
47
|
-
const { localizedText, targetLang } = namedInputs;
|
|
48
|
-
// Cache
|
|
49
|
-
if (localizedText.texts) {
|
|
50
|
-
return localizedText.texts;
|
|
51
|
-
}
|
|
52
|
-
if (targetLang === "ja") {
|
|
53
|
-
return recursiveSplitJa(localizedText.text);
|
|
54
|
-
}
|
|
55
|
-
// not split
|
|
56
|
-
return [localizedText.text];
|
|
57
|
-
},
|
|
42
|
+
agent: splitText,
|
|
58
43
|
inputs: {
|
|
59
44
|
targetLang: ":targetLang",
|
|
60
45
|
localizedText: ":localizedText",
|
|
@@ -213,6 +198,13 @@ const agentFilters = [
|
|
|
213
198
|
nodeIds: ["localizedText"],
|
|
214
199
|
},
|
|
215
200
|
];
|
|
201
|
+
export const getOutputMultilingualFilePathAndMkdir = (context) => {
|
|
202
|
+
const fileName = MulmoStudioContextMethods.getFileName(context);
|
|
203
|
+
const outDirPath = MulmoStudioContextMethods.getOutDirPath(context);
|
|
204
|
+
const outputMultilingualFilePath = getOutputMultilingualFilePath(outDirPath, fileName);
|
|
205
|
+
mkdir(outDirPath);
|
|
206
|
+
return { outputMultilingualFilePath, outDirPath };
|
|
207
|
+
};
|
|
216
208
|
export const translateBeat = async (index, context, targetLangs, args) => {
|
|
217
209
|
const { settings, callbacks } = args ?? {};
|
|
218
210
|
// Validate inputs
|
|
@@ -223,10 +215,7 @@ export const translateBeat = async (index, context, targetLangs, args) => {
|
|
|
223
215
|
throw new Error("targetLangs must be a non-empty array");
|
|
224
216
|
}
|
|
225
217
|
try {
|
|
226
|
-
const
|
|
227
|
-
const outDirPath = MulmoStudioContextMethods.getOutDirPath(context);
|
|
228
|
-
const outputMultilingualFilePath = getOutputMultilingualFilePath(outDirPath, fileName);
|
|
229
|
-
mkdir(outDirPath);
|
|
218
|
+
const { outputMultilingualFilePath } = getOutputMultilingualFilePathAndMkdir(context);
|
|
230
219
|
const config = settings2GraphAIConfig(settings, process.env);
|
|
231
220
|
assert(!!config?.openAIAgent?.apiKey, "The OPENAI_API_KEY environment variable is missing or empty");
|
|
232
221
|
const graph = new GraphAI(beatGraph, { ...vanillaAgents, fileWriteAgent, openAIAgent }, { agentFilters, config });
|
|
@@ -257,10 +246,7 @@ export const translate = async (context, args) => {
|
|
|
257
246
|
const { settings, callbacks } = args ?? {};
|
|
258
247
|
try {
|
|
259
248
|
MulmoStudioContextMethods.setSessionState(context, "multiLingual", true);
|
|
260
|
-
const
|
|
261
|
-
const outDirPath = MulmoStudioContextMethods.getOutDirPath(context);
|
|
262
|
-
const outputMultilingualFilePath = getOutputMultilingualFilePath(outDirPath, fileName);
|
|
263
|
-
mkdir(outDirPath);
|
|
249
|
+
const { outputMultilingualFilePath, outDirPath } = getOutputMultilingualFilePathAndMkdir(context);
|
|
264
250
|
const targetLangs = [...new Set([context.lang, context.studio.script.captionParams?.lang].filter((x) => !isNull(x)))];
|
|
265
251
|
const config = settings2GraphAIConfig(settings, process.env);
|
|
266
252
|
assert(!!config?.openAIAgent?.apiKey, "The OPENAI_API_KEY environment variable is missing or empty");
|
package/lib/index.common.d.ts
CHANGED
package/lib/index.common.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GraphAILogger } from "graphai";
|
|
1
2
|
import { mulmoScriptSchema, mulmoStudioMultiLingualFileSchema } from "../types/index.js";
|
|
2
3
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
4
|
const validate_1_0 = (script) => {
|
|
@@ -37,6 +38,9 @@ export const MulmoStudioMultiLingualMethod = {
|
|
|
37
38
|
validate(jsonData, studioBeatsLength) {
|
|
38
39
|
// TODO version check
|
|
39
40
|
const result = mulmoStudioMultiLingualFileSchema.safeParse(jsonData);
|
|
41
|
+
if (!result.success) {
|
|
42
|
+
GraphAILogger.warn("multiLingual file validation failed.");
|
|
43
|
+
}
|
|
40
44
|
const dataSet = result.success ? result.data.multiLingual : [];
|
|
41
45
|
while (dataSet.length < studioBeatsLength) {
|
|
42
46
|
dataSet.push({ multiLingualTexts: {} });
|
package/lib/utils/const.js
CHANGED
|
@@ -5,7 +5,7 @@ export const imageDirName = "images";
|
|
|
5
5
|
export const cacheDirName = "cache";
|
|
6
6
|
export const pdf_modes = ["slide", "talk", "handout"];
|
|
7
7
|
export const pdf_sizes = ["letter", "a4"];
|
|
8
|
-
export const languages = ["en", "ja", "fr", "es"];
|
|
8
|
+
export const languages = ["en", "ja", "fr", "es", "de", "zh-CN", "zh-TW", "ko", "it", "pt", "ar", "hi"];
|
|
9
9
|
export const storyToScriptGenerateMode = {
|
|
10
10
|
stepWise: "step_wise",
|
|
11
11
|
oneStep: "one_step",
|
package/lib/utils/file.d.ts
CHANGED
|
@@ -48,3 +48,4 @@ export declare const getAvailableScriptTemplates: () => MulmoScript[];
|
|
|
48
48
|
export declare const writingMessage: (filePath: string) => void;
|
|
49
49
|
export declare const readAndParseJson: <S extends ZodSchema<any>>(filePath: string, schema: S) => ReturnType<S["parse"]>;
|
|
50
50
|
export declare const generateTimestampedFileName: (prefix: string) => string;
|
|
51
|
+
export declare const hashSHA256: (text: string) => string;
|
package/lib/utils/file.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import { createHash } from "crypto";
|
|
3
4
|
import { parse as yamlParse } from "yaml";
|
|
4
5
|
import { fileURLToPath } from "url";
|
|
5
6
|
import { GraphAILogger } from "graphai";
|
|
@@ -226,3 +227,6 @@ export const generateTimestampedFileName = (prefix) => {
|
|
|
226
227
|
const pad = (n) => n.toString().padStart(2, "0");
|
|
227
228
|
return `${prefix}_${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
|
228
229
|
};
|
|
230
|
+
export const hashSHA256 = (text) => {
|
|
231
|
+
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
232
|
+
};
|
package/lib/utils/string.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LANG, LocalizedText } from "../types/index.js";
|
|
1
2
|
export declare function splitIntoSentencesJa(paragraph: string, divider: string, minimum: number): string[];
|
|
2
3
|
export declare const recursiveSplitJa: (text: string) => string[];
|
|
3
4
|
interface Replacement {
|
|
@@ -6,4 +7,8 @@ interface Replacement {
|
|
|
6
7
|
}
|
|
7
8
|
export declare function replacePairsJa(replacements: Replacement[]): (str: string) => string;
|
|
8
9
|
export declare const replacementsJa: Replacement[];
|
|
10
|
+
export declare const splitText: (namedInputs: {
|
|
11
|
+
localizedText: LocalizedText;
|
|
12
|
+
targetLang: LANG;
|
|
13
|
+
}) => string[];
|
|
9
14
|
export {};
|
package/lib/utils/string.js
CHANGED
|
@@ -56,3 +56,15 @@ export const replacementsJa = [
|
|
|
56
56
|
{ from: "%", to: "パーセント" },
|
|
57
57
|
{ from: "IPO", to: "アイピーオー" },
|
|
58
58
|
];
|
|
59
|
+
export const splitText = (namedInputs) => {
|
|
60
|
+
const { localizedText, targetLang } = namedInputs;
|
|
61
|
+
// Cache
|
|
62
|
+
if (localizedText.texts) {
|
|
63
|
+
return localizedText.texts;
|
|
64
|
+
}
|
|
65
|
+
if (targetLang === "ja") {
|
|
66
|
+
return recursiveSplitJa(localizedText.text);
|
|
67
|
+
}
|
|
68
|
+
// not split
|
|
69
|
+
return [localizedText.text];
|
|
70
|
+
};
|
package/lib/utils/utils.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare const llmPair: (_llm?: LLM, _model?: string) => {
|
|
|
9
9
|
export declare const chunkArray: <T>(array: T[], size?: number) => T[][];
|
|
10
10
|
export declare const isHttp: (fileOrUrl: string) => boolean;
|
|
11
11
|
export declare const text2hash: (input: string) => string;
|
|
12
|
-
export declare const localizedText: (beat: MulmoBeat, multiLingualData?: MulmoStudioMultiLingualData,
|
|
12
|
+
export declare const localizedText: (beat: MulmoBeat, multiLingualData?: MulmoStudioMultiLingualData, targetLang?: string, defaultLang?: string) => string;
|
|
13
13
|
export declare const sleep: (milliseconds: number) => Promise<unknown>;
|
|
14
14
|
export declare function userAssert(condition: boolean, message: string): asserts condition;
|
|
15
15
|
export declare const settings2GraphAIConfig: (settings?: Record<string, string>, env?: Record<string, string | undefined>) => ConfigDataDictionary<DefaultConfigData>;
|
package/lib/utils/utils.js
CHANGED
|
@@ -20,9 +20,12 @@ export const isHttp = (fileOrUrl) => {
|
|
|
20
20
|
export const text2hash = (input) => {
|
|
21
21
|
return crypto.createHash("sha256").update(input).digest("hex");
|
|
22
22
|
};
|
|
23
|
-
export const localizedText = (beat, multiLingualData,
|
|
24
|
-
if (
|
|
25
|
-
return
|
|
23
|
+
export const localizedText = (beat, multiLingualData, targetLang, defaultLang) => {
|
|
24
|
+
if (targetLang === defaultLang) {
|
|
25
|
+
return beat.text;
|
|
26
|
+
}
|
|
27
|
+
if (targetLang && multiLingualData?.multiLingualTexts?.[targetLang]?.text) {
|
|
28
|
+
return multiLingualData.multiLingualTexts[targetLang].text;
|
|
26
29
|
}
|
|
27
30
|
return beat.text;
|
|
28
31
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mulmocast",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.10",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.node.js",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"./scripts/test",
|
|
27
27
|
"./assets/audio/silent60sec.mp3",
|
|
28
28
|
"./assets/html/",
|
|
29
|
+
"./assets/images/",
|
|
29
30
|
"./assets/templates/"
|
|
30
31
|
],
|
|
31
32
|
"directories": {
|
|
@@ -82,8 +83,8 @@
|
|
|
82
83
|
"fluent-ffmpeg": "^2.1.3",
|
|
83
84
|
"google-auth-library": "^10.1.0",
|
|
84
85
|
"graphai": "^2.0.13",
|
|
85
|
-
"inquirer": "^12.
|
|
86
|
-
"marked": "^16.1.
|
|
86
|
+
"inquirer": "^12.9.0",
|
|
87
|
+
"marked": "^16.1.2",
|
|
87
88
|
"ora": "^8.2.0",
|
|
88
89
|
"puppeteer": "^24.15.0",
|
|
89
90
|
"replicate": "^1.0.1",
|
|
@@ -106,7 +107,7 @@
|
|
|
106
107
|
"ts-node": "^10.9.2",
|
|
107
108
|
"tsx": "^4.20.3",
|
|
108
109
|
"typescript": "^5.9.2",
|
|
109
|
-
"typescript-eslint": "^8.
|
|
110
|
+
"typescript-eslint": "^8.39.0"
|
|
110
111
|
},
|
|
111
112
|
"engines": {
|
|
112
113
|
"node": ">=18.0.0"
|