mulmocast 0.0.1 → 0.0.3
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/README.md +129 -15
- package/assets/font/NotoSansJP-Regular.ttf +0 -0
- package/assets/html/chart.html +38 -0
- package/assets/html/mermaid.html +51 -0
- package/assets/templates/business.json +57 -14
- package/assets/templates/children_book.json +1 -3
- package/assets/templates/coding.json +140 -0
- package/lib/actions/audio.d.ts +2 -2
- package/lib/actions/audio.js +88 -101
- package/lib/actions/images.d.ts +1 -1
- package/lib/actions/images.js +50 -88
- package/lib/actions/index.d.ts +5 -0
- package/lib/actions/index.js +5 -0
- package/lib/actions/movie.d.ts +9 -1
- package/lib/actions/movie.js +124 -65
- package/lib/actions/pdf.d.ts +2 -0
- package/lib/actions/pdf.js +211 -0
- package/lib/actions/pdf2.d.ts +2 -0
- package/lib/actions/pdf2.js +203 -0
- package/lib/actions/translate.d.ts +1 -1
- package/lib/actions/translate.js +38 -61
- package/lib/agents/add_bgm_agent.d.ts +1 -1
- package/lib/agents/add_bgm_agent.js +10 -14
- package/lib/agents/anthropic_agent.d.ts +23 -0
- package/lib/agents/anthropic_agent.js +162 -0
- package/lib/agents/combine_audio_files_agent.d.ts +1 -1
- package/lib/agents/combine_audio_files_agent.js +33 -32
- package/lib/agents/image_google_agent.d.ts +1 -1
- package/lib/agents/image_google_agent.js +8 -11
- package/lib/agents/image_openai_agent.js +7 -14
- package/lib/agents/index.d.ts +8 -8
- package/lib/agents/index.js +13 -30
- package/lib/agents/mulmo_prompts_agent.d.ts +1 -1
- package/lib/agents/mulmo_prompts_agent.js +7 -11
- package/lib/agents/nested_agent.d.ts +9 -0
- package/lib/agents/nested_agent.js +138 -0
- package/lib/agents/prompts_data.js +1 -4
- package/lib/agents/tts_nijivoice_agent.d.ts +1 -1
- package/lib/agents/tts_nijivoice_agent.js +8 -12
- package/lib/agents/tts_openai_agent.js +9 -16
- package/lib/agents/validate_mulmo_script_agent.d.ts +1 -1
- package/lib/agents/validate_mulmo_script_agent.js +6 -10
- package/lib/cli/args.d.ts +5 -2
- package/lib/cli/args.js +52 -35
- package/lib/cli/cli.d.ts +14 -0
- package/lib/cli/cli.js +74 -57
- package/lib/cli/common.js +1 -5
- package/lib/cli/tool-args.d.ts +4 -1
- package/lib/cli/tool-args.js +29 -18
- package/lib/cli/tool-cli.js +34 -51
- package/lib/methods/index.d.ts +4 -3
- package/lib/methods/index.js +4 -19
- package/lib/methods/mulmo_media_source.d.ts +4 -0
- package/lib/methods/mulmo_media_source.js +21 -0
- package/lib/methods/mulmo_script.d.ts +6 -5
- package/lib/methods/mulmo_script.js +29 -16
- package/lib/methods/mulmo_script_template.d.ts +1 -1
- package/lib/methods/mulmo_script_template.js +4 -10
- package/lib/methods/mulmo_studio_context.d.ts +1 -1
- package/lib/methods/mulmo_studio_context.js +3 -9
- package/lib/tools/create_mulmo_script_from_url.d.ts +3 -0
- package/lib/tools/create_mulmo_script_from_url.js +152 -0
- package/lib/tools/create_mulmo_script_interactively.d.ts +3 -0
- package/lib/tools/create_mulmo_script_interactively.js +258 -0
- package/lib/tools/dump_prompt.js +5 -8
- package/lib/tools/prompt.js +9 -11
- package/lib/tools/seed_from_url2.d.ts +3 -0
- package/lib/tools/seed_from_url2.js +154 -0
- package/lib/types/index.d.ts +2 -1
- package/lib/types/index.js +2 -17
- package/lib/types/schema.d.ts +3624 -2798
- package/lib/types/schema.js +172 -123
- package/lib/types/type.d.ts +34 -3
- package/lib/types/type.js +1 -2
- package/lib/utils/const.d.ts +4 -1
- package/lib/utils/const.js +6 -6
- package/lib/utils/file.d.ts +22 -4
- package/lib/utils/file.js +100 -79
- package/lib/utils/filters.d.ts +1 -0
- package/lib/utils/filters.js +47 -26
- package/lib/utils/image_plugins/chart.d.ts +3 -0
- package/lib/utils/image_plugins/chart.js +18 -0
- package/lib/utils/image_plugins/image.d.ts +2 -0
- package/lib/utils/image_plugins/image.js +3 -0
- package/lib/utils/image_plugins/index.d.ts +7 -0
- package/lib/utils/image_plugins/index.js +7 -0
- package/lib/utils/image_plugins/markdown.d.ts +3 -0
- package/lib/utils/image_plugins/markdown.js +11 -0
- package/lib/utils/image_plugins/mermaid.d.ts +3 -0
- package/lib/utils/image_plugins/mermaid.js +21 -0
- package/lib/utils/image_plugins/movie.d.ts +2 -0
- package/lib/utils/image_plugins/movie.js +3 -0
- package/lib/utils/image_plugins/source.d.ts +4 -0
- package/lib/utils/image_plugins/source.js +15 -0
- package/lib/utils/image_plugins/text_slide.d.ts +3 -0
- package/lib/utils/image_plugins/text_slide.js +12 -0
- package/lib/utils/image_plugins/type_guards.d.ts +6 -0
- package/lib/utils/image_plugins/type_guards.js +21 -0
- package/lib/utils/image_preprocess.d.ts +14 -0
- package/lib/utils/image_preprocess.js +52 -0
- package/lib/utils/inquirer.d.ts +2 -0
- package/lib/utils/inquirer.js +33 -0
- package/lib/utils/markdown.d.ts +3 -1
- package/lib/utils/markdown.js +20 -19
- package/lib/utils/pdf.d.ts +8 -0
- package/lib/utils/pdf.js +75 -0
- package/lib/utils/plugins.d.ts +5 -0
- package/lib/utils/plugins.js +11 -0
- package/lib/utils/preprocess.d.ts +70 -123
- package/lib/utils/preprocess.js +37 -43
- package/lib/utils/string.js +4 -10
- package/lib/utils/text_hash.js +2 -39
- package/lib/utils/utils.d.ts +12 -0
- package/lib/utils/utils.js +34 -0
- package/package.json +23 -8
package/lib/utils/markdown.js
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// Step 0: Prepare the header
|
|
11
|
-
const header = `<head><style>${style}</style></head>`;
|
|
12
|
-
// Step 1: Convert Markdown to HTML
|
|
13
|
-
const body = await (0, marked_1.marked)(markdown);
|
|
14
|
-
const html = `<htlm>${header}<body>${body}</body></html>`;
|
|
15
|
-
// Step 2: Use Puppeteer to render HTML to an image
|
|
16
|
-
const browser = await puppeteer_1.default.launch();
|
|
1
|
+
import { GraphAILogger } from "graphai";
|
|
2
|
+
import { marked } from "marked";
|
|
3
|
+
import puppeteer from "puppeteer";
|
|
4
|
+
const isCI = process.env.CI === "true";
|
|
5
|
+
export const renderHTMLToImage = async (html, outputPath, width, height) => {
|
|
6
|
+
// Use Puppeteer to render HTML to an image
|
|
7
|
+
const browser = await puppeteer.launch({
|
|
8
|
+
args: isCI ? ["--no-sandbox"] : [],
|
|
9
|
+
});
|
|
17
10
|
const page = await browser.newPage();
|
|
18
11
|
// Set the page content to the HTML generated from the Markdown
|
|
19
12
|
await page.setContent(html);
|
|
20
13
|
// Adjust page settings if needed (like width, height, etc.)
|
|
21
|
-
await page.setViewport({ width
|
|
14
|
+
await page.setViewport({ width, height });
|
|
22
15
|
// Step 3: Capture screenshot of the page (which contains the Markdown-rendered HTML)
|
|
23
16
|
await page.screenshot({ path: outputPath });
|
|
24
17
|
await browser.close();
|
|
25
|
-
|
|
18
|
+
GraphAILogger.info(`HTML image rendered to ${outputPath}`);
|
|
19
|
+
};
|
|
20
|
+
export const renderMarkdownToImage = async (markdown, style, outputPath, width, height) => {
|
|
21
|
+
const header = `<head><style>${style}</style></head>`;
|
|
22
|
+
const body = await marked(markdown);
|
|
23
|
+
const html = `<htlm>${header}<body>${body}</body></html>`;
|
|
24
|
+
await renderHTMLToImage(html, outputPath, width, height);
|
|
25
|
+
};
|
|
26
|
+
export const interpolate = (template, data) => {
|
|
27
|
+
return template.replace(/\$\{(.*?)\}/g, (_, key) => data[key.trim()] ?? "");
|
|
26
28
|
};
|
|
27
|
-
exports.convertMarkdownToImage = convertMarkdownToImage;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PDFFont } from "pdf-lib";
|
|
2
|
+
export declare const fontSize = 12;
|
|
3
|
+
export declare const textMargin = 6;
|
|
4
|
+
export declare const drawSize: (fitWidth: boolean, expectWidth: number, expectHeight: number, origWidth: number, origHeight: number) => {
|
|
5
|
+
drawWidth: number;
|
|
6
|
+
drawHeight: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const wrapText: (text: string, font: PDFFont, fontSize: number, maxWidth: number) => string[];
|
package/lib/utils/pdf.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export const fontSize = 12;
|
|
2
|
+
export const textMargin = 6;
|
|
3
|
+
export const drawSize = (fitWidth, expectWidth, expectHeight, origWidth, origHeight) => {
|
|
4
|
+
if (fitWidth) {
|
|
5
|
+
const drawWidth = expectWidth;
|
|
6
|
+
const scale = drawWidth / origWidth;
|
|
7
|
+
const drawHeight = origHeight * scale;
|
|
8
|
+
return {
|
|
9
|
+
drawWidth,
|
|
10
|
+
drawHeight,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const drawHeight = expectHeight;
|
|
14
|
+
const scale = drawHeight / origHeight;
|
|
15
|
+
const drawWidth = origWidth * scale;
|
|
16
|
+
return {
|
|
17
|
+
drawWidth,
|
|
18
|
+
drawHeight,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const isFullwidth = (char) => {
|
|
22
|
+
const code = char.charCodeAt(0);
|
|
23
|
+
return ((code >= 0x3000 && code <= 0x9fff) || // CJK, punctuation, kana
|
|
24
|
+
(code >= 0xff00 && code <= 0xffef) // Fullwidth ASCII
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
export const wrapText = (text, font, fontSize, maxWidth) => {
|
|
28
|
+
const lines = [];
|
|
29
|
+
for (const rawLine of text.split("\n")) {
|
|
30
|
+
let line = "";
|
|
31
|
+
let buffer = "";
|
|
32
|
+
for (let i = 0; i < rawLine.length; i++) {
|
|
33
|
+
const char = rawLine[i];
|
|
34
|
+
buffer += char;
|
|
35
|
+
const width = font.widthOfTextAtSize(line + buffer, fontSize);
|
|
36
|
+
const nextChar = rawLine[i + 1];
|
|
37
|
+
const currentIsFull = isFullwidth(char);
|
|
38
|
+
const nextIsFull = nextChar && isFullwidth(nextChar);
|
|
39
|
+
const isBreakable = currentIsFull || (!currentIsFull && (char === " " || nextChar === " " || nextIsFull));
|
|
40
|
+
if (width > maxWidth && buffer) {
|
|
41
|
+
lines.push(line);
|
|
42
|
+
line = "";
|
|
43
|
+
buffer = char;
|
|
44
|
+
}
|
|
45
|
+
if (isBreakable || i === rawLine.length - 1) {
|
|
46
|
+
line += buffer;
|
|
47
|
+
buffer = "";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (line)
|
|
51
|
+
lines.push(line);
|
|
52
|
+
}
|
|
53
|
+
return lines;
|
|
54
|
+
};
|
|
55
|
+
/*
|
|
56
|
+
export const wrapText = (text: string, font: PDFFont, fontSize: number, maxWidth: number) => {
|
|
57
|
+
const words = text.split(" ");
|
|
58
|
+
const lines = [];
|
|
59
|
+
let currentLine = "";
|
|
60
|
+
|
|
61
|
+
for (const word of words) {
|
|
62
|
+
const nextLine = currentLine ? `${currentLine} ${word}` : word;
|
|
63
|
+
// console.log(nextLine);
|
|
64
|
+
const width = font.widthOfTextAtSize(nextLine ?? "", fontSize);
|
|
65
|
+
if (width <= maxWidth) {
|
|
66
|
+
currentLine = nextLine;
|
|
67
|
+
} else {
|
|
68
|
+
lines.push(currentLine);
|
|
69
|
+
currentLine = word;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (currentLine) lines.push(currentLine);
|
|
73
|
+
return lines;
|
|
74
|
+
};
|
|
75
|
+
*/
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import ora from "ora";
|
|
2
|
+
const spinner = ora();
|
|
3
|
+
spinner.prefixText = "\n";
|
|
4
|
+
export const cliLoadingPlugin = ({ nodeId, message }) => (log) => {
|
|
5
|
+
if (log.nodeId === nodeId && log.state === "queued") {
|
|
6
|
+
spinner.start(message);
|
|
7
|
+
}
|
|
8
|
+
if (log.nodeId === nodeId && log.state === "completed") {
|
|
9
|
+
spinner.stop();
|
|
10
|
+
}
|
|
11
|
+
};
|
|
@@ -1,101 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}) => {
|
|
1
|
+
import { MulmoStudio, MulmoScript } from "../types/index.js";
|
|
2
|
+
export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, currentStudio: MulmoStudio | undefined, fileName: string) => {
|
|
4
3
|
beats: {
|
|
5
|
-
text: string;
|
|
6
|
-
speaker: string;
|
|
7
4
|
duration?: number | undefined;
|
|
8
|
-
speechOptions?: {
|
|
9
|
-
speed?: number | undefined;
|
|
10
|
-
instruction?: string | undefined;
|
|
11
|
-
} | undefined;
|
|
12
|
-
image?: {
|
|
13
|
-
type: "markdown";
|
|
14
|
-
markdown: string | string[];
|
|
15
|
-
} | {
|
|
16
|
-
type: "web";
|
|
17
|
-
url: string;
|
|
18
|
-
} | {
|
|
19
|
-
type: "pdf";
|
|
20
|
-
source: {
|
|
21
|
-
url: string;
|
|
22
|
-
kind: "url";
|
|
23
|
-
} | {
|
|
24
|
-
kind: "data";
|
|
25
|
-
data: string;
|
|
26
|
-
} | {
|
|
27
|
-
path: string;
|
|
28
|
-
kind: "path";
|
|
29
|
-
};
|
|
30
|
-
} | {
|
|
31
|
-
type: "image";
|
|
32
|
-
source: {
|
|
33
|
-
url: string;
|
|
34
|
-
kind: "url";
|
|
35
|
-
} | {
|
|
36
|
-
kind: "data";
|
|
37
|
-
data: string;
|
|
38
|
-
} | {
|
|
39
|
-
path: string;
|
|
40
|
-
kind: "path";
|
|
41
|
-
};
|
|
42
|
-
} | {
|
|
43
|
-
type: "svg";
|
|
44
|
-
source: {
|
|
45
|
-
url: string;
|
|
46
|
-
kind: "url";
|
|
47
|
-
} | {
|
|
48
|
-
kind: "data";
|
|
49
|
-
data: string;
|
|
50
|
-
} | {
|
|
51
|
-
path: string;
|
|
52
|
-
kind: "path";
|
|
53
|
-
};
|
|
54
|
-
} | {
|
|
55
|
-
type: "movie";
|
|
56
|
-
source: {
|
|
57
|
-
url: string;
|
|
58
|
-
kind: "url";
|
|
59
|
-
} | {
|
|
60
|
-
kind: "data";
|
|
61
|
-
data: string;
|
|
62
|
-
} | {
|
|
63
|
-
path: string;
|
|
64
|
-
kind: "path";
|
|
65
|
-
};
|
|
66
|
-
} | {
|
|
67
|
-
type: "textSlide";
|
|
68
|
-
slide: {
|
|
69
|
-
title: string;
|
|
70
|
-
bullets: string[];
|
|
71
|
-
};
|
|
72
|
-
} | undefined;
|
|
73
|
-
audio?: {
|
|
74
|
-
type: "audio";
|
|
75
|
-
source: {
|
|
76
|
-
url: string;
|
|
77
|
-
kind: "url";
|
|
78
|
-
} | {
|
|
79
|
-
kind: "data";
|
|
80
|
-
data: string;
|
|
81
|
-
} | {
|
|
82
|
-
path: string;
|
|
83
|
-
kind: "path";
|
|
84
|
-
};
|
|
85
|
-
} | {
|
|
86
|
-
type: "midi";
|
|
87
|
-
source: string;
|
|
88
|
-
} | undefined;
|
|
89
|
-
imageParams?: {
|
|
90
|
-
model?: string | undefined;
|
|
91
|
-
size?: string | undefined;
|
|
92
|
-
style?: string | undefined;
|
|
93
|
-
moderation?: string | undefined;
|
|
94
|
-
} | undefined;
|
|
95
|
-
textSlideParams?: {
|
|
96
|
-
cssStyles: string[];
|
|
97
|
-
} | undefined;
|
|
98
|
-
imagePrompt?: string | undefined;
|
|
99
5
|
multiLingualTexts?: Record<string, {
|
|
100
6
|
text: string;
|
|
101
7
|
lang: string;
|
|
@@ -108,11 +14,25 @@ export declare const createOrUpdateStudioData: (mulmoFile: string, files: {
|
|
|
108
14
|
imageFile?: string | undefined;
|
|
109
15
|
}[];
|
|
110
16
|
script: {
|
|
111
|
-
title: string;
|
|
112
17
|
$mulmocast: {
|
|
113
18
|
version: "1.0";
|
|
114
19
|
credit?: "closing" | undefined;
|
|
115
20
|
};
|
|
21
|
+
canvasSize: {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
};
|
|
25
|
+
speechParams: {
|
|
26
|
+
provider: "openai" | "nijivoice";
|
|
27
|
+
speakers: Record<string, {
|
|
28
|
+
voiceId: string;
|
|
29
|
+
displayName?: Record<string, string> | undefined;
|
|
30
|
+
speechOptions?: {
|
|
31
|
+
speed?: number | undefined;
|
|
32
|
+
instruction?: string | undefined;
|
|
33
|
+
} | undefined;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
116
36
|
beats: {
|
|
117
37
|
text: string;
|
|
118
38
|
speaker: string;
|
|
@@ -132,8 +52,11 @@ export declare const createOrUpdateStudioData: (mulmoFile: string, files: {
|
|
|
132
52
|
url: string;
|
|
133
53
|
kind: "url";
|
|
134
54
|
} | {
|
|
135
|
-
kind: "
|
|
55
|
+
kind: "base64";
|
|
136
56
|
data: string;
|
|
57
|
+
} | {
|
|
58
|
+
text: string;
|
|
59
|
+
kind: "text";
|
|
137
60
|
} | {
|
|
138
61
|
path: string;
|
|
139
62
|
kind: "path";
|
|
@@ -144,8 +67,11 @@ export declare const createOrUpdateStudioData: (mulmoFile: string, files: {
|
|
|
144
67
|
url: string;
|
|
145
68
|
kind: "url";
|
|
146
69
|
} | {
|
|
147
|
-
kind: "
|
|
70
|
+
kind: "base64";
|
|
148
71
|
data: string;
|
|
72
|
+
} | {
|
|
73
|
+
text: string;
|
|
74
|
+
kind: "text";
|
|
149
75
|
} | {
|
|
150
76
|
path: string;
|
|
151
77
|
kind: "path";
|
|
@@ -156,8 +82,11 @@ export declare const createOrUpdateStudioData: (mulmoFile: string, files: {
|
|
|
156
82
|
url: string;
|
|
157
83
|
kind: "url";
|
|
158
84
|
} | {
|
|
159
|
-
kind: "
|
|
85
|
+
kind: "base64";
|
|
160
86
|
data: string;
|
|
87
|
+
} | {
|
|
88
|
+
text: string;
|
|
89
|
+
kind: "text";
|
|
161
90
|
} | {
|
|
162
91
|
path: string;
|
|
163
92
|
kind: "path";
|
|
@@ -168,8 +97,11 @@ export declare const createOrUpdateStudioData: (mulmoFile: string, files: {
|
|
|
168
97
|
url: string;
|
|
169
98
|
kind: "url";
|
|
170
99
|
} | {
|
|
171
|
-
kind: "
|
|
100
|
+
kind: "base64";
|
|
172
101
|
data: string;
|
|
102
|
+
} | {
|
|
103
|
+
text: string;
|
|
104
|
+
kind: "text";
|
|
173
105
|
} | {
|
|
174
106
|
path: string;
|
|
175
107
|
kind: "path";
|
|
@@ -180,6 +112,27 @@ export declare const createOrUpdateStudioData: (mulmoFile: string, files: {
|
|
|
180
112
|
title: string;
|
|
181
113
|
bullets: string[];
|
|
182
114
|
};
|
|
115
|
+
} | {
|
|
116
|
+
type: "chart";
|
|
117
|
+
title: string;
|
|
118
|
+
chartData: Record<string, any>;
|
|
119
|
+
} | {
|
|
120
|
+
code: {
|
|
121
|
+
url: string;
|
|
122
|
+
kind: "url";
|
|
123
|
+
} | {
|
|
124
|
+
kind: "base64";
|
|
125
|
+
data: string;
|
|
126
|
+
} | {
|
|
127
|
+
text: string;
|
|
128
|
+
kind: "text";
|
|
129
|
+
} | {
|
|
130
|
+
path: string;
|
|
131
|
+
kind: "path";
|
|
132
|
+
};
|
|
133
|
+
type: "mermaid";
|
|
134
|
+
title: string;
|
|
135
|
+
appendix?: string[] | undefined;
|
|
183
136
|
} | undefined;
|
|
184
137
|
audio?: {
|
|
185
138
|
type: "audio";
|
|
@@ -187,8 +140,11 @@ export declare const createOrUpdateStudioData: (mulmoFile: string, files: {
|
|
|
187
140
|
url: string;
|
|
188
141
|
kind: "url";
|
|
189
142
|
} | {
|
|
190
|
-
kind: "
|
|
143
|
+
kind: "base64";
|
|
191
144
|
data: string;
|
|
145
|
+
} | {
|
|
146
|
+
text: string;
|
|
147
|
+
kind: "text";
|
|
192
148
|
} | {
|
|
193
149
|
path: string;
|
|
194
150
|
kind: "path";
|
|
@@ -204,43 +160,34 @@ export declare const createOrUpdateStudioData: (mulmoFile: string, files: {
|
|
|
204
160
|
moderation?: string | undefined;
|
|
205
161
|
} | undefined;
|
|
206
162
|
textSlideParams?: {
|
|
207
|
-
cssStyles: string[];
|
|
163
|
+
cssStyles: string | string[];
|
|
208
164
|
} | undefined;
|
|
209
165
|
imagePrompt?: string | undefined;
|
|
210
166
|
}[];
|
|
211
|
-
speechParams: {
|
|
212
|
-
speakers: Record<string, {
|
|
213
|
-
displayName: Record<string, string>;
|
|
214
|
-
voiceId: string;
|
|
215
|
-
speechOptions?: {
|
|
216
|
-
speed?: number | undefined;
|
|
217
|
-
instruction?: string | undefined;
|
|
218
|
-
} | undefined;
|
|
219
|
-
}>;
|
|
220
|
-
provider?: string | undefined;
|
|
221
|
-
};
|
|
222
167
|
lang?: string | undefined;
|
|
168
|
+
title?: string | undefined;
|
|
223
169
|
imageParams?: {
|
|
170
|
+
provider: "openai" | "google";
|
|
224
171
|
model?: string | undefined;
|
|
225
172
|
size?: string | undefined;
|
|
226
173
|
style?: string | undefined;
|
|
227
174
|
moderation?: string | undefined;
|
|
228
|
-
provider?: string | undefined;
|
|
229
175
|
} | undefined;
|
|
230
176
|
textSlideParams?: {
|
|
231
|
-
cssStyles: string[];
|
|
232
|
-
} | undefined;
|
|
233
|
-
description?: string | undefined;
|
|
234
|
-
reference?: string | undefined;
|
|
235
|
-
canvasSize?: {
|
|
236
|
-
width: number;
|
|
237
|
-
height: number;
|
|
177
|
+
cssStyles: string | string[];
|
|
238
178
|
} | undefined;
|
|
239
179
|
videoParams?: {
|
|
240
180
|
padding?: number | undefined;
|
|
241
181
|
} | undefined;
|
|
242
|
-
imagePath?: string | undefined;
|
|
243
182
|
omitCaptions?: boolean | undefined;
|
|
183
|
+
description?: string | undefined;
|
|
184
|
+
references?: {
|
|
185
|
+
type: "image" | "audio" | "article" | "video";
|
|
186
|
+
url: string;
|
|
187
|
+
title?: string | undefined;
|
|
188
|
+
description?: string | undefined;
|
|
189
|
+
}[] | undefined;
|
|
190
|
+
imagePath?: string | undefined;
|
|
244
191
|
__test_invalid__?: boolean | undefined;
|
|
245
192
|
};
|
|
246
193
|
filename: string;
|
package/lib/utils/preprocess.js
CHANGED
|
@@ -1,53 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const { outDirPath } = files;
|
|
9
|
-
const readData = (0, file_1.readMulmoScriptFile)(mulmoFile, "ERROR: File does not exist " + mulmoFile);
|
|
10
|
-
const { mulmoData: mulmoScript, fileName } = readData;
|
|
11
|
-
// Create or update MulmoStudio file with MulmoScript
|
|
12
|
-
const outputStudioFilePath = (0, file_1.getOutputStudioFilePath)(outDirPath, fileName);
|
|
13
|
-
const currentStudio = (0, file_1.readMulmoScriptFile)(outputStudioFilePath);
|
|
14
|
-
const studio = currentStudio?.mulmoData ?? {
|
|
1
|
+
import { mulmoScriptSchema, mulmoBeatSchema, mulmoStudioSchema } from "../types/index.js";
|
|
2
|
+
const rebuildStudio = (currentStudio, mulmoScript, fileName) => {
|
|
3
|
+
const parsed = mulmoStudioSchema.safeParse(currentStudio);
|
|
4
|
+
if (parsed.success) {
|
|
5
|
+
return parsed.data;
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
15
8
|
script: mulmoScript,
|
|
16
9
|
filename: fileName,
|
|
17
|
-
beats: Array(mulmoScript.beats.length).
|
|
10
|
+
beats: [...Array(mulmoScript.beats.length)].map(() => ({})),
|
|
18
11
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
source: {
|
|
30
|
-
kind: "url",
|
|
31
|
-
url: "https://github.com/receptron/mulmocast-cli/raw/refs/heads/main/assets/images/mulmocast_credit.png",
|
|
32
|
-
},
|
|
12
|
+
};
|
|
13
|
+
const mulmoCredit = (speaker) => {
|
|
14
|
+
return {
|
|
15
|
+
speaker,
|
|
16
|
+
text: "",
|
|
17
|
+
image: {
|
|
18
|
+
type: "image",
|
|
19
|
+
source: {
|
|
20
|
+
kind: "url",
|
|
21
|
+
url: "https://github.com/receptron/mulmocast-cli/raw/refs/heads/main/assets/images/mulmocast_credit.png",
|
|
33
22
|
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
},
|
|
24
|
+
audio: {
|
|
25
|
+
type: "audio",
|
|
26
|
+
source: {
|
|
27
|
+
kind: "url",
|
|
28
|
+
url: "https://github.com/receptron/mulmocast-cli/raw/refs/heads/main/assets/audio/silent300.mp3",
|
|
40
29
|
},
|
|
41
|
-
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export const createOrUpdateStudioData = (_mulmoScript, currentStudio, fileName) => {
|
|
34
|
+
const mulmoScript = _mulmoScript.__test_invalid__ ? _mulmoScript : mulmoScriptSchema.parse(_mulmoScript); // validate and insert default value
|
|
35
|
+
const studio = rebuildStudio(currentStudio, mulmoScript, fileName);
|
|
36
|
+
// Addition cloing credit
|
|
37
|
+
if (mulmoScript.$mulmocast.credit === "closing") {
|
|
38
|
+
mulmoScript.beats.push(mulmoCredit(mulmoScript.beats[0].speaker)); // First speaker
|
|
42
39
|
}
|
|
43
|
-
studio.script = mulmoScript; // update the script
|
|
44
|
-
studio.beats
|
|
40
|
+
studio.script = mulmoScriptSchema.parse(mulmoScript); // update the script
|
|
41
|
+
studio.beats = studio.script.beats.map((_, index) => studio.beats[index] ?? {});
|
|
45
42
|
mulmoScript.beats.forEach((beat, index) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const hash_string = `${beat.text}${voiceId}${speechOptions?.instruction ?? ""}${speechOptions?.speed ?? 1.0}`;
|
|
49
|
-
studio.beats[index] = { ...studio.beats[index], ...beat, audioFile: `${fileName}_${index}_${(0, text_hash_1.text2hash)(hash_string)}` };
|
|
43
|
+
// Filling the default values
|
|
44
|
+
studio.script.beats[index] = mulmoBeatSchema.parse(beat);
|
|
50
45
|
});
|
|
51
46
|
return studio;
|
|
52
47
|
};
|
|
53
|
-
exports.createOrUpdateStudioData = createOrUpdateStudioData;
|
package/lib/utils/string.js
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.replacementsJa = exports.recursiveSplitJa = void 0;
|
|
4
|
-
exports.splitIntoSentencesJa = splitIntoSentencesJa;
|
|
5
|
-
exports.replacePairsJa = replacePairsJa;
|
|
6
1
|
// split ja
|
|
7
|
-
function splitIntoSentencesJa(paragraph, divider, minimum) {
|
|
2
|
+
export function splitIntoSentencesJa(paragraph, divider, minimum) {
|
|
8
3
|
const sentences = paragraph
|
|
9
4
|
.split(divider) // Split by the Japanese full stop
|
|
10
5
|
.map((sentence) => sentence.trim()) // Trim whitespace
|
|
@@ -21,7 +16,7 @@ function splitIntoSentencesJa(paragraph, divider, minimum) {
|
|
|
21
16
|
}, [])
|
|
22
17
|
.map((sentence, index, array) => (index < array.length - 1 || paragraph.endsWith(divider) ? sentence + divider : sentence));
|
|
23
18
|
}
|
|
24
|
-
const recursiveSplitJa = (text) => {
|
|
19
|
+
export const recursiveSplitJa = (text) => {
|
|
25
20
|
const delimiters = ["。", "?", "!", "、"];
|
|
26
21
|
return delimiters
|
|
27
22
|
.reduce((textData, delimiter) => {
|
|
@@ -29,8 +24,7 @@ const recursiveSplitJa = (text) => {
|
|
|
29
24
|
}, [text])
|
|
30
25
|
.flat(1);
|
|
31
26
|
};
|
|
32
|
-
|
|
33
|
-
function replacePairsJa(str, replacements) {
|
|
27
|
+
export function replacePairsJa(str, replacements) {
|
|
34
28
|
replacements.forEach(({ from, to }) => {
|
|
35
29
|
// Escape any special regex characters in the 'from' string.
|
|
36
30
|
const escapedFrom = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -39,7 +33,7 @@ function replacePairsJa(str, replacements) {
|
|
|
39
33
|
});
|
|
40
34
|
return str;
|
|
41
35
|
}
|
|
42
|
-
|
|
36
|
+
export const replacementsJa = [
|
|
43
37
|
{ from: "Anthropic", to: "アンスロピック" },
|
|
44
38
|
{ from: "OpenAI", to: "オープンエーアイ" },
|
|
45
39
|
{ from: "AGI", to: "エージーアイ" },
|
package/lib/utils/text_hash.js
CHANGED
|
@@ -1,41 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.text2hash = void 0;
|
|
37
|
-
const crypto = __importStar(require("crypto"));
|
|
38
|
-
const text2hash = (input) => {
|
|
1
|
+
import * as crypto from "crypto";
|
|
2
|
+
export const text2hash = (input) => {
|
|
39
3
|
return crypto.createHash("sha256").update(input).digest("hex");
|
|
40
4
|
};
|
|
41
|
-
exports.text2hash = text2hash;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const llmAgents: string[];
|
|
2
|
+
type LLMAgent = (typeof llmAgents)[number];
|
|
3
|
+
export declare const defaultOpenAIModel: string;
|
|
4
|
+
export declare const llmPair: (_agent?: LLMAgent, _model?: string) => {
|
|
5
|
+
agent: string;
|
|
6
|
+
model: string;
|
|
7
|
+
max_tokens: number;
|
|
8
|
+
};
|
|
9
|
+
export declare const chunkArray: <T>(array: T[], size?: number) => T[][];
|
|
10
|
+
export declare const isHttp: (fileOrUrl: string) => boolean;
|
|
11
|
+
export declare const text2hash: (input: string) => string;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as crypto from "crypto";
|
|
2
|
+
export const llmAgents = ["openAIAgent", "anthropicAgent", "geminiAgent", "groqAgent"];
|
|
3
|
+
const defaultModels = {
|
|
4
|
+
anthropicAgent: "claude-3-7-sonnet-20250219",
|
|
5
|
+
geminiAgent: "gemini-1.5-flash",
|
|
6
|
+
groqAgent: "llama3-8b-8192",
|
|
7
|
+
openAIAgent: "gpt-4o",
|
|
8
|
+
};
|
|
9
|
+
const longMaxTokens = {
|
|
10
|
+
anthropicAgent: 8192,
|
|
11
|
+
geminiAgent: 8192,
|
|
12
|
+
groqAgent: 4096,
|
|
13
|
+
openAIAgent: 8192,
|
|
14
|
+
};
|
|
15
|
+
export const defaultOpenAIModel = defaultModels["openAIAgent"];
|
|
16
|
+
export const llmPair = (_agent, _model) => {
|
|
17
|
+
const agent = _agent && llmAgents.includes(_agent ?? "") ? _agent : "openAIAgent";
|
|
18
|
+
const model = _model ?? defaultModels[agent ?? ""];
|
|
19
|
+
const max_tokens = longMaxTokens[agent];
|
|
20
|
+
return { agent, model, max_tokens };
|
|
21
|
+
};
|
|
22
|
+
export const chunkArray = (array, size = 3) => {
|
|
23
|
+
const chunks = [];
|
|
24
|
+
const copy = [...array];
|
|
25
|
+
while (copy.length)
|
|
26
|
+
chunks.push(copy.splice(0, size));
|
|
27
|
+
return chunks;
|
|
28
|
+
};
|
|
29
|
+
export const isHttp = (fileOrUrl) => {
|
|
30
|
+
return /^https?:\/\//.test(fileOrUrl);
|
|
31
|
+
};
|
|
32
|
+
export const text2hash = (input) => {
|
|
33
|
+
return crypto.createHash("sha256").update(input).digest("hex");
|
|
34
|
+
};
|