mulmocast 0.0.10 → 0.0.12
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 +18 -3
- package/assets/templates/ghibli_shorts.json +34 -0
- package/assets/templates/shorts.json +18 -0
- package/assets/templates/trailer.json +25 -0
- package/lib/actions/audio.d.ts +2 -1
- package/lib/actions/audio.js +35 -17
- package/lib/actions/captions.js +5 -5
- package/lib/actions/images.d.ts +2 -1
- package/lib/actions/images.js +90 -58
- package/lib/actions/movie.js +53 -16
- package/lib/actions/pdf.js +3 -3
- package/lib/actions/translate.d.ts +2 -1
- package/lib/actions/translate.js +21 -16
- package/lib/agents/combine_audio_files_agent.js +4 -0
- package/lib/agents/image_google_agent.d.ts +4 -1
- package/lib/agents/image_google_agent.js +3 -2
- package/lib/agents/image_openai_agent.d.ts +5 -3
- package/lib/agents/image_openai_agent.js +35 -7
- package/lib/agents/index.d.ts +2 -1
- package/lib/agents/index.js +2 -1
- package/lib/agents/movie_google_agent.d.ts +9 -2
- package/lib/agents/movie_google_agent.js +24 -16
- package/lib/agents/tts_elevenlabs_agent.d.ts +4 -0
- package/lib/agents/tts_elevenlabs_agent.js +60 -0
- package/lib/agents/tts_google_agent.js +1 -1
- package/lib/agents/tts_nijivoice_agent.js +3 -2
- package/lib/agents/tts_openai_agent.js +1 -1
- package/lib/cli/commands/audio/handler.js +4 -1
- package/lib/cli/commands/image/handler.js +4 -1
- package/lib/cli/commands/movie/handler.js +4 -1
- package/lib/cli/commands/pdf/handler.js +4 -1
- package/lib/cli/commands/translate/handler.js +4 -1
- package/lib/cli/helpers.d.ts +3 -3
- package/lib/cli/helpers.js +38 -20
- package/lib/index.d.ts +5 -0
- package/lib/index.js +5 -0
- package/lib/methods/mulmo_media_source.d.ts +1 -0
- package/lib/methods/mulmo_media_source.js +12 -0
- package/lib/methods/mulmo_script.d.ts +1 -1
- package/lib/methods/mulmo_script.js +9 -5
- package/lib/methods/mulmo_studio_context.d.ts +5 -0
- package/lib/methods/mulmo_studio_context.js +23 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +1 -0
- package/lib/types/schema.d.ts +1513 -290
- package/lib/types/schema.js +26 -35
- package/lib/types/type.d.ts +4 -1
- package/lib/utils/file.d.ts +5 -15
- package/lib/utils/file.js +14 -21
- package/lib/utils/filters.js +4 -4
- package/lib/utils/image_plugins/beat.d.ts +4 -0
- package/lib/utils/image_plugins/beat.js +7 -0
- package/lib/utils/image_plugins/image.d.ts +1 -1
- package/lib/utils/image_plugins/index.d.ts +2 -1
- package/lib/utils/image_plugins/index.js +2 -1
- package/lib/utils/image_plugins/movie.d.ts +1 -1
- package/lib/utils/image_plugins/source.js +2 -2
- package/lib/utils/preprocess.d.ts +26 -23
- package/lib/utils/preprocess.js +4 -0
- package/package.json +8 -8
- package/scripts/templates/movie_prompts_no_text_template.json +50 -0
- package/scripts/templates/shorts_template.json +52 -0
package/lib/types/schema.js
CHANGED
|
@@ -20,11 +20,13 @@ export const speechOptionsSchema = z
|
|
|
20
20
|
})
|
|
21
21
|
.strict();
|
|
22
22
|
const speakerIdSchema = z.string();
|
|
23
|
+
export const text2SpeechProviderSchema = z.union([z.literal("openai"), z.literal("nijivoice"), z.literal("google"), z.literal("elevenlabs")]).default("openai");
|
|
23
24
|
const speakerDataSchema = z
|
|
24
25
|
.object({
|
|
25
26
|
displayName: z.record(langSchema, z.string()).optional(),
|
|
26
27
|
voiceId: z.string(),
|
|
27
28
|
speechOptions: speechOptionsSchema.optional(),
|
|
29
|
+
provider: text2SpeechProviderSchema.optional(),
|
|
28
30
|
})
|
|
29
31
|
.strict();
|
|
30
32
|
export const speakerDictionarySchema = z.record(speakerIdSchema, speakerDataSchema);
|
|
@@ -103,6 +105,12 @@ export const mulmoHtmlTailwindMediaSchema = z
|
|
|
103
105
|
html: stringOrStringArray,
|
|
104
106
|
})
|
|
105
107
|
.strict();
|
|
108
|
+
export const mulmoBeatReferenceMediaSchema = z
|
|
109
|
+
.object({
|
|
110
|
+
type: z.literal("beat"),
|
|
111
|
+
id: z.string().optional().describe("Specifies the beat to reference."),
|
|
112
|
+
})
|
|
113
|
+
.strict();
|
|
106
114
|
export const mulmoImageAssetSchema = z.union([
|
|
107
115
|
mulmoMarkdownMediaSchema,
|
|
108
116
|
mulmoWebMediaSchema,
|
|
@@ -116,6 +124,7 @@ export const mulmoImageAssetSchema = z.union([
|
|
|
116
124
|
mulmoChartMediaSchema,
|
|
117
125
|
mulmoMermaidMediaSchema,
|
|
118
126
|
mulmoHtmlTailwindMediaSchema,
|
|
127
|
+
mulmoBeatReferenceMediaSchema,
|
|
119
128
|
]);
|
|
120
129
|
const mulmoAudioMediaSchema = z
|
|
121
130
|
.object({
|
|
@@ -134,7 +143,6 @@ const imageIdSchema = z.string();
|
|
|
134
143
|
export const mulmoImageParamsSchema = z
|
|
135
144
|
.object({
|
|
136
145
|
model: z.string().optional(), // default: provider specific
|
|
137
|
-
size: z.string().optional(), // default: provider specific
|
|
138
146
|
style: z.string().optional(), // optional image style
|
|
139
147
|
moderation: z.string().optional(), // optional image style
|
|
140
148
|
images: z.record(imageIdSchema, mulmoImageMediaSchema).optional(),
|
|
@@ -145,13 +153,6 @@ export const textSlideParamsSchema = z
|
|
|
145
153
|
cssStyles: stringOrStringArray,
|
|
146
154
|
})
|
|
147
155
|
.strict();
|
|
148
|
-
/* TODO: Add something later
|
|
149
|
-
export const videoParamsSchema = z
|
|
150
|
-
.object({
|
|
151
|
-
padding: z.number().optional(), // msec
|
|
152
|
-
})
|
|
153
|
-
.strict();
|
|
154
|
-
*/
|
|
155
156
|
export const beatAudioParamsSchema = z
|
|
156
157
|
.object({
|
|
157
158
|
padding: z.number().optional().describe("Padding between beats"), // seconds
|
|
@@ -164,12 +165,15 @@ export const audioParamsSchema = z
|
|
|
164
165
|
introPadding: z.number().describe("Padding at the beginning of the audio"), // seconds
|
|
165
166
|
closingPadding: z.number().describe("Padding before the last beat"), // seconds
|
|
166
167
|
outroPadding: z.number().describe("Padding at the end of the audio"), // seconds
|
|
168
|
+
bgm: mediaSourceSchema.optional(),
|
|
167
169
|
})
|
|
168
170
|
.strict();
|
|
169
171
|
export const mulmoBeatSchema = z
|
|
170
172
|
.object({
|
|
171
173
|
speaker: speakerIdSchema.default("Presenter"),
|
|
172
|
-
text: z.string().describe("Text to be spoken. If empty, the audio is not generated."),
|
|
174
|
+
text: z.string().default("").describe("Text to be spoken. If empty, the audio is not generated."),
|
|
175
|
+
id: z.string().optional().describe("Unique identifier for the beat."),
|
|
176
|
+
description: z.string().optional(),
|
|
173
177
|
image: mulmoImageAssetSchema.optional(),
|
|
174
178
|
audio: mulmoAudioAssetSchema.optional(),
|
|
175
179
|
duration: z.number().optional().describe("Duration of the beat. Used only when the text is empty"),
|
|
@@ -195,7 +199,6 @@ export const mulmoCastCreditSchema = z
|
|
|
195
199
|
credit: z.literal("closing").optional(),
|
|
196
200
|
})
|
|
197
201
|
.strict();
|
|
198
|
-
export const text2SpeechProviderSchema = z.union([z.literal("openai"), z.literal("nijivoice"), z.literal("google")]).default("openai");
|
|
199
202
|
export const mulmoSpeechParamsSchema = z
|
|
200
203
|
.object({
|
|
201
204
|
provider: text2SpeechProviderSchema, // has default value
|
|
@@ -204,10 +207,15 @@ export const mulmoSpeechParamsSchema = z
|
|
|
204
207
|
.strict();
|
|
205
208
|
export const text2ImageProviderSchema = z.union([z.literal("openai"), z.literal("google")]).default("openai");
|
|
206
209
|
export const text2MovieProviderSchema = z.union([z.literal("openai"), z.literal("google")]).default("google");
|
|
210
|
+
export const mulmoTransitionSchema = z.object({
|
|
211
|
+
type: z.enum(["fade"]),
|
|
212
|
+
duration: z.number().min(0).max(2).default(0.3), // transition duration in seconds
|
|
213
|
+
});
|
|
207
214
|
export const mulmoMovieParamsSchema = z
|
|
208
215
|
.object({
|
|
209
216
|
provider: text2MovieProviderSchema.optional(),
|
|
210
217
|
model: z.string().optional(), // default: provider specific
|
|
218
|
+
transition: mulmoTransitionSchema.optional(),
|
|
211
219
|
})
|
|
212
220
|
.strict();
|
|
213
221
|
export const mulmoPresentationStyleSchema = z.object({
|
|
@@ -231,15 +239,12 @@ export const mulmoPresentationStyleSchema = z.object({
|
|
|
231
239
|
movieParams: mulmoMovieParamsSchema.optional(),
|
|
232
240
|
// for textSlides
|
|
233
241
|
textSlideParams: textSlideParamsSchema.optional(),
|
|
234
|
-
// videoParams: videoParamsSchema.optional(),
|
|
235
242
|
audioParams: audioParamsSchema.default({
|
|
236
243
|
introPadding: 1.0,
|
|
237
244
|
padding: 0.3,
|
|
238
245
|
closingPadding: 0.8,
|
|
239
246
|
outroPadding: 1.0,
|
|
240
247
|
}),
|
|
241
|
-
// TODO: Switch to showCaptions later
|
|
242
|
-
omitCaptions: z.boolean().optional(), // default is false
|
|
243
248
|
});
|
|
244
249
|
export const mulmoReferenceSchema = z.object({
|
|
245
250
|
url: URLStringSchema,
|
|
@@ -284,11 +289,11 @@ export const mulmoSessionStateSchema = z.object({
|
|
|
284
289
|
pdf: z.boolean(),
|
|
285
290
|
}),
|
|
286
291
|
inBeatSession: z.object({
|
|
287
|
-
audio: z.
|
|
288
|
-
image: z.
|
|
289
|
-
movie: z.
|
|
290
|
-
multiLingual: z.
|
|
291
|
-
caption: z.
|
|
292
|
+
audio: z.record(z.number().int(), z.boolean()),
|
|
293
|
+
image: z.record(z.number().int(), z.boolean()),
|
|
294
|
+
movie: z.record(z.number().int(), z.boolean()),
|
|
295
|
+
multiLingual: z.record(z.number().int(), z.boolean()),
|
|
296
|
+
caption: z.record(z.number().int(), z.boolean()),
|
|
292
297
|
}),
|
|
293
298
|
});
|
|
294
299
|
export const mulmoStudioSchema = z
|
|
@@ -297,23 +302,6 @@ export const mulmoStudioSchema = z
|
|
|
297
302
|
filename: z.string(),
|
|
298
303
|
beats: z.array(mulmoStudioBeatSchema).min(1),
|
|
299
304
|
multiLingual: mulmoStudioMultiLingualSchema,
|
|
300
|
-
state: mulmoSessionStateSchema.default({
|
|
301
|
-
inSession: {
|
|
302
|
-
audio: false,
|
|
303
|
-
image: false,
|
|
304
|
-
video: false,
|
|
305
|
-
multiLingual: false,
|
|
306
|
-
caption: false,
|
|
307
|
-
pdf: false,
|
|
308
|
-
},
|
|
309
|
-
inBeatSession: {
|
|
310
|
-
audio: new Set(),
|
|
311
|
-
image: new Set(),
|
|
312
|
-
movie: new Set(),
|
|
313
|
-
multiLingual: new Set(),
|
|
314
|
-
caption: new Set(),
|
|
315
|
-
},
|
|
316
|
-
}),
|
|
317
305
|
})
|
|
318
306
|
.strict();
|
|
319
307
|
export const mulmoScriptTemplateSchema = z
|
|
@@ -325,6 +313,9 @@ export const mulmoScriptTemplateSchema = z
|
|
|
325
313
|
presentationStyle: mulmoPresentationStyleSchema.optional(),
|
|
326
314
|
})
|
|
327
315
|
.strict();
|
|
316
|
+
export const mulmoScriptTemplateFileSchema = mulmoScriptTemplateSchema.extend({
|
|
317
|
+
filename: z.string(),
|
|
318
|
+
});
|
|
328
319
|
export const mulmoStoryboardSceneSchema = z
|
|
329
320
|
.object({
|
|
330
321
|
description: z.string(),
|
package/lib/types/type.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualDataSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoMovieParamsSchema, mulmoSpeechParamsSchema, textSlideParamsSchema, speechOptionsSchema, mulmoCanvasDimensionSchema, mulmoScriptTemplateSchema, text2ImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, multiLingualTextsSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema } from "./schema.js";
|
|
1
|
+
import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualDataSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoMovieParamsSchema, mulmoSpeechParamsSchema, textSlideParamsSchema, speechOptionsSchema, mulmoCanvasDimensionSchema, mulmoScriptTemplateSchema, mulmoScriptTemplateFileSchema, text2ImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, multiLingualTextsSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema, mulmoSessionStateSchema } from "./schema.js";
|
|
2
2
|
import { pdf_modes, pdf_sizes, storyToScriptGenerateMode } from "../utils/const.js";
|
|
3
3
|
import { LLM } from "../utils/utils.js";
|
|
4
4
|
import { z } from "zod";
|
|
@@ -22,6 +22,7 @@ export type MulmoStudioBeat = z.infer<typeof mulmoStudioBeatSchema>;
|
|
|
22
22
|
export type MulmoMediaSource = z.infer<typeof mediaSourceSchema>;
|
|
23
23
|
export type MulmoStudio = z.infer<typeof mulmoStudioSchema>;
|
|
24
24
|
export type MulmoScriptTemplate = z.infer<typeof mulmoScriptTemplateSchema>;
|
|
25
|
+
export type MulmoScriptTemplateFile = z.infer<typeof mulmoScriptTemplateFileSchema>;
|
|
25
26
|
export type MulmoStudioMultiLingual = z.infer<typeof mulmoStudioMultiLingualSchema>;
|
|
26
27
|
export type MulmoStudioMultiLingualData = z.infer<typeof mulmoStudioMultiLingualDataSchema>;
|
|
27
28
|
export type MultiLingualTexts = z.infer<typeof multiLingualTextsSchema>;
|
|
@@ -31,6 +32,7 @@ export type MulmoMarkdownMedia = z.infer<typeof mulmoMarkdownMediaSchema>;
|
|
|
31
32
|
export type MulmoImageMedia = z.infer<typeof mulmoImageMediaSchema>;
|
|
32
33
|
export type MulmoChartMedia = z.infer<typeof mulmoChartMediaSchema>;
|
|
33
34
|
export type MulmoMermaidMedia = z.infer<typeof mulmoMermaidMediaSchema>;
|
|
35
|
+
export type MulmoSessionState = z.infer<typeof mulmoSessionStateSchema>;
|
|
34
36
|
export type FileDirs = {
|
|
35
37
|
mulmoFilePath: string;
|
|
36
38
|
mulmoFileDirPath: string;
|
|
@@ -45,6 +47,7 @@ export type MulmoStudioContext = {
|
|
|
45
47
|
lang?: string;
|
|
46
48
|
force: boolean;
|
|
47
49
|
caption?: string;
|
|
50
|
+
sessionState: MulmoSessionState;
|
|
48
51
|
};
|
|
49
52
|
export type ScriptingParams = {
|
|
50
53
|
urls: string[];
|
package/lib/utils/file.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { MulmoScript,
|
|
1
|
+
import { MulmoScript, MulmoScriptTemplateFile } from "../types/index.js";
|
|
2
2
|
import { PDFMode } from "../types/index.js";
|
|
3
3
|
import { ZodSchema } from "zod";
|
|
4
|
+
export declare const updateNpmRoot: (_npmRoot: string) => void;
|
|
4
5
|
export declare function readMulmoScriptFile<T = MulmoScript>(path: string, errorMessage: string): {
|
|
5
6
|
mulmoData: T;
|
|
6
7
|
mulmoDataPath: string;
|
|
@@ -13,16 +14,8 @@ export declare function readMulmoScriptFile<T = MulmoScript>(path: string): {
|
|
|
13
14
|
} | null;
|
|
14
15
|
export declare const fetchMulmoScriptFile: (url: string) => Promise<{
|
|
15
16
|
result: boolean;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} | {
|
|
19
|
-
result: boolean;
|
|
20
|
-
script: any;
|
|
21
|
-
status?: undefined;
|
|
22
|
-
} | {
|
|
23
|
-
result: boolean;
|
|
24
|
-
status: string;
|
|
25
|
-
script?: undefined;
|
|
17
|
+
script?: MulmoScript;
|
|
18
|
+
status: string | number;
|
|
26
19
|
}>;
|
|
27
20
|
export declare const getOutputStudioFilePath: (outDirPath: string, fileName: string) => string;
|
|
28
21
|
export declare const resolveDirPath: (dirPath: string, studioFileName: string) => string;
|
|
@@ -43,9 +36,6 @@ export declare const getBaseDirPath: (basedir?: string) => string;
|
|
|
43
36
|
export declare const getFullPath: (baseDirPath: string | undefined, file: string) => string;
|
|
44
37
|
export declare const readScriptTemplateFile: (scriptName: string) => any;
|
|
45
38
|
export declare const readTemplatePrompt: (templateName: string) => string;
|
|
46
|
-
export declare const getAvailableTemplates: () =>
|
|
47
|
-
filename: string;
|
|
48
|
-
})[];
|
|
39
|
+
export declare const getAvailableTemplates: () => MulmoScriptTemplateFile[];
|
|
49
40
|
export declare const writingMessage: (filePath: string) => void;
|
|
50
|
-
export declare const resolveMediaSource: (source: MulmoMediaSource, context: MulmoStudioContext) => string | null;
|
|
51
41
|
export declare const readAndParseJson: <S extends ZodSchema<any>>(filePath: string, schema: S) => ReturnType<S["parse"]>;
|
package/lib/utils/file.js
CHANGED
|
@@ -4,16 +4,18 @@ import { parse as yamlParse } from "yaml";
|
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { GraphAILogger } from "graphai";
|
|
6
6
|
import { MulmoScriptTemplateMethods } from "../methods/mulmo_script_template.js";
|
|
7
|
-
import { MulmoStudioContextMethods } from "../methods/index.js";
|
|
8
7
|
import { mulmoScriptTemplateSchema } from "../types/schema.js";
|
|
9
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
9
|
const __dirname = path.dirname(__filename);
|
|
10
|
+
let npmRoot = path.resolve(__dirname, "../../");
|
|
11
|
+
export const updateNpmRoot = (_npmRoot) => {
|
|
12
|
+
npmRoot = _npmRoot;
|
|
13
|
+
};
|
|
11
14
|
export function readMulmoScriptFile(arg2, errorMessage) {
|
|
12
15
|
const scriptPath = path.resolve(arg2);
|
|
13
16
|
if (!fs.existsSync(scriptPath)) {
|
|
14
17
|
if (errorMessage) {
|
|
15
18
|
GraphAILogger.info(errorMessage);
|
|
16
|
-
process.exit(1);
|
|
17
19
|
}
|
|
18
20
|
return null;
|
|
19
21
|
}
|
|
@@ -30,7 +32,6 @@ export function readMulmoScriptFile(arg2, errorMessage) {
|
|
|
30
32
|
catch (__error) {
|
|
31
33
|
if (errorMessage) {
|
|
32
34
|
GraphAILogger.info("read file format is broken.");
|
|
33
|
-
process.exit(1);
|
|
34
35
|
}
|
|
35
36
|
return null;
|
|
36
37
|
}
|
|
@@ -41,10 +42,11 @@ export const fetchMulmoScriptFile = async (url) => {
|
|
|
41
42
|
if (!res.ok) {
|
|
42
43
|
return { result: false, status: res.status };
|
|
43
44
|
}
|
|
44
|
-
const script = await res.json();
|
|
45
|
+
const script = (await res.json());
|
|
45
46
|
return {
|
|
46
47
|
result: true,
|
|
47
48
|
script,
|
|
49
|
+
status: 200,
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
52
|
catch {
|
|
@@ -85,7 +87,7 @@ export const getOutputPdfFilePath = (outDirPath, fileName, pdfMode, lang) => {
|
|
|
85
87
|
return path.resolve(outDirPath, `${fileName}_${pdfMode}.pdf`);
|
|
86
88
|
};
|
|
87
89
|
export const getTemplateFilePath = (templateName) => {
|
|
88
|
-
return path.resolve(
|
|
90
|
+
return path.resolve(npmRoot, "./assets/templates/" + templateName + ".json");
|
|
89
91
|
};
|
|
90
92
|
export const mkdir = (dirPath) => {
|
|
91
93
|
if (!fs.existsSync(dirPath)) {
|
|
@@ -93,12 +95,12 @@ export const mkdir = (dirPath) => {
|
|
|
93
95
|
fs.mkdirSync(dirPath, { recursive: true });
|
|
94
96
|
}
|
|
95
97
|
};
|
|
96
|
-
export const silentPath = path.resolve(
|
|
97
|
-
export const silentLastPath = path.resolve(
|
|
98
|
-
export const silent60secPath = path.resolve(
|
|
99
|
-
export const defaultBGMPath = path.resolve(
|
|
98
|
+
export const silentPath = path.resolve(npmRoot, "./assets/audio/silent300.mp3");
|
|
99
|
+
export const silentLastPath = path.resolve(npmRoot, "./assets/audio/silent800.mp3");
|
|
100
|
+
export const silent60secPath = path.resolve(npmRoot, "./assets/audio/silent60sec.mp3");
|
|
101
|
+
export const defaultBGMPath = path.resolve(npmRoot, "./assets/music/StarsBeyondEx.mp3");
|
|
100
102
|
export const getHTMLFile = (filename) => {
|
|
101
|
-
const htmlPath = path.resolve(
|
|
103
|
+
const htmlPath = path.resolve(npmRoot, `./assets/html/${filename}.html`);
|
|
102
104
|
return fs.readFileSync(htmlPath, "utf-8");
|
|
103
105
|
};
|
|
104
106
|
// for cli
|
|
@@ -121,7 +123,7 @@ export const getFullPath = (baseDirPath, file) => {
|
|
|
121
123
|
return path.resolve(file);
|
|
122
124
|
};
|
|
123
125
|
export const readScriptTemplateFile = (scriptName) => {
|
|
124
|
-
const scriptPath = path.resolve(
|
|
126
|
+
const scriptPath = path.resolve(npmRoot, "./scripts/templates", scriptName);
|
|
125
127
|
const scriptData = fs.readFileSync(scriptPath, "utf-8");
|
|
126
128
|
// NOTE: We don't want to schema parse the script here to eliminate default values.
|
|
127
129
|
return JSON.parse(scriptData);
|
|
@@ -142,7 +144,7 @@ export const readTemplatePrompt = (templateName) => {
|
|
|
142
144
|
return prompt;
|
|
143
145
|
};
|
|
144
146
|
export const getAvailableTemplates = () => {
|
|
145
|
-
const templatesDir = path.resolve(
|
|
147
|
+
const templatesDir = path.resolve(npmRoot, "./assets/templates");
|
|
146
148
|
if (!fs.existsSync(templatesDir)) {
|
|
147
149
|
return [];
|
|
148
150
|
}
|
|
@@ -158,15 +160,6 @@ export const getAvailableTemplates = () => {
|
|
|
158
160
|
export const writingMessage = (filePath) => {
|
|
159
161
|
GraphAILogger.debug(`writing: ${filePath}`);
|
|
160
162
|
};
|
|
161
|
-
export const resolveMediaSource = (source, context) => {
|
|
162
|
-
if (source.kind === "path") {
|
|
163
|
-
return MulmoStudioContextMethods.resolveAssetPath(context, source.path);
|
|
164
|
-
}
|
|
165
|
-
if (source.kind === "url") {
|
|
166
|
-
return source.url;
|
|
167
|
-
}
|
|
168
|
-
return null;
|
|
169
|
-
};
|
|
170
163
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
171
164
|
export const readAndParseJson = (filePath, schema) => {
|
|
172
165
|
const fileContent = fs.readFileSync(filePath, "utf-8");
|
package/lib/utils/filters.js
CHANGED
|
@@ -5,10 +5,10 @@ import fsPromise from "fs/promises";
|
|
|
5
5
|
import { GraphAILogger } from "graphai";
|
|
6
6
|
import { writingMessage } from "./file.js";
|
|
7
7
|
import { text2hash } from "./utils.js";
|
|
8
|
-
import {
|
|
8
|
+
import { MulmoStudioContextMethods } from "../methods/mulmo_studio_context.js";
|
|
9
9
|
export const fileCacheAgentFilter = async (context, next) => {
|
|
10
10
|
const { namedInputs } = context;
|
|
11
|
-
const { file, force,
|
|
11
|
+
const { file, force, mulmoContext, index, sessionType } = namedInputs;
|
|
12
12
|
const shouldUseCache = async () => {
|
|
13
13
|
if (force) {
|
|
14
14
|
return false;
|
|
@@ -25,7 +25,7 @@ export const fileCacheAgentFilter = async (context, next) => {
|
|
|
25
25
|
return true;
|
|
26
26
|
}
|
|
27
27
|
try {
|
|
28
|
-
|
|
28
|
+
MulmoStudioContextMethods.setBeatSessionState(mulmoContext, sessionType, index, true);
|
|
29
29
|
const output = (await next(context));
|
|
30
30
|
const buffer = output ? output["buffer"] : undefined;
|
|
31
31
|
if (buffer) {
|
|
@@ -37,7 +37,7 @@ export const fileCacheAgentFilter = async (context, next) => {
|
|
|
37
37
|
return false;
|
|
38
38
|
}
|
|
39
39
|
finally {
|
|
40
|
-
|
|
40
|
+
MulmoStudioContextMethods.setBeatSessionState(mulmoContext, sessionType, index, false);
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
43
|
export const browserlessCacheGenerator = (cacheDir) => {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ImageProcessorParams } from "../../types/index.js";
|
|
2
|
+
export declare const imageType = "beat";
|
|
3
|
+
export declare const processBeatReference: (__: ImageProcessorParams) => Promise<undefined>;
|
|
4
|
+
export declare const process: (__: ImageProcessorParams) => Promise<undefined>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const imageType = "beat";
|
|
2
|
+
export const processBeatReference = async (__) => {
|
|
3
|
+
// For beat reference, return undefined to indicate no image should be generated
|
|
4
|
+
// The actual reference will be resolved in mergeResult
|
|
5
|
+
return undefined;
|
|
6
|
+
};
|
|
7
|
+
export const process = processBeatReference;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const imageType = "image";
|
|
2
|
-
export declare const process: (params: import("../../
|
|
2
|
+
export declare const process: (params: import("../../index.js").ImageProcessorParams) => string | undefined;
|
|
@@ -5,4 +5,5 @@ import * as pluginChart from "./chart.js";
|
|
|
5
5
|
import * as pluginMermaid from "./mermaid.js";
|
|
6
6
|
import * as pluginMovie from "./movie.js";
|
|
7
7
|
import * as pluginHtmlTailwind from "./html_tailwind.js";
|
|
8
|
-
|
|
8
|
+
import * as pluginBeat from "./beat.js";
|
|
9
|
+
export declare const imagePlugins: (typeof pluginTextSlide | typeof pluginMarkdown | typeof pluginImage | typeof pluginChart | typeof pluginMermaid | typeof pluginMovie | typeof pluginHtmlTailwind | typeof pluginBeat)[];
|
|
@@ -5,4 +5,5 @@ import * as pluginChart from "./chart.js";
|
|
|
5
5
|
import * as pluginMermaid from "./mermaid.js";
|
|
6
6
|
import * as pluginMovie from "./movie.js";
|
|
7
7
|
import * as pluginHtmlTailwind from "./html_tailwind.js";
|
|
8
|
-
|
|
8
|
+
import * as pluginBeat from "./beat.js";
|
|
9
|
+
export const imagePlugins = [pluginTextSlide, pluginMarkdown, pluginImage, pluginChart, pluginMermaid, pluginMovie, pluginHtmlTailwind, pluginBeat];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const imageType = "movie";
|
|
2
|
-
export declare const process: (params: import("../../
|
|
2
|
+
export declare const process: (params: import("../../index.js").ImageProcessorParams) => string | undefined;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { GraphAILogger } from "graphai";
|
|
2
|
-
import {
|
|
2
|
+
import { MulmoMediaSourceMethods } from "../../methods/mulmo_media_source.js";
|
|
3
3
|
export const processSource = (imageType) => {
|
|
4
4
|
return (params) => {
|
|
5
5
|
const { beat, context } = params;
|
|
6
6
|
if (!beat.image || beat.image.type !== imageType)
|
|
7
7
|
return;
|
|
8
|
-
const path =
|
|
8
|
+
const path = MulmoMediaSourceMethods.resolve(beat.image.source, context);
|
|
9
9
|
if (path) {
|
|
10
10
|
return path;
|
|
11
11
|
}
|
|
@@ -23,6 +23,19 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
23
23
|
introPadding: number;
|
|
24
24
|
closingPadding: number;
|
|
25
25
|
outroPadding: number;
|
|
26
|
+
bgm?: {
|
|
27
|
+
url: string;
|
|
28
|
+
kind: "url";
|
|
29
|
+
} | {
|
|
30
|
+
kind: "base64";
|
|
31
|
+
data: string;
|
|
32
|
+
} | {
|
|
33
|
+
text: string;
|
|
34
|
+
kind: "text";
|
|
35
|
+
} | {
|
|
36
|
+
path: string;
|
|
37
|
+
kind: "path";
|
|
38
|
+
} | undefined;
|
|
26
39
|
};
|
|
27
40
|
$mulmocast: {
|
|
28
41
|
version: "1.0";
|
|
@@ -33,7 +46,7 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
33
46
|
height: number;
|
|
34
47
|
};
|
|
35
48
|
speechParams: {
|
|
36
|
-
provider: "openai" | "nijivoice" | "google";
|
|
49
|
+
provider: "openai" | "nijivoice" | "google" | "elevenlabs";
|
|
37
50
|
speakers: Record<string, {
|
|
38
51
|
voiceId: string;
|
|
39
52
|
displayName?: Record<string, string> | undefined;
|
|
@@ -41,6 +54,7 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
41
54
|
speed?: number | undefined;
|
|
42
55
|
instruction?: string | undefined;
|
|
43
56
|
} | undefined;
|
|
57
|
+
provider?: "openai" | "nijivoice" | "google" | "elevenlabs" | undefined;
|
|
44
58
|
}>;
|
|
45
59
|
};
|
|
46
60
|
beats: {
|
|
@@ -133,6 +147,9 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
133
147
|
} | {
|
|
134
148
|
type: "html_tailwind";
|
|
135
149
|
html: string | string[];
|
|
150
|
+
} | {
|
|
151
|
+
type: "beat";
|
|
152
|
+
id?: string | undefined;
|
|
136
153
|
} | {
|
|
137
154
|
type: "movie";
|
|
138
155
|
source: {
|
|
@@ -150,6 +167,7 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
150
167
|
};
|
|
151
168
|
mixAudio: number;
|
|
152
169
|
} | undefined;
|
|
170
|
+
id?: string | undefined;
|
|
153
171
|
audio?: {
|
|
154
172
|
type: "audio";
|
|
155
173
|
source: {
|
|
@@ -169,9 +187,9 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
169
187
|
type: "midi";
|
|
170
188
|
source: string;
|
|
171
189
|
} | undefined;
|
|
190
|
+
description?: string | undefined;
|
|
172
191
|
imageParams?: {
|
|
173
192
|
model?: string | undefined;
|
|
174
|
-
size?: string | undefined;
|
|
175
193
|
style?: string | undefined;
|
|
176
194
|
moderation?: string | undefined;
|
|
177
195
|
images?: Record<string, {
|
|
@@ -203,10 +221,10 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
203
221
|
}[];
|
|
204
222
|
lang?: string | undefined;
|
|
205
223
|
title?: string | undefined;
|
|
224
|
+
description?: string | undefined;
|
|
206
225
|
imageParams?: {
|
|
207
226
|
provider: "openai" | "google";
|
|
208
227
|
model?: string | undefined;
|
|
209
|
-
size?: string | undefined;
|
|
210
228
|
style?: string | undefined;
|
|
211
229
|
moderation?: string | undefined;
|
|
212
230
|
images?: Record<string, {
|
|
@@ -230,11 +248,13 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
230
248
|
cssStyles: string | string[];
|
|
231
249
|
} | undefined;
|
|
232
250
|
movieParams?: {
|
|
233
|
-
model?: string | undefined;
|
|
234
251
|
provider?: "openai" | "google" | undefined;
|
|
252
|
+
model?: string | undefined;
|
|
253
|
+
transition?: {
|
|
254
|
+
type: "fade";
|
|
255
|
+
duration: number;
|
|
256
|
+
} | undefined;
|
|
235
257
|
} | undefined;
|
|
236
|
-
omitCaptions?: boolean | undefined;
|
|
237
|
-
description?: string | undefined;
|
|
238
258
|
references?: {
|
|
239
259
|
type: "image" | "audio" | "article" | "paper" | "video";
|
|
240
260
|
url: string;
|
|
@@ -245,21 +265,4 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
|
|
|
245
265
|
__test_invalid__?: boolean | undefined;
|
|
246
266
|
};
|
|
247
267
|
filename: string;
|
|
248
|
-
state: {
|
|
249
|
-
inSession: {
|
|
250
|
-
pdf: boolean;
|
|
251
|
-
image: boolean;
|
|
252
|
-
audio: boolean;
|
|
253
|
-
video: boolean;
|
|
254
|
-
multiLingual: boolean;
|
|
255
|
-
caption: boolean;
|
|
256
|
-
};
|
|
257
|
-
inBeatSession: {
|
|
258
|
-
image: Set<number>;
|
|
259
|
-
movie: Set<number>;
|
|
260
|
-
audio: Set<number>;
|
|
261
|
-
multiLingual: Set<number>;
|
|
262
|
-
caption: Set<number>;
|
|
263
|
-
};
|
|
264
|
-
};
|
|
265
268
|
};
|
package/lib/utils/preprocess.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { GraphAILogger } from "graphai";
|
|
1
2
|
import { mulmoScriptSchema, mulmoBeatSchema, mulmoStudioSchema } from "../types/index.js";
|
|
2
3
|
const rebuildStudio = (currentStudio, mulmoScript, fileName) => {
|
|
3
4
|
const parsed = mulmoStudioSchema.safeParse(currentStudio);
|
|
4
5
|
if (parsed.success) {
|
|
5
6
|
return parsed.data;
|
|
6
7
|
}
|
|
8
|
+
if (currentStudio) {
|
|
9
|
+
GraphAILogger.info("currentStudio is invalid", parsed.error);
|
|
10
|
+
}
|
|
7
11
|
// We need to parse it to fill default values
|
|
8
12
|
return mulmoStudioSchema.parse({
|
|
9
13
|
script: mulmoScript,
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mulmocast",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "lib/
|
|
6
|
+
"main": "lib/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"mulmo": "lib/cli/bin.js"
|
|
9
9
|
},
|
|
@@ -69,27 +69,27 @@
|
|
|
69
69
|
"google-auth-library": "^9.15.1",
|
|
70
70
|
"graphai": "^2.0.5",
|
|
71
71
|
"inquirer": "^12.6.1",
|
|
72
|
-
"marked": "^15.0.
|
|
72
|
+
"marked": "^15.0.12",
|
|
73
73
|
"ora": "^8.2.0",
|
|
74
74
|
"pdf-lib": "^1.17.1",
|
|
75
|
-
"puppeteer": "^24.
|
|
75
|
+
"puppeteer": "^24.10.0",
|
|
76
76
|
"yaml": "^2.8.0",
|
|
77
77
|
"yargs": "^17.7.2",
|
|
78
|
-
"zod": "^3.
|
|
78
|
+
"zod": "^3.25.51",
|
|
79
79
|
"zod-to-json-schema": "^3.24.5"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@receptron/test_utils": "^2.0.0",
|
|
83
83
|
"@types/fluent-ffmpeg": "^2.1.26",
|
|
84
84
|
"@types/yargs": "^17.0.33",
|
|
85
|
-
"eslint": "^9.
|
|
85
|
+
"eslint": "^9.28.0",
|
|
86
86
|
"eslint-config-prettier": "^10.1.5",
|
|
87
|
-
"eslint-plugin-prettier": "^5.4.
|
|
87
|
+
"eslint-plugin-prettier": "^5.4.1",
|
|
88
88
|
"prettier": "^3.3.3",
|
|
89
89
|
"ts-node": "^10.9.2",
|
|
90
90
|
"tsx": "^4.19.4",
|
|
91
91
|
"typescript": "^5.7.3",
|
|
92
|
-
"typescript-eslint": "^8.
|
|
92
|
+
"typescript-eslint": "^8.33.1"
|
|
93
93
|
},
|
|
94
94
|
"engines": {
|
|
95
95
|
"node": ">=16.0.0"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$mulmocast": {
|
|
3
|
+
"version": "1.0",
|
|
4
|
+
"credit": "closing"
|
|
5
|
+
},
|
|
6
|
+
"title": "[TITLE: Brief, engaging title for the topic]",
|
|
7
|
+
"lang": "en",
|
|
8
|
+
"references": [
|
|
9
|
+
{
|
|
10
|
+
"url": "[SOURCE_URL: URL of the source material]",
|
|
11
|
+
"title": "[SOURCE_TITLE: Title of the referenced article, or paper]",
|
|
12
|
+
"type": "[SOURCE_TYPE: article, paper]"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"movieParams": {
|
|
16
|
+
"provider": "google"
|
|
17
|
+
},
|
|
18
|
+
"beats": [
|
|
19
|
+
{
|
|
20
|
+
"duration": 5.0,
|
|
21
|
+
"imagePrompt": "[IMAGE_PROMPT: A prompt for the image to be generated for this beat.]",
|
|
22
|
+
"moviePrompt": "[MOVIE_PROMPT: A movie prompt for that image.]"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"duration": 5.0,
|
|
26
|
+
"imagePrompt": "[IMAGE_PROMPT: A prompt for the image to be generated for this beat.]",
|
|
27
|
+
"moviePrompt": "[MOVIE_PROMPT: A movie prompt for that image.]"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"duration": 5.0,
|
|
31
|
+
"imagePrompt": "[IMAGE_PROMPT: A prompt for the image to be generated for this beat.]",
|
|
32
|
+
"moviePrompt": "[MOVIE_PROMPT: A movie prompt for that image.]"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"duration": 5.0,
|
|
36
|
+
"imagePrompt": "[IMAGE_PROMPT: A prompt for the image to be generated for this beat.]",
|
|
37
|
+
"moviePrompt": "[MOVIE_PROMPT: A movie prompt for that image.]"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"duration": 5.0,
|
|
41
|
+
"imagePrompt": "[IMAGE_PROMPT: A prompt for the image to be generated for this beat.]",
|
|
42
|
+
"moviePrompt": "[MOVIE_PROMPT: A movie prompt for that image.]"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"duration": 5.0,
|
|
46
|
+
"imagePrompt": "[IMAGE_PROMPT: A prompt for the image to be generated for this beat.]",
|
|
47
|
+
"moviePrompt": "[MOVIE_PROMPT: A movie prompt for that image.]"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|