mulmocast 2.1.14 → 2.1.16
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-portrait.png +0 -0
- package/lib/actions/audio.js +1 -1
- package/lib/actions/bundle.d.ts +4 -1
- package/lib/actions/bundle.js +37 -21
- package/lib/actions/translate.js +1 -1
- package/lib/agents/image_genai_agent.js +2 -2
- package/lib/agents/image_openai_agent.js +1 -1
- package/lib/agents/image_replicate_agent.js +1 -1
- package/lib/agents/lipsync_replicate_agent.js +1 -1
- package/lib/agents/movie_genai_agent.js +2 -2
- package/lib/agents/movie_replicate_agent.js +1 -1
- package/lib/agents/sound_effect_replicate_agent.js +1 -1
- package/lib/agents/tts_elevenlabs_agent.js +1 -1
- package/lib/agents/tts_gemini_agent.js +1 -1
- package/lib/agents/tts_kotodama_agent.js +1 -1
- package/lib/agents/tts_openai_agent.js +5 -2
- package/lib/cli/commands/bundle/handler.js +1 -1
- package/lib/cli/commands/movie/builder.js +1 -1
- package/lib/cli/commands/pdf/builder.js +1 -1
- package/lib/cli/commands/tool/scripting/builder.js +1 -1
- package/lib/cli/commands/tool/scripting/handler.d.ts +1 -1
- package/lib/cli/commands/tool/scripting/handler.js +1 -1
- package/lib/cli/commands/tool/story_to_script/builder.js +2 -2
- package/lib/cli/commands/tool/story_to_script/handler.d.ts +1 -1
- package/lib/cli/commands/tool/story_to_script/handler.js +1 -1
- package/lib/cli/common.js +1 -1
- package/lib/cli/helpers.js +1 -1
- package/lib/data/scriptTemplates.js +2 -2
- package/lib/data/templateDataSet.js +1 -1
- package/lib/index.common.d.ts +2 -2
- package/lib/index.common.js +2 -2
- package/lib/mcp/server.js +1 -1
- package/lib/methods/mulmo_presentation_style.d.ts +6 -6
- package/lib/methods/mulmo_presentation_style.js +1 -1
- package/lib/methods/mulmo_studio_context.d.ts +1 -1
- package/lib/tools/story_to_script.d.ts +1 -1
- package/lib/tools/story_to_script.js +1 -1
- package/lib/types/agent.d.ts +1 -0
- package/lib/types/const.d.ts +15 -0
- package/lib/types/const.js +15 -0
- package/lib/types/provider2agent.d.ts +191 -0
- package/lib/types/provider2agent.js +326 -0
- package/lib/types/schema.js +2 -2
- package/lib/types/type.d.ts +2 -2
- package/lib/utils/context.js +5 -3
- package/lib/utils/utils.d.ts +1 -1
- package/lib/utils/utils.js +1 -1
- package/package.json +5 -5
- package/scripts/templates/html.json +1 -1
- package/scripts/templates/presentation.json +1 -1
- package/scripts/test/test_en_portrait.json +31 -0
- package/scripts/test/test_en_portrait.json~ +31 -0
|
Binary file
|
package/lib/actions/audio.js
CHANGED
|
@@ -8,7 +8,7 @@ import { fileCacheAgentFilter, nijovoiceTextAgentFilter } from "../utils/filters
|
|
|
8
8
|
import { getAudioArtifactFilePath, getAudioFilePath, getOutputStudioFilePath, resolveDirPath, defaultBGMPath, mkdir, writingMessage } from "../utils/file.js";
|
|
9
9
|
import { localizedText, settings2GraphAIConfig } from "../utils/utils.js";
|
|
10
10
|
import { text2hash } from "../utils/utils_node.js";
|
|
11
|
-
import { provider2TTSAgent } from "../
|
|
11
|
+
import { provider2TTSAgent } from "../types/provider2agent.js";
|
|
12
12
|
import { invalidAudioSourceError } from "../utils/error_cause.js";
|
|
13
13
|
import { MulmoStudioContextMethods } from "../methods/mulmo_studio_context.js";
|
|
14
14
|
import { MulmoMediaSourceMethods } from "../methods/mulmo_media_source.js";
|
package/lib/actions/bundle.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { type MulmoStudioContext } from "../types/index.js";
|
|
2
|
-
export
|
|
2
|
+
export type MulmoViewerBundleOptions = {
|
|
3
|
+
skipZip?: boolean;
|
|
4
|
+
};
|
|
5
|
+
export declare const mulmoViewerBundle: (context: MulmoStudioContext, options?: MulmoViewerBundleOptions) => Promise<void>;
|
package/lib/actions/bundle.js
CHANGED
|
@@ -4,7 +4,7 @@ import { GraphAILogger } from "graphai";
|
|
|
4
4
|
import { listLocalizedAudioPaths } from "./audio.js";
|
|
5
5
|
import { mkdir } from "../utils/file.js";
|
|
6
6
|
import { ZipBuilder } from "../utils/zip.js";
|
|
7
|
-
import { bundleTargetLang } from "../
|
|
7
|
+
import { bundleTargetLang } from "../types/const.js";
|
|
8
8
|
import { createSilentAudio } from "../utils/ffmpeg_utils.js";
|
|
9
9
|
import { silentMp3 } from "../utils/context.js";
|
|
10
10
|
const downloadFile = async (url, destPath) => {
|
|
@@ -27,9 +27,12 @@ const processBgm = async (bgm, outDir, baseDir, zipper) => {
|
|
|
27
27
|
return undefined;
|
|
28
28
|
}
|
|
29
29
|
const fileName = path.basename(bgm.path);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
if (zipper) {
|
|
31
|
+
zipper.addFile(sourcePath, fileName);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
fs.copyFileSync(sourcePath, path.resolve(outDir, fileName));
|
|
35
|
+
}
|
|
33
36
|
return fileName;
|
|
34
37
|
}
|
|
35
38
|
else if (bgm.kind === "url") {
|
|
@@ -37,7 +40,7 @@ const processBgm = async (bgm, outDir, baseDir, zipper) => {
|
|
|
37
40
|
const fileName = path.basename(new URL(bgm.url).pathname) || "bgm.mp3";
|
|
38
41
|
const destPath = path.resolve(outDir, fileName);
|
|
39
42
|
await downloadFile(bgm.url, destPath);
|
|
40
|
-
zipper
|
|
43
|
+
zipper?.addFile(destPath);
|
|
41
44
|
return fileName;
|
|
42
45
|
}
|
|
43
46
|
// base64 or other formats are not supported
|
|
@@ -52,12 +55,16 @@ const imageSourceMappings = [
|
|
|
52
55
|
["lipSyncFile", "videoWithAudioSource"],
|
|
53
56
|
["htmlImageFile", "htmlImageSource"],
|
|
54
57
|
];
|
|
55
|
-
export const mulmoViewerBundle = async (context) => {
|
|
56
|
-
const
|
|
58
|
+
export const mulmoViewerBundle = async (context, options = {}) => {
|
|
59
|
+
const { skipZip = false } = options;
|
|
57
60
|
const outDir = context.fileDirs.outDirPath;
|
|
58
61
|
const baseDir = context.fileDirs.baseDirPath;
|
|
62
|
+
const filename = context.studio.filename;
|
|
59
63
|
mkdir(outDir);
|
|
60
|
-
|
|
64
|
+
// Bundle directory: output/<script_name>/
|
|
65
|
+
const bundleDir = path.resolve(outDir, filename);
|
|
66
|
+
mkdir(bundleDir);
|
|
67
|
+
const zipper = skipZip ? undefined : new ZipBuilder(path.resolve(bundleDir, zipFileName));
|
|
61
68
|
// text
|
|
62
69
|
const resultJson = [];
|
|
63
70
|
context.studio.script.beats.forEach((beat, index) => {
|
|
@@ -77,13 +84,17 @@ export const mulmoViewerBundle = async (context) => {
|
|
|
77
84
|
}
|
|
78
85
|
if (fileName === "silent300.mp3") {
|
|
79
86
|
// Download from GitHub URL
|
|
80
|
-
const destPath = path.resolve(
|
|
87
|
+
const destPath = path.resolve(bundleDir, fileName);
|
|
81
88
|
await downloadFile(silentMp3, destPath);
|
|
82
|
-
zipper
|
|
89
|
+
zipper?.addFile(destPath, fileName);
|
|
83
90
|
}
|
|
84
91
|
else if (fs.existsSync(audio)) {
|
|
85
|
-
|
|
86
|
-
|
|
92
|
+
if (zipper) {
|
|
93
|
+
zipper.addFile(audio, fileName);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
fs.copyFileSync(audio, path.resolve(bundleDir, fileName));
|
|
97
|
+
}
|
|
87
98
|
}
|
|
88
99
|
}
|
|
89
100
|
}));
|
|
@@ -96,13 +107,17 @@ export const mulmoViewerBundle = async (context) => {
|
|
|
96
107
|
if (typeof value === "string") {
|
|
97
108
|
data[source] = path.basename(value);
|
|
98
109
|
if (fs.existsSync(value)) {
|
|
99
|
-
|
|
100
|
-
|
|
110
|
+
if (zipper) {
|
|
111
|
+
zipper.addFile(value);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
fs.copyFileSync(value, path.resolve(bundleDir, path.basename(value)));
|
|
115
|
+
}
|
|
101
116
|
}
|
|
102
117
|
}
|
|
103
118
|
});
|
|
104
119
|
});
|
|
105
|
-
// silent
|
|
120
|
+
// silent - generated files always go to bundleDir
|
|
106
121
|
await Promise.all(context.studio.script.beats.map(async (__, index) => {
|
|
107
122
|
const data = resultJson[index];
|
|
108
123
|
if (data.audioSources &&
|
|
@@ -111,9 +126,9 @@ export const mulmoViewerBundle = async (context) => {
|
|
|
111
126
|
data.videoWithAudioSource === undefined &&
|
|
112
127
|
data.duration) {
|
|
113
128
|
const file = `silent_${index}.mp3`;
|
|
114
|
-
const audioFile = path.resolve(
|
|
129
|
+
const audioFile = path.resolve(bundleDir, file);
|
|
115
130
|
await createSilentAudio(audioFile, data.duration);
|
|
116
|
-
zipper
|
|
131
|
+
zipper?.addFile(audioFile);
|
|
117
132
|
data.audioSources.ja = file;
|
|
118
133
|
data.audioSources.en = file;
|
|
119
134
|
}
|
|
@@ -127,11 +142,12 @@ export const mulmoViewerBundle = async (context) => {
|
|
|
127
142
|
});
|
|
128
143
|
});
|
|
129
144
|
// BGM
|
|
130
|
-
const bgmFileName = await processBgm(context.studio?.script.audioParams?.bgm,
|
|
145
|
+
const bgmFileName = await processBgm(context.studio?.script.audioParams?.bgm, bundleDir, baseDir, zipper);
|
|
131
146
|
const bundleData = { beats: resultJson, bgmSource: bgmFileName, title: context.studio.script.title };
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
147
|
+
const viewJsonPath = path.resolve(bundleDir, viewJsonFileName);
|
|
148
|
+
fs.writeFileSync(viewJsonPath, JSON.stringify(bundleData, null, 2));
|
|
149
|
+
zipper?.addFile(viewJsonPath);
|
|
150
|
+
if (zipper) {
|
|
135
151
|
await zipper.finalize();
|
|
136
152
|
}
|
|
137
153
|
};
|
package/lib/actions/translate.js
CHANGED
|
@@ -7,7 +7,7 @@ import { fileWriteAgent } from "@graphai/vanilla_node_agents";
|
|
|
7
7
|
import { splitText } from "../utils/string.js";
|
|
8
8
|
import { settings2GraphAIConfig, beatId, multiLingualObjectToArray } from "../utils/utils.js";
|
|
9
9
|
import { getMultiLingual } from "../utils/context.js";
|
|
10
|
-
import { currentMulmoScriptVersion } from "../
|
|
10
|
+
import { currentMulmoScriptVersion } from "../types/const.js";
|
|
11
11
|
import { translateApiKeyMissingError, hasCause, agentGenerationError, translateAction, multiLingualFileTarget } from "../utils/error_cause.js";
|
|
12
12
|
import { getOutputMultilingualFilePath, mkdir, writingMessage, hashSHA256 } from "../utils/file.js";
|
|
13
13
|
import { translateSystemPrompt, translatePrompts } from "../utils/prompt.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import { GraphAILogger } from "graphai";
|
|
3
|
-
import { provider2ImageAgent } from "../
|
|
3
|
+
import { provider2ImageAgent } from "../types/provider2agent.js";
|
|
4
4
|
import { apiKeyMissingError, agentIncorrectAPIKeyError, agentGenerationError, agentInvalidResponseError, imageAction, imageFileTarget, hasCause, getGenAIErrorReason, resultify, } from "../utils/error_cause.js";
|
|
5
5
|
import { getAspectRatio } from "../utils/utils.js";
|
|
6
|
-
import { ASPECT_RATIOS, PRO_ASPECT_RATIOS } from "../
|
|
6
|
+
import { ASPECT_RATIOS, PRO_ASPECT_RATIOS } from "../types/const.js";
|
|
7
7
|
import { GoogleGenAI, PersonGeneration } from "@google/genai";
|
|
8
8
|
const getGeminiContents = (prompt, referenceImages) => {
|
|
9
9
|
const contents = [{ text: prompt }];
|
|
@@ -2,7 +2,7 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { GraphAILogger } from "graphai";
|
|
4
4
|
import OpenAI, { toFile, AuthenticationError, RateLimitError, APIError } from "openai";
|
|
5
|
-
import { provider2ImageAgent, gptImages } from "../
|
|
5
|
+
import { provider2ImageAgent, gptImages } from "../types/provider2agent.js";
|
|
6
6
|
import { apiKeyMissingError, agentGenerationError, openAIAgentGenerationError, agentIncorrectAPIKeyError, agentAPIRateLimitError, agentInvalidResponseError, imageAction, imageFileTarget, } from "../utils/error_cause.js";
|
|
7
7
|
// https://platform.openai.com/docs/guides/image-generation
|
|
8
8
|
export const imageOpenaiAgent = async ({ namedInputs, params, config, }) => {
|
|
@@ -3,7 +3,7 @@ import { GraphAILogger } from "graphai";
|
|
|
3
3
|
import Replicate from "replicate";
|
|
4
4
|
import { getAspectRatio } from "./movie_replicate_agent.js";
|
|
5
5
|
import { apiKeyMissingError, agentIncorrectAPIKeyError, agentGenerationError, agentInvalidResponseError, imageAction, imageFileTarget, hasCause, } from "../utils/error_cause.js";
|
|
6
|
-
import { provider2ImageAgent } from "../
|
|
6
|
+
import { provider2ImageAgent } from "../types/provider2agent.js";
|
|
7
7
|
export const imageReplicateAgent = async ({ namedInputs, params, config, }) => {
|
|
8
8
|
const { prompt, referenceImages } = namedInputs;
|
|
9
9
|
const { canvasSize } = params;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from "fs";
|
|
2
2
|
import { GraphAILogger } from "graphai";
|
|
3
3
|
import Replicate from "replicate";
|
|
4
|
-
import { provider2LipSyncAgent } from "../
|
|
4
|
+
import { provider2LipSyncAgent } from "../types/provider2agent.js";
|
|
5
5
|
import { apiKeyMissingError, agentGenerationError, agentFileNotExistError, imageAction, movieFileTarget, audioFileTarget, hasCause, } from "../utils/error_cause.js";
|
|
6
6
|
export const lipSyncReplicateAgent = async ({ namedInputs, params, config, }) => {
|
|
7
7
|
const { movieFile, audioFile, imageFile } = namedInputs;
|
|
@@ -3,8 +3,8 @@ import { GraphAILogger, sleep } from "graphai";
|
|
|
3
3
|
import { GoogleGenAI, PersonGeneration } from "@google/genai";
|
|
4
4
|
import { apiKeyMissingError, agentGenerationError, agentInvalidResponseError, imageAction, movieFileTarget, videoDurationTarget, hasCause, } from "../utils/error_cause.js";
|
|
5
5
|
import { getAspectRatio } from "../utils/utils.js";
|
|
6
|
-
import { ASPECT_RATIOS } from "../
|
|
7
|
-
import { getModelDuration, provider2MovieAgent } from "../
|
|
6
|
+
import { ASPECT_RATIOS } from "../types/const.js";
|
|
7
|
+
import { getModelDuration, provider2MovieAgent } from "../types/provider2agent.js";
|
|
8
8
|
const pollUntilDone = async (ai, operation) => {
|
|
9
9
|
const response = { operation };
|
|
10
10
|
while (!response.operation.done) {
|
|
@@ -2,7 +2,7 @@ import { readFileSync } from "fs";
|
|
|
2
2
|
import { GraphAILogger } from "graphai";
|
|
3
3
|
import Replicate from "replicate";
|
|
4
4
|
import { apiKeyMissingError, agentGenerationError, agentInvalidResponseError, imageAction, movieFileTarget, videoDurationTarget, unsupportedModelTarget, } from "../utils/error_cause.js";
|
|
5
|
-
import { provider2MovieAgent, getModelDuration } from "../
|
|
5
|
+
import { provider2MovieAgent, getModelDuration } from "../types/provider2agent.js";
|
|
6
6
|
async function generateMovie(model, apiKey, prompt, imagePath, aspectRatio, duration) {
|
|
7
7
|
const replicate = new Replicate({
|
|
8
8
|
auth: apiKey,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "fs";
|
|
2
2
|
import { GraphAILogger } from "graphai";
|
|
3
3
|
import Replicate from "replicate";
|
|
4
|
-
import { provider2SoundEffectAgent } from "../
|
|
4
|
+
import { provider2SoundEffectAgent } from "../types/provider2agent.js";
|
|
5
5
|
import { apiKeyMissingError, agentGenerationError, imageAction, movieFileTarget, hasCause } from "../utils/error_cause.js";
|
|
6
6
|
export const soundEffectReplicateAgent = async ({ namedInputs, params, config }) => {
|
|
7
7
|
const { prompt, movieFile } = namedInputs;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GraphAILogger } from "graphai";
|
|
2
|
-
import { provider2TTSAgent } from "../
|
|
2
|
+
import { provider2TTSAgent } from "../types/provider2agent.js";
|
|
3
3
|
import { apiKeyMissingError, agentVoiceLimitReachedError, agentIncorrectAPIKeyError, agentGenerationError, audioAction, audioFileTarget, } from "../utils/error_cause.js";
|
|
4
4
|
export const ttsElevenlabsAgent = async ({ namedInputs, params, config, }) => {
|
|
5
5
|
const { text } = namedInputs;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GraphAILogger } from "graphai";
|
|
2
2
|
import { GoogleGenAI } from "@google/genai";
|
|
3
|
-
import { provider2TTSAgent } from "../
|
|
3
|
+
import { provider2TTSAgent } from "../types/provider2agent.js";
|
|
4
4
|
import { agentIncorrectAPIKeyError, apiKeyMissingError, agentGenerationError, audioAction, audioFileTarget, getGenAIErrorReason, } from "../utils/error_cause.js";
|
|
5
5
|
import { pcmToMp3 } from "../utils/ffmpeg_utils.js";
|
|
6
6
|
const getPrompt = (text, instructions) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GraphAILogger } from "graphai";
|
|
2
|
-
import { provider2TTSAgent } from "../
|
|
2
|
+
import { provider2TTSAgent } from "../types/provider2agent.js";
|
|
3
3
|
import { apiKeyMissingError, agentIncorrectAPIKeyError, agentGenerationError, audioAction, audioFileTarget } from "../utils/error_cause.js";
|
|
4
4
|
export const ttsKotodamaAgent = async ({ namedInputs, params, config, }) => {
|
|
5
5
|
const { text } = namedInputs;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { GraphAILogger } from "graphai";
|
|
2
2
|
import OpenAI, { AuthenticationError, RateLimitError } from "openai";
|
|
3
|
-
import { provider2TTSAgent } from "../
|
|
3
|
+
import { provider2TTSAgent } from "../types/provider2agent.js";
|
|
4
4
|
import { apiKeyMissingError, agentIncorrectAPIKeyError, agentAPIRateLimitError, agentGenerationError, audioAction, audioFileTarget, } from "../utils/error_cause.js";
|
|
5
5
|
export const ttsOpenaiAgent = async ({ namedInputs, params, config, }) => {
|
|
6
6
|
const { text } = namedInputs;
|
|
7
|
-
const { model, voice, suppressError, instructions } = params;
|
|
7
|
+
const { model, voice, suppressError, instructions, speed } = params;
|
|
8
8
|
const { apiKey, baseURL } = config ?? {};
|
|
9
9
|
if (!apiKey) {
|
|
10
10
|
throw new Error("OpenAI API key is required (OPENAI_API_KEY)", {
|
|
@@ -21,6 +21,9 @@ export const ttsOpenaiAgent = async ({ namedInputs, params, config, }) => {
|
|
|
21
21
|
if (instructions) {
|
|
22
22
|
tts_options["instructions"] = instructions;
|
|
23
23
|
}
|
|
24
|
+
if (speed) {
|
|
25
|
+
tts_options["speed"] = speed;
|
|
26
|
+
}
|
|
24
27
|
GraphAILogger.log("ttsOptions", tts_options);
|
|
25
28
|
const response = await openai.audio.speech.create(tts_options);
|
|
26
29
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mulmoViewerBundle, audio, images, translate } from "../../../actions/index.js";
|
|
2
2
|
import { initializeContext } from "../../helpers.js";
|
|
3
|
-
import { bundleTargetLang } from "../../../
|
|
3
|
+
import { bundleTargetLang } from "../../../types/const.js";
|
|
4
4
|
export const handler = async (argv) => {
|
|
5
5
|
const context = await initializeContext(argv);
|
|
6
6
|
if (!context) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { commonOptions } from "../../common.js";
|
|
2
|
-
import { pdf_modes, pdf_sizes } from "../../../
|
|
2
|
+
import { pdf_modes, pdf_sizes } from "../../../types/const.js";
|
|
3
3
|
export const builder = (yargs) => commonOptions(yargs)
|
|
4
4
|
.option("i", {
|
|
5
5
|
alias: "imagedir",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { llm } from "../../../../
|
|
1
|
+
import { llm } from "../../../../types/provider2agent.js";
|
|
2
2
|
import { getAvailablePromptTemplates } from "../../../../utils/file.js";
|
|
3
3
|
const availableTemplateNames = getAvailablePromptTemplates().map((template) => template.filename);
|
|
4
4
|
export const builder = (yargs) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ToolCliArgs } from "../../../../types/cli_types.js";
|
|
2
|
-
import type { LLM } from "../../../../
|
|
2
|
+
import type { LLM } from "../../../../types/provider2agent.js";
|
|
3
3
|
export declare const handler: (argv: ToolCliArgs<{
|
|
4
4
|
o?: string;
|
|
5
5
|
b?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getBaseDirPath, getFullPath } from "../../../../utils/file.js";
|
|
2
|
-
import { outDirName, cacheDirName } from "../../../../
|
|
2
|
+
import { outDirName, cacheDirName } from "../../../../types/const.js";
|
|
3
3
|
import { getUrlsIfNeeded, selectTemplate } from "../../../../utils/inquirer.js";
|
|
4
4
|
import { createMulmoScriptFromUrl, createMulmoScriptFromFile } from "../../../../tools/create_mulmo_script_from_url.js";
|
|
5
5
|
import { createMulmoScriptInteractively } from "../../../../tools/create_mulmo_script_interactively.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getAvailablePromptTemplates } from "../../../../utils/file.js";
|
|
2
|
-
import { llm } from "../../../../
|
|
3
|
-
import { storyToScriptGenerateMode } from "../../../../
|
|
2
|
+
import { llm } from "../../../../types/provider2agent.js";
|
|
3
|
+
import { storyToScriptGenerateMode } from "../../../../types/const.js";
|
|
4
4
|
const availableTemplateNames = getAvailablePromptTemplates().map((template) => template.filename);
|
|
5
5
|
export const builder = (yargs) => {
|
|
6
6
|
return yargs
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ToolCliArgs } from "../../../../types/cli_types.js";
|
|
2
|
-
import type { LLM } from "../../../../
|
|
2
|
+
import type { LLM } from "../../../../types/provider2agent.js";
|
|
3
3
|
export declare const handler: (argv: ToolCliArgs<{
|
|
4
4
|
o?: string;
|
|
5
5
|
b?: string;
|
|
@@ -3,7 +3,7 @@ import { setGraphAILogger } from "../../../../cli/helpers.js";
|
|
|
3
3
|
import { storyToScript } from "../../../../tools/story_to_script.js";
|
|
4
4
|
import { mulmoStoryboardSchema } from "../../../../types/schema.js";
|
|
5
5
|
import { getBaseDirPath, getFullPath, readAndParseJson } from "../../../../utils/file.js";
|
|
6
|
-
import { outDirName } from "../../../../
|
|
6
|
+
import { outDirName } from "../../../../types/const.js";
|
|
7
7
|
export const handler = async (argv) => {
|
|
8
8
|
const { v: verbose, s: filename, file, o: outdir, b: basedir, beats_per_scene, llm, llm_model, mode } = argv;
|
|
9
9
|
let { t: template } = argv;
|
package/lib/cli/common.js
CHANGED
package/lib/cli/helpers.js
CHANGED
|
@@ -4,7 +4,7 @@ import path from "path";
|
|
|
4
4
|
import clipboardy from "clipboardy";
|
|
5
5
|
import { getBaseDirPath, getFullPath, getOutputStudioFilePath, resolveDirPath, mkdir, getOutputMultilingualFilePath, generateTimestampedFileName, } from "../utils/file.js";
|
|
6
6
|
import { isHttp } from "../utils/utils.js";
|
|
7
|
-
import { outDirName, imageDirName, audioDirName } from "../
|
|
7
|
+
import { outDirName, imageDirName, audioDirName } from "../types/const.js";
|
|
8
8
|
import { MulmoStudioContextMethods } from "../methods/mulmo_studio_context.js";
|
|
9
9
|
import { translate } from "../actions/translate.js";
|
|
10
10
|
import { initializeContextFromFiles } from "../utils/context.js";
|
|
@@ -484,7 +484,7 @@ export const scriptTemplates = [
|
|
|
484
484
|
],
|
|
485
485
|
filename: "html",
|
|
486
486
|
htmlImageParams: {
|
|
487
|
-
model: "claude-
|
|
487
|
+
model: "claude-sonnet-4-5-20250929",
|
|
488
488
|
provider: "anthropic",
|
|
489
489
|
},
|
|
490
490
|
lang: "en",
|
|
@@ -987,7 +987,7 @@ export const scriptTemplates = [
|
|
|
987
987
|
],
|
|
988
988
|
filename: "presentation",
|
|
989
989
|
htmlImageParams: {
|
|
990
|
-
model: "claude-
|
|
990
|
+
model: "claude-sonnet-4-5-20250929",
|
|
991
991
|
provider: "anthropic",
|
|
992
992
|
},
|
|
993
993
|
lang: "en",
|
|
@@ -49,7 +49,7 @@ export const templateDataSet = {
|
|
|
49
49
|
"```",
|
|
50
50
|
html: "Another LLM will generate actual slides from the prompt and data for each beat. Adding optional data would help it to generate more compelling slide. Mention the reference in one of beats, if it exists. The valid type of reference is 'article', 'paper', 'image', 'video', 'audio'. Use the JSON below as a template.\n" +
|
|
51
51
|
"```JSON\n" +
|
|
52
|
-
'{"$mulmocast":{"version":"1.1","credit":"closing"},"references":[{"url":"https://www.somegreatwebsite.com/article/123","title":"Title of the article we are referencing","type":"[TYPE OF ARTICLE: article, paper, image, video, audio]"}],"title":"[TITLE: Brief, engaging title for the topic]","htmlImageParams":{"provider":"anthropic","model":"claude-
|
|
52
|
+
'{"$mulmocast":{"version":"1.1","credit":"closing"},"references":[{"url":"https://www.somegreatwebsite.com/article/123","title":"Title of the article we are referencing","type":"[TYPE OF ARTICLE: article, paper, image, video, audio]"}],"title":"[TITLE: Brief, engaging title for the topic]","htmlImageParams":{"provider":"anthropic","model":"claude-sonnet-4-5-20250929"},"lang":"en","beats":[{"text":"[NARRATION: Narration for the beat.]","htmlPrompt":{"prompt":"[PROMPT to create appropriate HTML page for the beat.]"}},{"text":"[NARRATION: Narration for the beat.]","htmlPrompt":{"prompt":"[PROMPT to create appropriate HTML page for the beat with the data.]","data":{"description":"DATA TO BE PRESENTED IN THIS BEAT (in any format)]","net_income":{"Q2 FY2024":320,"Q3 FY2024":333,"Q4 FY2024":350},"unit":"USD (Million)"}}}],"canvasSize":{"width":1536,"height":1024}}\n' +
|
|
53
53
|
"```",
|
|
54
54
|
image_prompt: "Another AI will generate images for each beat based on the image prompt of that beat. Movie prompts must be written in English. Mention the reference in one of beats, if it exists. Use the JSON below as a template.\n" +
|
|
55
55
|
"```JSON\n" +
|
package/lib/index.common.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./types/index.js";
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
2
|
+
export * from "./types/provider2agent.js";
|
|
3
|
+
export * from "./types/const.js";
|
|
4
4
|
export * from "./utils/string.js";
|
|
5
5
|
export * from "./utils/utils.js";
|
|
6
6
|
export * from "./utils/prompt.js";
|
package/lib/index.common.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Entry point for universal code
|
|
2
2
|
export * from "./types/index.js";
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
3
|
+
export * from "./types/provider2agent.js";
|
|
4
|
+
export * from "./types/const.js";
|
|
5
5
|
export * from "./utils/string.js";
|
|
6
6
|
export * from "./utils/utils.js";
|
|
7
7
|
export * from "./utils/prompt.js";
|
package/lib/mcp/server.js
CHANGED
|
@@ -9,7 +9,7 @@ import { fileURLToPath } from "url";
|
|
|
9
9
|
import { GraphAILogger } from "graphai";
|
|
10
10
|
import { audio, images, movie, captions, pdf } from "../actions/index.js";
|
|
11
11
|
import { initializeContext, runTranslateIfNeeded } from "../cli/helpers.js";
|
|
12
|
-
import { outDirName } from "../
|
|
12
|
+
import { outDirName } from "../types/const.js";
|
|
13
13
|
import { resolveDirPath, mkdir, generateTimestampedFileName } from "../utils/file.js";
|
|
14
14
|
import { MulmoScriptMethods } from "../methods/index.js";
|
|
15
15
|
dotenv.config({ quiet: true });
|
|
@@ -177,19 +177,19 @@ export declare const MulmoPresentationStyleMethods: {
|
|
|
177
177
|
};
|
|
178
178
|
getSoundEffectAgentInfo(presentationStyle: MulmoPresentationStyle, beat: MulmoBeat): {
|
|
179
179
|
agentName: string;
|
|
180
|
-
defaultModel: import("../
|
|
180
|
+
defaultModel: import("../types/provider2agent.js").ReplicateModel;
|
|
181
181
|
keyName: string;
|
|
182
|
-
models: import("../
|
|
183
|
-
modelParams: Record<import("../
|
|
182
|
+
models: import("../types/provider2agent.js").ReplicateModel[];
|
|
183
|
+
modelParams: Record<import("../types/provider2agent.js").ReplicateModel, {
|
|
184
184
|
identifier?: `${string}/${string}:${string}`;
|
|
185
185
|
}>;
|
|
186
186
|
};
|
|
187
187
|
getLipSyncAgentInfo(presentationStyle: MulmoPresentationStyle, beat: MulmoBeat): {
|
|
188
188
|
agentName: string;
|
|
189
|
-
defaultModel: import("../
|
|
189
|
+
defaultModel: import("../types/provider2agent.js").ReplicateModel;
|
|
190
190
|
keyName: string;
|
|
191
|
-
models: import("../
|
|
192
|
-
modelParams: Record<import("../
|
|
191
|
+
models: import("../types/provider2agent.js").ReplicateModel[];
|
|
192
|
+
modelParams: Record<import("../types/provider2agent.js").ReplicateModel, {
|
|
193
193
|
identifier?: `${string}/${string}:${string}` | `${string}/${string}`;
|
|
194
194
|
video?: string;
|
|
195
195
|
audio: string;
|
|
@@ -6,7 +6,7 @@
|
|
|
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 "../
|
|
9
|
+
import { provider2ImageAgent, provider2MovieAgent, provider2LLMAgent, 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
12
|
"body { margin: 60px; margin-top: 40px; color:#333; font-size: 30px; font-family: Arial, sans-serif; box-sizing: border-box; height: 100vh }",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Works in both Node.js and modern browsers.
|
|
5
5
|
*/
|
|
6
6
|
import { BeatSessionType, MulmoStudioContext, SessionProgressCallback, SessionType, MulmoBeat, SpeechOptions } from "../types/index.js";
|
|
7
|
-
import { provider2TTSAgent } from "../
|
|
7
|
+
import { provider2TTSAgent } from "../types/provider2agent.js";
|
|
8
8
|
export declare const addSessionProgressCallback: (cb: SessionProgressCallback) => void;
|
|
9
9
|
export declare const removeSessionProgressCallback: (cb: SessionProgressCallback) => void;
|
|
10
10
|
export declare const MulmoStudioContextMethods: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MulmoStoryboard, StoryToScriptGenerateMode } from "../types/index.js";
|
|
2
|
-
import type { LLM } from "../
|
|
2
|
+
import type { LLM } from "../types/provider2agent.js";
|
|
3
3
|
export declare const storyToScript: ({ story, beatsPerScene, templateName, outdir, fileName, llm, llmModel, generateMode, }: {
|
|
4
4
|
story: MulmoStoryboard;
|
|
5
5
|
beatsPerScene: number;
|
|
@@ -10,7 +10,7 @@ import { graphDataScriptGeneratePrompt, sceneToBeatsPrompt, storyToScriptInfoPro
|
|
|
10
10
|
import { fileWriteAgent } from "@graphai/vanilla_node_agents";
|
|
11
11
|
import validateSchemaAgent from "../agents/validate_schema_agent.js";
|
|
12
12
|
import { llmPair } from "../utils/utils.js";
|
|
13
|
-
import { storyToScriptGenerateMode } from "../
|
|
13
|
+
import { storyToScriptGenerateMode } from "../types/const.js";
|
|
14
14
|
import { cliLoadingPlugin } from "../utils/plugins.js";
|
|
15
15
|
const vanillaAgents = agents.default ?? agents;
|
|
16
16
|
const createValidatedScriptGraphData = ({ systemPrompt, prompt, schema, llmAgent, llmModel, maxTokens, }) => {
|
package/lib/types/agent.d.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const currentMulmoScriptVersion = "1.1";
|
|
2
|
+
export declare const outDirName = "output";
|
|
3
|
+
export declare const audioDirName = "audio";
|
|
4
|
+
export declare const imageDirName = "images";
|
|
5
|
+
export declare const cacheDirName = "cache";
|
|
6
|
+
export declare const pdf_modes: string[];
|
|
7
|
+
export declare const pdf_sizes: string[];
|
|
8
|
+
export declare const languages: string[];
|
|
9
|
+
export declare const storyToScriptGenerateMode: {
|
|
10
|
+
stepWise: string;
|
|
11
|
+
oneStep: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const bundleTargetLang: string[];
|
|
14
|
+
export declare const ASPECT_RATIOS: string[];
|
|
15
|
+
export declare const PRO_ASPECT_RATIOS: string[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const currentMulmoScriptVersion = "1.1";
|
|
2
|
+
export const outDirName = "output";
|
|
3
|
+
export const audioDirName = "audio";
|
|
4
|
+
export const imageDirName = "images";
|
|
5
|
+
export const cacheDirName = "cache";
|
|
6
|
+
export const pdf_modes = ["slide", "talk", "handout"];
|
|
7
|
+
export const pdf_sizes = ["letter", "a4"];
|
|
8
|
+
export const languages = ["en", "ja", "fr", "es", "de", "zh-CN", "zh-TW", "ko", "it", "pt", "ar", "hi"];
|
|
9
|
+
export const storyToScriptGenerateMode = {
|
|
10
|
+
stepWise: "step_wise",
|
|
11
|
+
oneStep: "one_step",
|
|
12
|
+
};
|
|
13
|
+
export const bundleTargetLang = ["ja", "en"];
|
|
14
|
+
export const ASPECT_RATIOS = ["1:1", "9:16", "16:9"];
|
|
15
|
+
export const PRO_ASPECT_RATIOS = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"];
|