mulmocast 1.2.27 → 1.2.28

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.
@@ -0,0 +1,19 @@
1
+ {
2
+ "title": "Documentary",
3
+ "description": "Template for documentary, biography, and other long form content.",
4
+ "systemPrompt": "Generate 30 to 40 beats. Another AI will generate image for each beat based on the text description of that beat. Mention the reference in one of beats, if it exists. Use the JSON below as a template.",
5
+ "presentationStyle": {
6
+ "$mulmocast": {
7
+ "version": "1.1",
8
+ "credit": "closing"
9
+ },
10
+ "imageParams": {
11
+ "style": "<style>Photo realistic and cinematic. Let the art convey the story and emotions without text. Use the image for the aspect ratio</style>"
12
+ },
13
+ "canvasSize": {
14
+ "width": 1536,
15
+ "height": 1024
16
+ }
17
+ },
18
+ "scriptName": "text_only_template.json"
19
+ }
@@ -1,4 +1,4 @@
1
- import { MulmoStudioContext, MulmoBeat, MulmoCanvasDimension, MulmoImageParams } from "../types/index.js";
1
+ import { MulmoStudioContext, MulmoBeat, MulmoCanvasDimension, MulmoImageParams, MulmoMovieParams } from "../types/index.js";
2
2
  export declare const imagePreprocessAgent: (namedInputs: {
3
3
  context: MulmoStudioContext;
4
4
  beat: MulmoBeat;
@@ -31,6 +31,10 @@ export declare const imagePreprocessAgent: (namedInputs: {
31
31
  duration?: number;
32
32
  audioFile?: string;
33
33
  beatDuration?: number;
34
+ movieAgentInfo?: {
35
+ agent: string;
36
+ movieParams: MulmoMovieParams;
37
+ };
34
38
  htmlPrompt?: undefined;
35
39
  htmlImageFile?: undefined;
36
40
  htmlPath?: undefined;
@@ -38,21 +42,6 @@ export declare const imagePreprocessAgent: (namedInputs: {
38
42
  } | {
39
43
  imagePath: string;
40
44
  imageFromMovie: boolean;
41
- movieAgentInfo: {
42
- agent: string;
43
- movieParams: {
44
- speed?: number | undefined;
45
- provider?: string | undefined;
46
- model?: string | undefined;
47
- fillOption?: {
48
- style: "aspectFit" | "aspectFill";
49
- } | undefined;
50
- transition?: {
51
- type: "fade" | "slideout_left";
52
- duration: number;
53
- } | undefined;
54
- };
55
- };
56
45
  imageParams: MulmoImageParams;
57
46
  movieFile: string | undefined;
58
47
  soundEffectFile?: string;
@@ -71,6 +60,10 @@ export declare const imagePreprocessAgent: (namedInputs: {
71
60
  duration?: number;
72
61
  audioFile?: string;
73
62
  beatDuration?: number;
63
+ movieAgentInfo?: {
64
+ agent: string;
65
+ movieParams: MulmoMovieParams;
66
+ };
74
67
  htmlPrompt?: undefined;
75
68
  htmlImageFile?: undefined;
76
69
  htmlPath?: undefined;
@@ -81,21 +74,6 @@ export declare const imagePreprocessAgent: (namedInputs: {
81
74
  imageAgentInfo: import("../types/type.js").Text2ImageAgentInfo;
82
75
  prompt: string;
83
76
  referenceImages: string[];
84
- movieAgentInfo: {
85
- agent: string;
86
- movieParams: {
87
- speed?: number | undefined;
88
- provider?: string | undefined;
89
- model?: string | undefined;
90
- fillOption?: {
91
- style: "aspectFit" | "aspectFill";
92
- } | undefined;
93
- transition?: {
94
- type: "fade" | "slideout_left";
95
- duration: number;
96
- } | undefined;
97
- };
98
- };
99
77
  imageParams: MulmoImageParams;
100
78
  movieFile: string | undefined;
101
79
  soundEffectFile?: string;
@@ -114,6 +92,10 @@ export declare const imagePreprocessAgent: (namedInputs: {
114
92
  duration?: number;
115
93
  audioFile?: string;
116
94
  beatDuration?: number;
95
+ movieAgentInfo?: {
96
+ agent: string;
97
+ movieParams: MulmoMovieParams;
98
+ };
117
99
  htmlPrompt?: undefined;
118
100
  htmlImageFile?: undefined;
119
101
  htmlPath?: undefined;
@@ -2,7 +2,6 @@ import { MulmoPresentationStyleMethods, MulmoStudioContextMethods, MulmoBeatMeth
2
2
  import { getBeatPngImagePath, getBeatMoviePaths, getAudioFilePath } from "../utils/file.js";
3
3
  import { imagePrompt, htmlImageSystemPrompt } from "../utils/prompt.js";
4
4
  import { renderHTMLToImage } from "../utils/markdown.js";
5
- import { GraphAILogger } from "graphai";
6
5
  import { beatId } from "../utils/utils.js";
7
6
  const htmlStyle = (context, beat) => {
8
7
  return {
@@ -57,21 +56,20 @@ export const imagePreprocessAgent = async (namedInputs) => {
57
56
  returnValue.audioFile = studioBeat?.audioFile;
58
57
  }
59
58
  }
59
+ returnValue.movieAgentInfo = MulmoPresentationStyleMethods.getMovieAgentInfo(context.presentationStyle, beat);
60
60
  if (beat.image) {
61
61
  const plugin = MulmoBeatMethods.getPlugin(beat);
62
62
  const pluginPath = plugin.path({ beat, context, imagePath, ...htmlStyle(context, beat) });
63
63
  // undefined prompt indicates that image generation is not needed
64
64
  return { ...returnValue, imagePath: pluginPath, referenceImageForMovie: pluginPath };
65
65
  }
66
- const movieAgentInfo = MulmoPresentationStyleMethods.getMovieAgentInfo(context.presentationStyle, beat);
67
- GraphAILogger.log(`movieParams: ${index}`, movieAgentInfo.movieParams, returnValue.soundEffectAgentInfo, "\n", beat.moviePrompt, beat.soundEffectPrompt);
68
66
  if (beat.moviePrompt && !beat.imagePrompt) {
69
- return { ...returnValue, imagePath, imageFromMovie: true, movieAgentInfo }; // no image prompt, only movie prompt
67
+ return { ...returnValue, imagePath, imageFromMovie: true }; // no image prompt, only movie prompt
70
68
  }
71
69
  // referenceImages for "edit_image", openai agent.
72
70
  const referenceImages = MulmoBeatMethods.getImageReferenceForImageGenerator(beat, imageRefs);
73
71
  const prompt = imagePrompt(beat, imageAgentInfo.imageParams.style);
74
- return { ...returnValue, imagePath, referenceImageForMovie: imagePath, imageAgentInfo, prompt, referenceImages, movieAgentInfo };
72
+ return { ...returnValue, imagePath, referenceImageForMovie: imagePath, imageAgentInfo, prompt, referenceImages };
75
73
  };
76
74
  export const imagePluginAgent = async (namedInputs) => {
77
75
  const { context, beat, index } = namedInputs;
@@ -4,7 +4,7 @@ import { getReferenceImagePath, resolveAssetPath } from "../utils/file.js";
4
4
  import { getExtention } from "../utils/utils.js";
5
5
  import { graphOption } from "./images.js";
6
6
  import { MulmoPresentationStyleMethods } from "../methods/index.js";
7
- import { imageOpenaiAgent, mediaMockAgent, imageGenAIAgent } from "../agents/index.js";
7
+ import { imageOpenaiAgent, mediaMockAgent, imageGenAIAgent, imageReplicateAgent } from "../agents/index.js";
8
8
  // public api
9
9
  // Application may call this function directly to generate reference image.
10
10
  export const generateReferenceImage = async (inputs) => {
@@ -39,7 +39,7 @@ export const generateReferenceImage = async (inputs) => {
39
39
  },
40
40
  };
41
41
  const options = await graphOption(context);
42
- const graph = new GraphAI(image_graph_data, { imageGenAIAgent, imageOpenaiAgent, mediaMockAgent }, options);
42
+ const graph = new GraphAI(image_graph_data, { imageGenAIAgent, imageOpenaiAgent, mediaMockAgent, imageReplicateAgent }, options);
43
43
  await graph.run();
44
44
  return imagePath;
45
45
  };
@@ -54,6 +54,10 @@ export declare const beat_graph_data: {
54
54
  duration?: number;
55
55
  audioFile?: string;
56
56
  beatDuration?: number;
57
+ movieAgentInfo?: {
58
+ agent: string;
59
+ movieParams: import("../types/type.js").MulmoMovieParams;
60
+ };
57
61
  htmlPrompt?: undefined;
58
62
  htmlImageFile?: undefined;
59
63
  htmlPath?: undefined;
@@ -61,21 +65,6 @@ export declare const beat_graph_data: {
61
65
  } | {
62
66
  imagePath: string;
63
67
  imageFromMovie: boolean;
64
- movieAgentInfo: {
65
- agent: string;
66
- movieParams: {
67
- speed?: number | undefined;
68
- provider?: string | undefined;
69
- model?: string | undefined;
70
- fillOption?: {
71
- style: "aspectFit" | "aspectFill";
72
- } | undefined;
73
- transition?: {
74
- type: "fade" | "slideout_left";
75
- duration: number;
76
- } | undefined;
77
- };
78
- };
79
68
  imageParams: MulmoImageParams;
80
69
  movieFile: string | undefined;
81
70
  soundEffectFile?: string;
@@ -94,6 +83,10 @@ export declare const beat_graph_data: {
94
83
  duration?: number;
95
84
  audioFile?: string;
96
85
  beatDuration?: number;
86
+ movieAgentInfo?: {
87
+ agent: string;
88
+ movieParams: import("../types/type.js").MulmoMovieParams;
89
+ };
97
90
  htmlPrompt?: undefined;
98
91
  htmlImageFile?: undefined;
99
92
  htmlPath?: undefined;
@@ -104,21 +97,6 @@ export declare const beat_graph_data: {
104
97
  imageAgentInfo: import("../types/type.js").Text2ImageAgentInfo;
105
98
  prompt: string;
106
99
  referenceImages: string[];
107
- movieAgentInfo: {
108
- agent: string;
109
- movieParams: {
110
- speed?: number | undefined;
111
- provider?: string | undefined;
112
- model?: string | undefined;
113
- fillOption?: {
114
- style: "aspectFit" | "aspectFill";
115
- } | undefined;
116
- transition?: {
117
- type: "fade" | "slideout_left";
118
- duration: number;
119
- } | undefined;
120
- };
121
- };
122
100
  imageParams: MulmoImageParams;
123
101
  movieFile: string | undefined;
124
102
  soundEffectFile?: string;
@@ -137,6 +115,10 @@ export declare const beat_graph_data: {
137
115
  duration?: number;
138
116
  audioFile?: string;
139
117
  beatDuration?: number;
118
+ movieAgentInfo?: {
119
+ agent: string;
120
+ movieParams: import("../types/type.js").MulmoMovieParams;
121
+ };
140
122
  htmlPrompt?: undefined;
141
123
  htmlImageFile?: undefined;
142
124
  htmlPath?: undefined;
@@ -5,7 +5,7 @@ import * as vanilla from "@graphai/vanilla";
5
5
  import { openAIAgent } from "@graphai/openai_agent";
6
6
  import { anthropicAgent } from "@graphai/anthropic_agent";
7
7
  import { fileWriteAgent } from "@graphai/vanilla_node_agents";
8
- import { imageGenAIAgent, imageOpenaiAgent, movieGenAIAgent, movieReplicateAgent, mediaMockAgent, soundEffectReplicateAgent, lipSyncReplicateAgent, } from "../agents/index.js";
8
+ import { imageGenAIAgent, imageOpenaiAgent, imageReplicateAgent, movieGenAIAgent, movieReplicateAgent, mediaMockAgent, soundEffectReplicateAgent, lipSyncReplicateAgent, } from "../agents/index.js";
9
9
  import { MulmoPresentationStyleMethods, MulmoStudioContextMethods } from "../methods/index.js";
10
10
  import { getOutputStudioFilePath, mkdir } from "../utils/file.js";
11
11
  import { fileCacheAgentFilter } from "../utils/filters.js";
@@ -17,6 +17,7 @@ const vanillaAgents = vanilla.default ?? vanilla;
17
17
  const imageAgents = {
18
18
  imageGenAIAgent,
19
19
  imageOpenaiAgent,
20
+ imageReplicateAgent,
20
21
  };
21
22
  const movieAgents = {
22
23
  movieGenAIAgent,
@@ -0,0 +1,7 @@
1
+ import { AgentFunction, AgentFunctionInfo } from "graphai";
2
+ import type { ReplicateImageAgentParams } from "../types/agent.js";
3
+ import type { AgentBufferResult, ImageAgentInputs, AgentConfig } from "../types/agent.js";
4
+ export type ReplicateImageAgentConfig = AgentConfig;
5
+ export declare const imageReplicateAgent: AgentFunction<ReplicateImageAgentParams, AgentBufferResult, ImageAgentInputs, ReplicateImageAgentConfig>;
6
+ declare const imageReplicateAgentInfo: AgentFunctionInfo;
7
+ export default imageReplicateAgentInfo;
@@ -0,0 +1,84 @@
1
+ import { GraphAILogger } from "graphai";
2
+ import Replicate from "replicate";
3
+ import { getAspectRatio } from "./movie_replicate_agent.js";
4
+ import { provider2ImageAgent } from "../utils/provider2agent.js";
5
+ export const imageReplicateAgent = async ({ namedInputs, params, config, }) => {
6
+ const { prompt } = namedInputs;
7
+ const { canvasSize } = params;
8
+ const model = params.model ?? provider2ImageAgent.replicate.defaultModel;
9
+ const apiKey = config?.apiKey;
10
+ if (!apiKey) {
11
+ throw new Error("Replicate API key is required (REPLICATE_API_TOKEN)");
12
+ }
13
+ const replicate = new Replicate({
14
+ auth: apiKey,
15
+ });
16
+ const input = {
17
+ prompt,
18
+ width: canvasSize.width,
19
+ height: canvasSize.height,
20
+ };
21
+ if (model === "bytedance/seedream-4") {
22
+ input.size = "custom";
23
+ if (input.width < 1024) {
24
+ const ratio = 1024 / input.width;
25
+ input.width = 1024;
26
+ input.height = Math.round(input.height * ratio);
27
+ }
28
+ if (input.height < 1024) {
29
+ const ratio = 1024 / input.height;
30
+ input.width = Math.round(input.width * ratio);
31
+ input.height = 1024;
32
+ }
33
+ }
34
+ else if (model === "qwen/qwen-image") {
35
+ input.aspect_ratio = getAspectRatio(canvasSize);
36
+ }
37
+ // Add image if provided (for image-to-image generation)
38
+ /*
39
+ if (imagePath) {
40
+ const buffer = readFileSync(imagePath);
41
+ const base64Image = `data:image/png;base64,${buffer.toString("base64")}`;
42
+ const start_image = provider2MovieAgent.replicate.modelParams[model]?.start_image;
43
+ if (start_image === "first_frame_image" || start_image === "image" || start_image === "start_image") {
44
+ input[start_image] = base64Image;
45
+ } else if (start_image === undefined) {
46
+ throw new Error(`Model ${model} does not support image-to-video generation`);
47
+ } else {
48
+ input.image = base64Image;
49
+ }
50
+ }
51
+ */
52
+ try {
53
+ const output = await replicate.run(model, { input });
54
+ // Download the generated video
55
+ if (output && Array.isArray(output) && output.length > 0 && typeof output[0] === "object" && "url" in output[0]) {
56
+ const imageUrl = output[0].url();
57
+ const imageResponse = await fetch(imageUrl);
58
+ if (!imageResponse.ok) {
59
+ throw new Error(`Error downloading video: ${imageResponse.status} - ${imageResponse.statusText}`);
60
+ }
61
+ const arrayBuffer = await imageResponse.arrayBuffer();
62
+ const buffer = Buffer.from(arrayBuffer);
63
+ return { buffer };
64
+ }
65
+ throw new Error("ERROR: generateImage returned undefined");
66
+ }
67
+ catch (error) {
68
+ GraphAILogger.info("Replicate generation error:", error);
69
+ throw error;
70
+ }
71
+ };
72
+ const imageReplicateAgentInfo = {
73
+ name: "imageReplicateAgent",
74
+ agent: imageReplicateAgent,
75
+ mock: imageReplicateAgent,
76
+ samples: [],
77
+ description: "Replicate Image agent using FLUX and other models",
78
+ category: ["image"],
79
+ author: "Receptron Team",
80
+ repository: "https://github.com/receptron/mulmocast-cli/",
81
+ license: "MIT",
82
+ environmentVariables: ["REPLICATE_API_TOKEN"],
83
+ };
84
+ export default imageReplicateAgentInfo;
@@ -2,6 +2,7 @@ import addBGMAgent from "./add_bgm_agent.js";
2
2
  import combineAudioFilesAgent from "./combine_audio_files_agent.js";
3
3
  import imageGenAIAgent from "./image_genai_agent.js";
4
4
  import imageOpenaiAgent from "./image_openai_agent.js";
5
+ import imageReplicateAgent from "./image_replicate_agent.js";
5
6
  import tavilySearchAgent from "./tavily_agent.js";
6
7
  import movieGenAIAgent from "./movie_genai_agent.js";
7
8
  import movieReplicateAgent from "./movie_replicate_agent.js";
@@ -18,4 +19,4 @@ import { browserlessAgent } from "@graphai/browserless_agent";
18
19
  import { textInputAgent } from "@graphai/input_agents";
19
20
  import { openAIAgent } from "@graphai/openai_agent";
20
21
  import { fileWriteAgent } from "@graphai/vanilla_node_agents";
21
- export { openAIAgent, fileWriteAgent, browserlessAgent, textInputAgent, addBGMAgent, combineAudioFilesAgent, imageGenAIAgent, imageOpenaiAgent, tavilySearchAgent, movieGenAIAgent, movieReplicateAgent, mediaMockAgent, ttsElevenlabsAgent, ttsNijivoiceAgent, ttsOpenaiAgent, ttsGoogleAgent, validateSchemaAgent, soundEffectReplicateAgent, lipSyncReplicateAgent, puppeteerCrawlerAgent, };
22
+ export { openAIAgent, fileWriteAgent, browserlessAgent, textInputAgent, addBGMAgent, combineAudioFilesAgent, imageGenAIAgent, imageOpenaiAgent, imageReplicateAgent, tavilySearchAgent, movieGenAIAgent, movieReplicateAgent, mediaMockAgent, ttsElevenlabsAgent, ttsNijivoiceAgent, ttsOpenaiAgent, ttsGoogleAgent, validateSchemaAgent, soundEffectReplicateAgent, lipSyncReplicateAgent, puppeteerCrawlerAgent, };
@@ -2,6 +2,7 @@ import addBGMAgent from "./add_bgm_agent.js";
2
2
  import combineAudioFilesAgent from "./combine_audio_files_agent.js";
3
3
  import imageGenAIAgent from "./image_genai_agent.js";
4
4
  import imageOpenaiAgent from "./image_openai_agent.js";
5
+ import imageReplicateAgent from "./image_replicate_agent.js";
5
6
  import tavilySearchAgent from "./tavily_agent.js";
6
7
  import movieGenAIAgent from "./movie_genai_agent.js";
7
8
  import movieReplicateAgent from "./movie_replicate_agent.js";
@@ -19,4 +20,4 @@ import { textInputAgent } from "@graphai/input_agents";
19
20
  import { openAIAgent } from "@graphai/openai_agent";
20
21
  // import * as vanilla from "@graphai/vanilla";
21
22
  import { fileWriteAgent } from "@graphai/vanilla_node_agents";
22
- export { openAIAgent, fileWriteAgent, browserlessAgent, textInputAgent, addBGMAgent, combineAudioFilesAgent, imageGenAIAgent, imageOpenaiAgent, tavilySearchAgent, movieGenAIAgent, movieReplicateAgent, mediaMockAgent, ttsElevenlabsAgent, ttsNijivoiceAgent, ttsOpenaiAgent, ttsGoogleAgent, validateSchemaAgent, soundEffectReplicateAgent, lipSyncReplicateAgent, puppeteerCrawlerAgent, };
23
+ export { openAIAgent, fileWriteAgent, browserlessAgent, textInputAgent, addBGMAgent, combineAudioFilesAgent, imageGenAIAgent, imageOpenaiAgent, imageReplicateAgent, tavilySearchAgent, movieGenAIAgent, movieReplicateAgent, mediaMockAgent, ttsElevenlabsAgent, ttsNijivoiceAgent, ttsOpenaiAgent, ttsGoogleAgent, validateSchemaAgent, soundEffectReplicateAgent, lipSyncReplicateAgent, puppeteerCrawlerAgent, };
@@ -1,13 +1,4 @@
1
1
  import { AgentFunction, AgentFunctionInfo } from "graphai";
2
- type Article = {
3
- url: string;
4
- title: string | null;
5
- byline: string | null;
6
- excerpt: string | null;
7
- length: number | null;
8
- textContent: string | null;
9
- };
10
- export declare const fetchArticle: (url: string) => Promise<Article>;
11
2
  export declare const puppeteerCrawlerAgent: AgentFunction;
12
3
  declare const puppeteerCrawlerAgentInfo: AgentFunctionInfo;
13
4
  export default puppeteerCrawlerAgentInfo;
@@ -17,7 +17,7 @@ const waitStable = async (page, ms = 1200, step = 200) => {
17
17
  await new Promise((r) => setTimeout(r, step));
18
18
  }
19
19
  };
20
- export const fetchArticle = async (url) => {
20
+ const fetchArticle = async (url) => {
21
21
  const browser = await puppeteer.launch({
22
22
  headless: true,
23
23
  args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"],
@@ -256,6 +256,48 @@ export const promptTemplates = [
256
256
  systemPrompt: "Another AI will generate comic strips for each beat based on the text description of that beat. Mention the reference in one of beats, if it exists. Use the JSON below as a template.",
257
257
  title: "American Comic Strips",
258
258
  },
259
+ {
260
+ description: "Template for documentary, biography, and other long form content.",
261
+ filename: "documentary",
262
+ presentationStyle: {
263
+ $mulmocast: {
264
+ credit: "closing",
265
+ version: "1.1",
266
+ },
267
+ audioParams: {
268
+ audioVolume: 1,
269
+ bgmVolume: 0.2,
270
+ closingPadding: 0.8,
271
+ introPadding: 1,
272
+ outroPadding: 1,
273
+ padding: 0.3,
274
+ suppressSpeech: false,
275
+ },
276
+ canvasSize: {
277
+ height: 1024,
278
+ width: 1536,
279
+ },
280
+ imageParams: {
281
+ style: "<style>Photo realistic and cinematic. Let the art convey the story and emotions without text. Use the image for the aspect ratio</style>",
282
+ },
283
+ soundEffectParams: {
284
+ provider: "replicate",
285
+ },
286
+ speechParams: {
287
+ speakers: {
288
+ Presenter: {
289
+ displayName: {
290
+ en: "Presenter",
291
+ },
292
+ voiceId: "shimmer",
293
+ },
294
+ },
295
+ },
296
+ },
297
+ scriptName: "text_only_template.json",
298
+ systemPrompt: "Generate 30 to 40 beats. Another AI will generate image for each beat based on the text description of that beat. Mention the reference in one of beats, if it exists. Use the JSON below as a template.",
299
+ title: "Documentary",
300
+ },
259
301
  {
260
302
  description: "Template for Dr. Slump style comic presentation.",
261
303
  filename: "drslump_comic",