mulmocast 0.1.6 → 1.1.0
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/templates/akira_comic.json +1 -1
- package/assets/templates/ani.json +48 -0
- package/assets/templates/ani_ja.json +44 -0
- package/assets/templates/characters.json +1 -1
- package/assets/templates/children_book.json +1 -1
- package/assets/templates/comic_strips.json +1 -1
- package/assets/templates/drslump_comic.json +1 -1
- package/assets/templates/ghibli_comic.json +1 -1
- package/assets/templates/ghibli_image_only.json +1 -1
- package/assets/templates/ghibli_shorts.json +2 -3
- package/assets/templates/ghost_comic.json +1 -1
- package/assets/templates/onepiece_comic.json +1 -1
- package/assets/templates/portrait_movie.json +1 -1
- package/assets/templates/realistic_movie.json +1 -1
- package/assets/templates/sensei_and_taro.json +4 -5
- package/assets/templates/shorts.json +1 -1
- package/assets/templates/trailer.json +1 -1
- package/lib/actions/audio.js +8 -7
- package/lib/actions/image_agents.d.ts +53 -98
- package/lib/actions/image_agents.js +14 -6
- package/lib/actions/images.js +42 -13
- package/lib/actions/movie.js +1 -1
- package/lib/agents/index.d.ts +2 -1
- package/lib/agents/index.js +2 -1
- package/lib/agents/movie_replicate_agent.js +18 -5
- package/lib/agents/sound_effect_replicate_agent.d.ts +5 -0
- package/lib/agents/sound_effect_replicate_agent.js +59 -0
- 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/story_to_script/builder.js +1 -1
- package/lib/cli/commands/tool/story_to_script/handler.d.ts +1 -1
- package/lib/mcp/server.js +2 -2
- package/lib/methods/index.d.ts +1 -0
- package/lib/methods/index.js +1 -0
- package/lib/methods/mulmo_presentation_style.d.ts +25 -6
- package/lib/methods/mulmo_presentation_style.js +33 -30
- package/lib/methods/mulmo_script.d.ts +4 -0
- package/lib/methods/mulmo_script.js +31 -0
- package/lib/tools/story_to_script.d.ts +1 -1
- package/lib/types/agent.d.ts +9 -0
- package/lib/types/schema.d.ts +727 -554
- package/lib/types/schema.js +41 -24
- package/lib/types/type.d.ts +4 -4
- package/lib/utils/assets.d.ts +18 -0
- package/lib/utils/assets.js +101 -0
- package/lib/utils/context.d.ts +98 -84
- package/lib/utils/context.js +2 -1
- package/lib/utils/ffmpeg_utils.js +6 -0
- package/lib/utils/file.d.ts +4 -1
- package/lib/utils/file.js +3 -5
- package/lib/utils/preprocess.d.ts +57 -47
- package/lib/utils/preprocess.js +7 -5
- package/lib/utils/provider2agent.d.ts +27 -7
- package/lib/utils/provider2agent.js +85 -7
- package/lib/utils/utils.d.ts +1 -2
- package/lib/utils/utils.js +4 -2
- package/package.json +7 -7
- package/scripts/templates/presentation.json~ +0 -119
package/lib/types/schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { htmlLLMProvider, provider2TTSAgent, provider2ImageAgent, provider2MovieAgent, defaultProviders } from "../utils/provider2agent.js";
|
|
2
|
+
import { htmlLLMProvider, provider2TTSAgent, provider2ImageAgent, provider2MovieAgent, defaultProviders, provider2SoundEffectAgent, } from "../utils/provider2agent.js";
|
|
3
3
|
export const langSchema = z.string();
|
|
4
4
|
const URLStringSchema = z.string().url();
|
|
5
5
|
export const localizedTextSchema = z
|
|
@@ -26,6 +26,7 @@ export const speakerDataSchema = z
|
|
|
26
26
|
.object({
|
|
27
27
|
displayName: z.record(langSchema, z.string()).optional(),
|
|
28
28
|
voiceId: z.string(),
|
|
29
|
+
isDefault: z.boolean().optional(),
|
|
29
30
|
speechOptions: speechOptionsSchema.optional(),
|
|
30
31
|
provider: text2SpeechProviderSchema.optional(),
|
|
31
32
|
model: z.string().optional().describe("TTS model to use for this speaker"),
|
|
@@ -96,7 +97,7 @@ export const mulmoChartMediaSchema = z
|
|
|
96
97
|
.object({
|
|
97
98
|
type: z.literal("chart"),
|
|
98
99
|
title: z.string(),
|
|
99
|
-
chartData: z.record(z.any()),
|
|
100
|
+
chartData: z.record(z.string(), z.any()),
|
|
100
101
|
})
|
|
101
102
|
.strict();
|
|
102
103
|
export const mulmoMermaidMediaSchema = z
|
|
@@ -223,12 +224,18 @@ export const htmlPromptParamsSchema = z
|
|
|
223
224
|
systemPrompt: z.string().default("").optional(),
|
|
224
225
|
prompt: z.string().default(""),
|
|
225
226
|
data: z.any().optional(),
|
|
226
|
-
images: z.record(z.any()).optional(),
|
|
227
|
+
images: z.record(z.string(), z.any()).optional(),
|
|
227
228
|
})
|
|
228
229
|
.strict();
|
|
230
|
+
export const text2MovieProviderSchema = z.enum(Object.keys(provider2MovieAgent)).default(defaultProviders.text2movie);
|
|
231
|
+
export const text2SoundEffectProviderSchema = z.enum(Object.keys(provider2SoundEffectAgent)).default(defaultProviders.soundEffect);
|
|
232
|
+
export const mulmoSoundEffectParamsSchema = z.object({
|
|
233
|
+
provider: text2SoundEffectProviderSchema.optional(),
|
|
234
|
+
model: z.string().optional(), // default: provider specific
|
|
235
|
+
});
|
|
229
236
|
export const mulmoBeatSchema = z
|
|
230
237
|
.object({
|
|
231
|
-
speaker: speakerIdSchema.
|
|
238
|
+
speaker: speakerIdSchema.optional(),
|
|
232
239
|
text: z.string().default("").describe("Text to be spoken. If empty, the audio is not generated."),
|
|
233
240
|
id: z.string().optional().describe("Unique identifier for the beat."),
|
|
234
241
|
description: z.string().optional(),
|
|
@@ -239,11 +246,13 @@ export const mulmoBeatSchema = z
|
|
|
239
246
|
audioParams: beatAudioParamsSchema.optional(), // beat specific parameters
|
|
240
247
|
movieParams: z
|
|
241
248
|
.object({
|
|
249
|
+
provider: text2MovieProviderSchema.optional(),
|
|
242
250
|
model: z.string().optional(),
|
|
243
|
-
fillOption: mulmoFillOptionSchema.optional(),
|
|
244
|
-
speed: z.number().optional().describe("Speed of the video. 1.0 is normal speed. 0.5 is half speed. 2.0 is double speed."),
|
|
251
|
+
fillOption: mulmoFillOptionSchema.optional(), // for movie.ts
|
|
252
|
+
speed: z.number().optional().describe("Speed of the video. 1.0 is normal speed. 0.5 is half speed. 2.0 is double speed."), // for movie.ts
|
|
245
253
|
})
|
|
246
254
|
.optional(),
|
|
255
|
+
soundEffectParams: mulmoSoundEffectParamsSchema.optional(),
|
|
247
256
|
htmlImageParams: mulmoHtmlImageParamsSchema.optional(),
|
|
248
257
|
speechOptions: speechOptionsSchema.optional(),
|
|
249
258
|
textSlideParams: textSlideParamsSchema.optional(),
|
|
@@ -251,6 +260,7 @@ export const mulmoBeatSchema = z
|
|
|
251
260
|
imageNames: z.array(imageIdSchema).optional(), // list of image names to use for image generation. The default is all images in the imageParams.images.
|
|
252
261
|
imagePrompt: z.string().optional(),
|
|
253
262
|
moviePrompt: z.string().optional(),
|
|
263
|
+
soundEffectPrompt: z.string().optional(),
|
|
254
264
|
htmlPrompt: htmlPromptParamsSchema.optional(),
|
|
255
265
|
})
|
|
256
266
|
.strict();
|
|
@@ -263,19 +273,11 @@ export const mulmoCanvasDimensionSchema = z
|
|
|
263
273
|
// export const voiceMapSchema = z.record(speakerIdSchema, z.string())
|
|
264
274
|
export const mulmoCastCreditSchema = z
|
|
265
275
|
.object({
|
|
266
|
-
version: z.literal("1.
|
|
276
|
+
version: z.literal("1.1"),
|
|
267
277
|
credit: z.literal("closing").optional(),
|
|
268
278
|
})
|
|
269
279
|
.strict();
|
|
270
|
-
export const mulmoSpeechParamsSchema = z
|
|
271
|
-
.object({
|
|
272
|
-
provider: text2SpeechProviderSchema, // has default value
|
|
273
|
-
speakers: speakerDictionarySchema,
|
|
274
|
-
model: z.string().optional().describe("Default TTS model to use"),
|
|
275
|
-
})
|
|
276
|
-
.strict();
|
|
277
280
|
export const text2HtmlImageProviderSchema = z.enum(htmlLLMProvider).default(defaultProviders.text2Html);
|
|
278
|
-
export const text2MovieProviderSchema = z.enum(Object.keys(provider2MovieAgent)).default(defaultProviders.text2movie);
|
|
279
281
|
// NOTE: This is UI only. (until we figure out how to use it in mulmoMovieParamsSchema)
|
|
280
282
|
export const mulmoGoogleMovieModelSchema = z
|
|
281
283
|
.object({
|
|
@@ -296,27 +298,40 @@ export const mulmoTransitionSchema = z.object({
|
|
|
296
298
|
});
|
|
297
299
|
export const mulmoMovieParamsSchema = z
|
|
298
300
|
.object({
|
|
299
|
-
provider: text2MovieProviderSchema.optional(),
|
|
300
|
-
model: z.string().optional(), // default: provider specific
|
|
301
|
-
transition: mulmoTransitionSchema.optional(),
|
|
302
|
-
fillOption: mulmoFillOptionSchema.optional(),
|
|
301
|
+
provider: text2MovieProviderSchema.optional(), // for agent
|
|
302
|
+
model: z.string().optional(), // default: provider specific. for agent
|
|
303
|
+
transition: mulmoTransitionSchema.optional(), // for movie.ts
|
|
304
|
+
fillOption: mulmoFillOptionSchema.optional(), // for movie.ts
|
|
303
305
|
})
|
|
304
306
|
.strict();
|
|
307
|
+
const defaultSpeaker = "Presenter";
|
|
305
308
|
export const mulmoPresentationStyleSchema = z.object({
|
|
306
309
|
$mulmocast: mulmoCastCreditSchema,
|
|
307
310
|
canvasSize: mulmoCanvasDimensionSchema, // has default value
|
|
308
|
-
speechParams:
|
|
311
|
+
speechParams: z
|
|
312
|
+
.object({
|
|
313
|
+
speakers: speakerDictionarySchema,
|
|
314
|
+
})
|
|
315
|
+
.default({
|
|
309
316
|
speakers: {
|
|
310
|
-
|
|
317
|
+
[defaultSpeaker]: {
|
|
311
318
|
voiceId: "shimmer",
|
|
312
319
|
displayName: {
|
|
313
|
-
en:
|
|
320
|
+
en: defaultSpeaker,
|
|
314
321
|
},
|
|
315
322
|
},
|
|
316
323
|
},
|
|
317
324
|
}),
|
|
318
|
-
imageParams: mulmoImageParamsSchema.optional()
|
|
319
|
-
|
|
325
|
+
imageParams: mulmoImageParamsSchema.optional().default({
|
|
326
|
+
provider: defaultProviders.text2image,
|
|
327
|
+
images: {},
|
|
328
|
+
}),
|
|
329
|
+
movieParams: mulmoMovieParamsSchema.optional().default({
|
|
330
|
+
provider: defaultProviders.text2movie,
|
|
331
|
+
}),
|
|
332
|
+
soundEffectParams: mulmoSoundEffectParamsSchema.optional().default({
|
|
333
|
+
provider: defaultProviders.soundEffect,
|
|
334
|
+
}),
|
|
320
335
|
htmlImageParams: mulmoHtmlImageParamsSchema
|
|
321
336
|
.extend({
|
|
322
337
|
provider: text2HtmlImageProviderSchema,
|
|
@@ -365,6 +380,7 @@ export const mulmoStudioBeatSchema = z
|
|
|
365
380
|
audioFile: z.string().optional(),
|
|
366
381
|
imageFile: z.string().optional(), // path to the image
|
|
367
382
|
movieFile: z.string().optional(), // path to the movie file
|
|
383
|
+
soundEffectFile: z.string().optional(), // path to the sound effect file
|
|
368
384
|
captionFile: z.string().optional(), // path to the caption image
|
|
369
385
|
})
|
|
370
386
|
.strict();
|
|
@@ -389,6 +405,7 @@ export const mulmoSessionStateSchema = z.object({
|
|
|
389
405
|
caption: z.record(z.number().int(), z.boolean()),
|
|
390
406
|
html: z.record(z.number().int(), z.boolean()),
|
|
391
407
|
imageReference: z.record(z.number().int(), z.boolean()),
|
|
408
|
+
soundEffect: z.record(z.number().int(), z.boolean()),
|
|
392
409
|
}),
|
|
393
410
|
});
|
|
394
411
|
export const mulmoStudioSchema = z
|
package/lib/types/type.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualDataSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoImageParamsImagesSchema, mulmoFillOptionSchema, mulmoMovieParamsSchema,
|
|
1
|
+
import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualDataSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoImageParamsImagesSchema, mulmoFillOptionSchema, mulmoMovieParamsSchema, textSlideParamsSchema, speechOptionsSchema, speakerDataSchema, mulmoCanvasDimensionSchema, mulmoScriptTemplateSchema, mulmoScriptTemplateFileSchema, text2ImageProviderSchema, text2HtmlImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, multiLingualTextsSchema, mulmoImageAssetSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema, mulmoSessionStateSchema, mulmoOpenAIImageModelSchema, mulmoGoogleImageModelSchema, mulmoGoogleMovieModelSchema, mulmoReplicateMovieModelSchema, mulmoImagePromptMediaSchema } from "./schema.js";
|
|
2
2
|
import { pdf_modes, pdf_sizes, storyToScriptGenerateMode } from "../utils/const.js";
|
|
3
|
-
import { LLM } from "../utils/
|
|
3
|
+
import type { LLM } from "../utils/provider2agent.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
export type LANG = z.infer<typeof langSchema>;
|
|
6
6
|
export type MulmoBeat = z.infer<typeof mulmoBeatSchema>;
|
|
7
7
|
export type SpeakerDictonary = z.infer<typeof speakerDictionarySchema>;
|
|
8
|
-
export type MulmoSpeechParams = z.infer<typeof mulmoSpeechParamsSchema>;
|
|
9
8
|
export type SpeechOptions = z.infer<typeof speechOptionsSchema>;
|
|
10
9
|
export type SpeakerData = z.infer<typeof speakerDataSchema>;
|
|
11
10
|
export type MulmoImageParams = z.infer<typeof mulmoImageParamsSchema>;
|
|
@@ -36,6 +35,7 @@ export type MulmoGoogleImageModel = z.infer<typeof mulmoGoogleImageModelSchema>;
|
|
|
36
35
|
export type MulmoGoogleMovieModel = z.infer<typeof mulmoGoogleMovieModelSchema>;
|
|
37
36
|
export type MulmoReplicateMovieModel = z.infer<typeof mulmoReplicateMovieModelSchema>;
|
|
38
37
|
export type MulmoImagePromptMedia = z.infer<typeof mulmoImagePromptMediaSchema>;
|
|
38
|
+
export type MulmoImageAsset = z.infer<typeof mulmoImageAssetSchema>;
|
|
39
39
|
export type MulmoTextSlideMedia = z.infer<typeof mulmoTextSlideMediaSchema>;
|
|
40
40
|
export type MulmoMarkdownMedia = z.infer<typeof mulmoMarkdownMediaSchema>;
|
|
41
41
|
export type MulmoImageMedia = z.infer<typeof mulmoImageMediaSchema>;
|
|
@@ -91,7 +91,7 @@ export type Text2HtmlAgentInfo = {
|
|
|
91
91
|
export type BeatMediaType = "movie" | "image";
|
|
92
92
|
export type StoryToScriptGenerateMode = (typeof storyToScriptGenerateMode)[keyof typeof storyToScriptGenerateMode];
|
|
93
93
|
export type SessionType = "audio" | "image" | "video" | "multiLingual" | "caption" | "pdf";
|
|
94
|
-
export type BeatSessionType = "audio" | "image" | "multiLingual" | "caption" | "movie" | "html" | "imageReference";
|
|
94
|
+
export type BeatSessionType = "audio" | "image" | "multiLingual" | "caption" | "movie" | "html" | "imageReference" | "soundEffect";
|
|
95
95
|
export type SessionProgressEvent = {
|
|
96
96
|
kind: "session";
|
|
97
97
|
sessionType: SessionType;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type BgmAsset = {
|
|
2
|
+
name: string;
|
|
3
|
+
title: string;
|
|
4
|
+
url: string;
|
|
5
|
+
suno_url: string;
|
|
6
|
+
date: string;
|
|
7
|
+
duration: string;
|
|
8
|
+
account: string;
|
|
9
|
+
original_license: string;
|
|
10
|
+
prompt: string;
|
|
11
|
+
model: string;
|
|
12
|
+
};
|
|
13
|
+
export type BgmAssets = {
|
|
14
|
+
license: string;
|
|
15
|
+
bgms: BgmAsset[];
|
|
16
|
+
};
|
|
17
|
+
export declare const bgmAssets: BgmAssets;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export const bgmAssets = {
|
|
2
|
+
license: "Free to distribute as the BMG of media generated by MulmoCast, including commercial use.",
|
|
3
|
+
bgms: [
|
|
4
|
+
{
|
|
5
|
+
name: "story001.mp3",
|
|
6
|
+
title: "Whispered Melody",
|
|
7
|
+
url: "https://github.com/receptron/mulmocast-media/raw/refs/heads/main/bgms/story001.mp3",
|
|
8
|
+
suno_url: "https://suno.com/s/v6zer50aQJu8Y0qA",
|
|
9
|
+
date: "2025-06-17",
|
|
10
|
+
duration: "03:17",
|
|
11
|
+
account: "@snakajima",
|
|
12
|
+
original_license: "Generated by Suno with commercial use rights (PRO Plan)",
|
|
13
|
+
prompt: "instrumental, smooth, piano",
|
|
14
|
+
model: "v4.5 beta",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "story002.mp3",
|
|
18
|
+
title: "Rise and Shine",
|
|
19
|
+
url: "https://github.com/receptron/mulmocast-media/raw/refs/heads/main/bgms/story002.mp3",
|
|
20
|
+
suno_url: "https://suno.com/s/mJnvyu3UXnkdAPfQ",
|
|
21
|
+
date: "2025-06-17",
|
|
22
|
+
duration: "04:04",
|
|
23
|
+
account: "@snakajima",
|
|
24
|
+
original_license: "Generated by Suno with commercial use rights (PRO Plan)",
|
|
25
|
+
prompt: "techno, inspiring, piano",
|
|
26
|
+
model: "v4.5 beta",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "story003.mp3",
|
|
30
|
+
title: "Chasing the Sunset",
|
|
31
|
+
url: "https://github.com/receptron/mulmocast-media/raw/refs/heads/main/bgms/story003.mp3",
|
|
32
|
+
suno_url: "https://suno.com/s/2zGjMQ9vURJbaMZA",
|
|
33
|
+
date: "2025-06-17",
|
|
34
|
+
duration: "02:49",
|
|
35
|
+
account: "@snakajima",
|
|
36
|
+
original_license: "Generated by Suno with commercial use rights (PRO Plan)",
|
|
37
|
+
prompt: "piano, inspiring, sunset",
|
|
38
|
+
model: "v4.5 beta",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "story004.mp3",
|
|
42
|
+
title: "Whispering Keys",
|
|
43
|
+
url: "https://github.com/receptron/mulmocast-media/raw/refs/heads/main/bgms/story004.mp3",
|
|
44
|
+
suno_url: "https://suno.com/s/0SFoBRsBWsncw6tu",
|
|
45
|
+
date: "2025-06-17",
|
|
46
|
+
duration: "04:00",
|
|
47
|
+
account: "@snakajima",
|
|
48
|
+
original_license: "Generated by Suno with commercial use rights (PRO Plan)",
|
|
49
|
+
prompt: "Piano, classical, ambient",
|
|
50
|
+
model: "v4",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "story005.mp3",
|
|
54
|
+
title: "Whisper of Ivory",
|
|
55
|
+
url: "https://github.com/receptron/mulmocast-media/raw/refs/heads/main/bgms/story005.mp3",
|
|
56
|
+
suno_url: "https://suno.com/s/0SFoBRsBWsncw6tu",
|
|
57
|
+
date: "2025-06-17",
|
|
58
|
+
duration: "04:00",
|
|
59
|
+
account: "@snakajima",
|
|
60
|
+
original_license: "Generated by Suno with commercial use rights (PRO Plan)",
|
|
61
|
+
prompt: "Piano solo, classical, ambient",
|
|
62
|
+
model: "v4",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "theme001.mp3",
|
|
66
|
+
title: "Rise of the Flame",
|
|
67
|
+
url: "https://github.com/receptron/mulmocast-media/raw/refs/heads/main/bgms/theme001.mp3",
|
|
68
|
+
suno_url: "https://suno.com/s/WhYOf8oJYhBgSKET",
|
|
69
|
+
date: "2025-06-20",
|
|
70
|
+
duration: "03:23",
|
|
71
|
+
account: "@snakajima",
|
|
72
|
+
original_license: "Generated by Suno with commercial use rights (PRO Plan)",
|
|
73
|
+
prompt: "Olympic Theme, classical, emotional",
|
|
74
|
+
model: "v4",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "olympic001.mp3",
|
|
78
|
+
title: "Olympic-style Theme Music",
|
|
79
|
+
url: "https://github.com/receptron/mulmocast-media/raw/refs/heads/main/bgms/olympic001.mp3",
|
|
80
|
+
suno_url: "https://suno.com/s/32wpnmCrkFVvkTSQ",
|
|
81
|
+
date: "2025-07-17",
|
|
82
|
+
duration: "02:54",
|
|
83
|
+
account: "@snakajima",
|
|
84
|
+
original_license: "Generated by Suno with commercial use rights (PRO Plan)",
|
|
85
|
+
prompt: "Epic orchestral fanfare in the style of John Williams' Olympic Fanfare and Theme. Bright brass fanfare, soaring strings, powerful percussion, and heroic French horn melodies. Triumphant and majestic mood, suitable for an opening ceremony or national celebration. Emphasize dynamic builds, rich harmonies, and cinematic grandeur.",
|
|
86
|
+
model: "v4.5+",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "morning001.mp3",
|
|
90
|
+
title: "Morning Dance",
|
|
91
|
+
url: "https://github.com/receptron/mulmocast-media/raw/refs/heads/main/bgms/morning001.mp3",
|
|
92
|
+
suno_url: "https://suno.com/s/9MTkutZYqxeyBlwK",
|
|
93
|
+
date: "2025-07-17",
|
|
94
|
+
duration: "03:52",
|
|
95
|
+
account: "@snakajima",
|
|
96
|
+
original_license: "morning, piano solo, Japanese name, sexy",
|
|
97
|
+
prompt: "morning, piano solo, Japanese name, sexy",
|
|
98
|
+
model: "v4.5+",
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
package/lib/utils/context.d.ts
CHANGED
|
@@ -16,9 +16,35 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
16
16
|
audioFile?: string | undefined;
|
|
17
17
|
imageFile?: string | undefined;
|
|
18
18
|
movieFile?: string | undefined;
|
|
19
|
+
soundEffectFile?: string | undefined;
|
|
19
20
|
captionFile?: string | undefined;
|
|
20
21
|
}[];
|
|
21
22
|
script: {
|
|
23
|
+
imageParams: {
|
|
24
|
+
provider: string;
|
|
25
|
+
model?: string | undefined;
|
|
26
|
+
style?: string | undefined;
|
|
27
|
+
moderation?: string | undefined;
|
|
28
|
+
images?: Record<string, {
|
|
29
|
+
type: "image";
|
|
30
|
+
source: {
|
|
31
|
+
url: string;
|
|
32
|
+
kind: "url";
|
|
33
|
+
} | {
|
|
34
|
+
kind: "base64";
|
|
35
|
+
data: string;
|
|
36
|
+
} | {
|
|
37
|
+
text: string;
|
|
38
|
+
kind: "text";
|
|
39
|
+
} | {
|
|
40
|
+
path: string;
|
|
41
|
+
kind: "path";
|
|
42
|
+
};
|
|
43
|
+
} | {
|
|
44
|
+
type: "imagePrompt";
|
|
45
|
+
prompt: string;
|
|
46
|
+
}> | undefined;
|
|
47
|
+
};
|
|
22
48
|
audioParams: {
|
|
23
49
|
padding: number;
|
|
24
50
|
introPadding: number;
|
|
@@ -41,8 +67,23 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
41
67
|
kind: "path";
|
|
42
68
|
} | undefined;
|
|
43
69
|
};
|
|
70
|
+
movieParams: {
|
|
71
|
+
provider?: string | undefined;
|
|
72
|
+
model?: string | undefined;
|
|
73
|
+
fillOption?: {
|
|
74
|
+
style: "aspectFit" | "aspectFill";
|
|
75
|
+
} | undefined;
|
|
76
|
+
transition?: {
|
|
77
|
+
type: "fade" | "slideout_left";
|
|
78
|
+
duration: number;
|
|
79
|
+
} | undefined;
|
|
80
|
+
};
|
|
81
|
+
soundEffectParams: {
|
|
82
|
+
provider?: string | undefined;
|
|
83
|
+
model?: string | undefined;
|
|
84
|
+
};
|
|
44
85
|
$mulmocast: {
|
|
45
|
-
version: "1.
|
|
86
|
+
version: "1.1";
|
|
46
87
|
credit?: "closing" | undefined;
|
|
47
88
|
};
|
|
48
89
|
canvasSize: {
|
|
@@ -50,10 +91,10 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
50
91
|
height: number;
|
|
51
92
|
};
|
|
52
93
|
speechParams: {
|
|
53
|
-
provider: string;
|
|
54
94
|
speakers: Record<string, {
|
|
55
95
|
voiceId: string;
|
|
56
96
|
displayName?: Record<string, string> | undefined;
|
|
97
|
+
isDefault?: boolean | undefined;
|
|
57
98
|
speechOptions?: {
|
|
58
99
|
speed?: number | undefined;
|
|
59
100
|
instruction?: string | undefined;
|
|
@@ -61,16 +102,9 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
61
102
|
provider?: string | undefined;
|
|
62
103
|
model?: string | undefined;
|
|
63
104
|
}>;
|
|
64
|
-
model?: string | undefined;
|
|
65
105
|
};
|
|
66
106
|
beats: {
|
|
67
107
|
text: string;
|
|
68
|
-
speaker: string;
|
|
69
|
-
duration?: number | undefined;
|
|
70
|
-
speechOptions?: {
|
|
71
|
-
speed?: number | undefined;
|
|
72
|
-
instruction?: string | undefined;
|
|
73
|
-
} | undefined;
|
|
74
108
|
image?: {
|
|
75
109
|
type: "markdown";
|
|
76
110
|
markdown: string | string[];
|
|
@@ -175,6 +209,11 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
175
209
|
type: "voice_over";
|
|
176
210
|
startAt?: number | undefined;
|
|
177
211
|
} | undefined;
|
|
212
|
+
duration?: number | undefined;
|
|
213
|
+
speechOptions?: {
|
|
214
|
+
speed?: number | undefined;
|
|
215
|
+
instruction?: string | undefined;
|
|
216
|
+
} | undefined;
|
|
178
217
|
id?: string | undefined;
|
|
179
218
|
audio?: {
|
|
180
219
|
type: "audio";
|
|
@@ -196,6 +235,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
196
235
|
source: string;
|
|
197
236
|
} | undefined;
|
|
198
237
|
imagePrompt?: string | undefined;
|
|
238
|
+
speaker?: string | undefined;
|
|
199
239
|
description?: string | undefined;
|
|
200
240
|
imageParams?: {
|
|
201
241
|
provider: string;
|
|
@@ -228,11 +268,16 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
228
268
|
} | undefined;
|
|
229
269
|
movieParams?: {
|
|
230
270
|
speed?: number | undefined;
|
|
271
|
+
provider?: string | undefined;
|
|
231
272
|
model?: string | undefined;
|
|
232
273
|
fillOption?: {
|
|
233
274
|
style: "aspectFit" | "aspectFill";
|
|
234
275
|
} | undefined;
|
|
235
276
|
} | undefined;
|
|
277
|
+
soundEffectParams?: {
|
|
278
|
+
provider?: string | undefined;
|
|
279
|
+
model?: string | undefined;
|
|
280
|
+
} | undefined;
|
|
236
281
|
htmlImageParams?: {
|
|
237
282
|
model?: string | undefined;
|
|
238
283
|
} | undefined;
|
|
@@ -245,6 +290,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
245
290
|
} | undefined;
|
|
246
291
|
imageNames?: string[] | undefined;
|
|
247
292
|
moviePrompt?: string | undefined;
|
|
293
|
+
soundEffectPrompt?: string | undefined;
|
|
248
294
|
htmlPrompt?: {
|
|
249
295
|
prompt: string;
|
|
250
296
|
data?: any;
|
|
@@ -255,42 +301,6 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
255
301
|
lang?: string | undefined;
|
|
256
302
|
title?: string | undefined;
|
|
257
303
|
description?: string | undefined;
|
|
258
|
-
imageParams?: {
|
|
259
|
-
provider: string;
|
|
260
|
-
model?: string | undefined;
|
|
261
|
-
style?: string | undefined;
|
|
262
|
-
moderation?: string | undefined;
|
|
263
|
-
images?: Record<string, {
|
|
264
|
-
type: "image";
|
|
265
|
-
source: {
|
|
266
|
-
url: string;
|
|
267
|
-
kind: "url";
|
|
268
|
-
} | {
|
|
269
|
-
kind: "base64";
|
|
270
|
-
data: string;
|
|
271
|
-
} | {
|
|
272
|
-
text: string;
|
|
273
|
-
kind: "text";
|
|
274
|
-
} | {
|
|
275
|
-
path: string;
|
|
276
|
-
kind: "path";
|
|
277
|
-
};
|
|
278
|
-
} | {
|
|
279
|
-
type: "imagePrompt";
|
|
280
|
-
prompt: string;
|
|
281
|
-
}> | undefined;
|
|
282
|
-
} | undefined;
|
|
283
|
-
movieParams?: {
|
|
284
|
-
provider?: string | undefined;
|
|
285
|
-
model?: string | undefined;
|
|
286
|
-
fillOption?: {
|
|
287
|
-
style: "aspectFit" | "aspectFill";
|
|
288
|
-
} | undefined;
|
|
289
|
-
transition?: {
|
|
290
|
-
type: "fade" | "slideout_left";
|
|
291
|
-
duration: number;
|
|
292
|
-
} | undefined;
|
|
293
|
-
} | undefined;
|
|
294
304
|
htmlImageParams?: {
|
|
295
305
|
provider: string;
|
|
296
306
|
model?: string | undefined;
|
|
@@ -333,9 +343,35 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
333
343
|
caption: {};
|
|
334
344
|
html: {};
|
|
335
345
|
imageReference: {};
|
|
346
|
+
soundEffect: {};
|
|
336
347
|
};
|
|
337
348
|
};
|
|
338
349
|
presentationStyle: {
|
|
350
|
+
imageParams: {
|
|
351
|
+
provider: string;
|
|
352
|
+
model?: string | undefined;
|
|
353
|
+
style?: string | undefined;
|
|
354
|
+
moderation?: string | undefined;
|
|
355
|
+
images?: Record<string, {
|
|
356
|
+
type: "image";
|
|
357
|
+
source: {
|
|
358
|
+
url: string;
|
|
359
|
+
kind: "url";
|
|
360
|
+
} | {
|
|
361
|
+
kind: "base64";
|
|
362
|
+
data: string;
|
|
363
|
+
} | {
|
|
364
|
+
text: string;
|
|
365
|
+
kind: "text";
|
|
366
|
+
} | {
|
|
367
|
+
path: string;
|
|
368
|
+
kind: "path";
|
|
369
|
+
};
|
|
370
|
+
} | {
|
|
371
|
+
type: "imagePrompt";
|
|
372
|
+
prompt: string;
|
|
373
|
+
}> | undefined;
|
|
374
|
+
};
|
|
339
375
|
audioParams: {
|
|
340
376
|
padding: number;
|
|
341
377
|
introPadding: number;
|
|
@@ -358,8 +394,23 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
358
394
|
kind: "path";
|
|
359
395
|
} | undefined;
|
|
360
396
|
};
|
|
397
|
+
movieParams: {
|
|
398
|
+
provider?: string | undefined;
|
|
399
|
+
model?: string | undefined;
|
|
400
|
+
fillOption?: {
|
|
401
|
+
style: "aspectFit" | "aspectFill";
|
|
402
|
+
} | undefined;
|
|
403
|
+
transition?: {
|
|
404
|
+
type: "fade" | "slideout_left";
|
|
405
|
+
duration: number;
|
|
406
|
+
} | undefined;
|
|
407
|
+
};
|
|
408
|
+
soundEffectParams: {
|
|
409
|
+
provider?: string | undefined;
|
|
410
|
+
model?: string | undefined;
|
|
411
|
+
};
|
|
361
412
|
$mulmocast: {
|
|
362
|
-
version: "1.
|
|
413
|
+
version: "1.1";
|
|
363
414
|
credit?: "closing" | undefined;
|
|
364
415
|
};
|
|
365
416
|
canvasSize: {
|
|
@@ -367,10 +418,10 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
367
418
|
height: number;
|
|
368
419
|
};
|
|
369
420
|
speechParams: {
|
|
370
|
-
provider: string;
|
|
371
421
|
speakers: Record<string, {
|
|
372
422
|
voiceId: string;
|
|
373
423
|
displayName?: Record<string, string> | undefined;
|
|
424
|
+
isDefault?: boolean | undefined;
|
|
374
425
|
speechOptions?: {
|
|
375
426
|
speed?: number | undefined;
|
|
376
427
|
instruction?: string | undefined;
|
|
@@ -378,44 +429,7 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
378
429
|
provider?: string | undefined;
|
|
379
430
|
model?: string | undefined;
|
|
380
431
|
}>;
|
|
381
|
-
model?: string | undefined;
|
|
382
432
|
};
|
|
383
|
-
imageParams?: {
|
|
384
|
-
provider: string;
|
|
385
|
-
model?: string | undefined;
|
|
386
|
-
style?: string | undefined;
|
|
387
|
-
moderation?: string | undefined;
|
|
388
|
-
images?: Record<string, {
|
|
389
|
-
type: "image";
|
|
390
|
-
source: {
|
|
391
|
-
url: string;
|
|
392
|
-
kind: "url";
|
|
393
|
-
} | {
|
|
394
|
-
kind: "base64";
|
|
395
|
-
data: string;
|
|
396
|
-
} | {
|
|
397
|
-
text: string;
|
|
398
|
-
kind: "text";
|
|
399
|
-
} | {
|
|
400
|
-
path: string;
|
|
401
|
-
kind: "path";
|
|
402
|
-
};
|
|
403
|
-
} | {
|
|
404
|
-
type: "imagePrompt";
|
|
405
|
-
prompt: string;
|
|
406
|
-
}> | undefined;
|
|
407
|
-
} | undefined;
|
|
408
|
-
movieParams?: {
|
|
409
|
-
provider?: string | undefined;
|
|
410
|
-
model?: string | undefined;
|
|
411
|
-
fillOption?: {
|
|
412
|
-
style: "aspectFit" | "aspectFill";
|
|
413
|
-
} | undefined;
|
|
414
|
-
transition?: {
|
|
415
|
-
type: "fade" | "slideout_left";
|
|
416
|
-
duration: number;
|
|
417
|
-
} | undefined;
|
|
418
|
-
} | undefined;
|
|
419
433
|
htmlImageParams?: {
|
|
420
434
|
provider: string;
|
|
421
435
|
model?: string | undefined;
|
package/lib/utils/context.js
CHANGED
|
@@ -58,6 +58,7 @@ const initSessionState = () => {
|
|
|
58
58
|
caption: {},
|
|
59
59
|
html: {},
|
|
60
60
|
imageReference: {},
|
|
61
|
+
soundEffect: {},
|
|
61
62
|
},
|
|
62
63
|
};
|
|
63
64
|
};
|
|
@@ -84,7 +85,7 @@ export const initializeContextFromFiles = async (files, raiseError, force, capti
|
|
|
84
85
|
const currentStudio = readMulmoScriptFile(outputStudioFilePath);
|
|
85
86
|
try {
|
|
86
87
|
// validate mulmoStudioSchema. skip if __test_invalid__ is true
|
|
87
|
-
const studio = createOrUpdateStudioData(mulmoScript, currentStudio?.mulmoData, fileName, caption);
|
|
88
|
+
const studio = createOrUpdateStudioData(mulmoScript, currentStudio?.mulmoData, fileName, caption, presentationStyle);
|
|
88
89
|
const multiLingual = getMultiLingual(outputMultilingualFilePath, studio.beats.length);
|
|
89
90
|
return buildContext(studio, files, presentationStyle, multiLingual, force, lang);
|
|
90
91
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ffmpeg from "fluent-ffmpeg";
|
|
2
2
|
import { GraphAILogger } from "graphai";
|
|
3
|
+
import fs from "fs";
|
|
3
4
|
export const setFfmpegPath = (ffmpegPath) => {
|
|
4
5
|
ffmpeg.setFfmpegPath(ffmpegPath);
|
|
5
6
|
};
|
|
@@ -61,6 +62,11 @@ export const FfmpegContextGenerateOutput = (context, output, options = []) => {
|
|
|
61
62
|
};
|
|
62
63
|
export const ffmpegGetMediaDuration = (filePath) => {
|
|
63
64
|
return new Promise((resolve, reject) => {
|
|
65
|
+
// Only check file existence for local paths, not URLs
|
|
66
|
+
if (!filePath.startsWith("http://") && !filePath.startsWith("https://") && !fs.existsSync(filePath)) {
|
|
67
|
+
reject(new Error(`File not found: ${filePath}`));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
64
70
|
ffmpeg.ffprobe(filePath, (err, metadata) => {
|
|
65
71
|
if (err) {
|
|
66
72
|
GraphAILogger.info("Error while getting metadata:", err);
|
package/lib/utils/file.d.ts
CHANGED
|
@@ -25,7 +25,10 @@ export declare const getAudioArtifactFilePath: (outDirPath: string, fileName: st
|
|
|
25
25
|
export declare const getOutputVideoFilePath: (outDirPath: string, fileName: string, lang?: string, caption?: string) => string;
|
|
26
26
|
export declare const imageSuffix = "p";
|
|
27
27
|
export declare const getBeatPngImagePath: (context: MulmoStudioContext, index: number) => string;
|
|
28
|
-
export declare const
|
|
28
|
+
export declare const getBeatMoviePaths: (context: MulmoStudioContext, index: number) => {
|
|
29
|
+
movieFile: string;
|
|
30
|
+
soundEffectFile: string;
|
|
31
|
+
};
|
|
29
32
|
export declare const getReferenceImagePath: (context: MulmoStudioContext, key: string, extension: string) => string;
|
|
30
33
|
export declare const getCaptionImagePath: (context: MulmoStudioContext, index: number) => string;
|
|
31
34
|
export declare const getOutputPdfFilePath: (outDirPath: string, fileName: string, pdfMode: PDFMode, lang?: string) => string;
|
package/lib/utils/file.js
CHANGED
|
@@ -87,13 +87,11 @@ export const getBeatPngImagePath = (context, index) => {
|
|
|
87
87
|
}
|
|
88
88
|
return `${imageProjectDirPath}/${index}${imageSuffix}.png`;
|
|
89
89
|
};
|
|
90
|
-
export const
|
|
90
|
+
export const getBeatMoviePaths = (context, index) => {
|
|
91
91
|
const imageProjectDirPath = MulmoStudioContextMethods.getImageProjectDirPath(context);
|
|
92
92
|
const beat = context.studio.script.beats[index]; // beat could be undefined only in a test case.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
return `${imageProjectDirPath}/${index}.mov`;
|
|
93
|
+
const filename = beat?.id ? `${beat.id}` : `${index}`;
|
|
94
|
+
return { movieFile: `${imageProjectDirPath}/${filename}.mov`, soundEffectFile: `${imageProjectDirPath}/${filename}_sound.mov` };
|
|
97
95
|
};
|
|
98
96
|
export const getReferenceImagePath = (context, key, extension) => {
|
|
99
97
|
const imageProjectDirPath = MulmoStudioContextMethods.getImageProjectDirPath(context);
|