mulmocast 0.0.22 → 0.0.24

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.
Files changed (43) hide show
  1. package/README.md +5 -0
  2. package/assets/html/caption.html +2 -0
  3. package/lib/actions/audio.d.ts +2 -2
  4. package/lib/actions/audio.js +8 -7
  5. package/lib/actions/captions.js +7 -5
  6. package/lib/actions/images.d.ts +9 -5
  7. package/lib/actions/images.js +73 -36
  8. package/lib/actions/movie.d.ts +2 -2
  9. package/lib/actions/movie.js +24 -9
  10. package/lib/agents/combine_audio_files_agent.js +9 -5
  11. package/lib/agents/image_openai_agent.d.ts +2 -0
  12. package/lib/agents/image_openai_agent.js +3 -2
  13. package/lib/agents/index.d.ts +2 -1
  14. package/lib/agents/index.js +2 -1
  15. package/lib/agents/movie_replicate_agent.d.ts +23 -0
  16. package/lib/agents/movie_replicate_agent.js +93 -0
  17. package/lib/agents/tts_elevenlabs_agent.js +2 -2
  18. package/lib/agents/tts_nijivoice_agent.js +3 -2
  19. package/lib/agents/tts_openai_agent.js +3 -2
  20. package/lib/cli/commands/tool/scripting/builder.d.ts +3 -1
  21. package/lib/cli/commands/tool/scripting/builder.js +5 -0
  22. package/lib/cli/commands/tool/scripting/handler.d.ts +1 -0
  23. package/lib/cli/commands/tool/scripting/handler.js +13 -4
  24. package/lib/cli/commands/tool/story_to_script/builder.d.ts +1 -1
  25. package/lib/cli/helpers.js +8 -3
  26. package/lib/methods/mulmo_presentation_style.d.ts +2 -1
  27. package/lib/methods/mulmo_presentation_style.js +21 -2
  28. package/lib/methods/mulmo_studio_context.js +1 -1
  29. package/lib/tools/create_mulmo_script_from_url.d.ts +1 -0
  30. package/lib/tools/create_mulmo_script_from_url.js +129 -43
  31. package/lib/types/schema.d.ts +793 -163
  32. package/lib/types/schema.js +32 -1
  33. package/lib/types/type.d.ts +9 -2
  34. package/lib/utils/ffmpeg_utils.d.ts +1 -1
  35. package/lib/utils/ffmpeg_utils.js +2 -2
  36. package/lib/utils/preprocess.d.ts +29 -6
  37. package/lib/utils/prompt.d.ts +2 -1
  38. package/lib/utils/prompt.js +10 -0
  39. package/lib/utils/utils.d.ts +3 -0
  40. package/lib/utils/utils.js +47 -0
  41. package/package.json +3 -2
  42. package/scripts/templates/presentation.json +123 -0
  43. package/scripts/templates/presentation.json~ +119 -0
@@ -84,6 +84,12 @@ export const mulmoTextSlideMediaSchema = z
84
84
  }),
85
85
  })
86
86
  .strict();
87
+ export const mulmoCaptionParamsSchema = z
88
+ .object({
89
+ lang: langSchema.optional(),
90
+ styles: z.array(z.string()).default([]), // css styles
91
+ })
92
+ .strict();
87
93
  export const mulmoChartMediaSchema = z
88
94
  .object({
89
95
  type: z.literal("chart"),
@@ -141,6 +147,11 @@ const mulmoMidiMediaSchema = z
141
147
  export const mulmoAudioAssetSchema = z.union([mulmoAudioMediaSchema, mulmoMidiMediaSchema]);
142
148
  const imageIdSchema = z.string();
143
149
  export const mulmoImageParamsImagesSchema = z.record(imageIdSchema, mulmoImageMediaSchema);
150
+ export const mulmoFillOptionSchema = z
151
+ .object({
152
+ style: z.enum(["aspectFit", "aspectFill"]).default("aspectFit"),
153
+ })
154
+ .describe("How to handle aspect ratio differences between image and canvas");
144
155
  export const mulmoImageParamsSchema = z
145
156
  .object({
146
157
  model: z.string().optional(), // default: provider specific
@@ -159,6 +170,11 @@ export const beatAudioParamsSchema = z
159
170
  padding: z.number().optional().describe("Padding between beats"), // seconds
160
171
  })
161
172
  .strict();
173
+ export const mulmoHtmlImageParamsSchema = z
174
+ .object({
175
+ model: z.string().optional(), // default: provider specific
176
+ })
177
+ .strict();
162
178
  // Note: we can't extend beatAudioParamsSchema because it has padding as optional
163
179
  export const audioParamsSchema = z
164
180
  .object({
@@ -190,8 +206,15 @@ export const mulmoBeatSchema = z
190
206
  duration: z.number().optional().describe("Duration of the beat. Used only when the text is empty"),
191
207
  imageParams: mulmoImageParamsSchema.optional(), // beat specific parameters
192
208
  audioParams: beatAudioParamsSchema.optional(), // beat specific parameters
209
+ movieParams: z
210
+ .object({
211
+ fillOption: mulmoFillOptionSchema,
212
+ })
213
+ .optional(),
214
+ htmlImageParams: mulmoHtmlImageParamsSchema.optional(),
193
215
  speechOptions: speechOptionsSchema.optional(),
194
216
  textSlideParams: textSlideParamsSchema.optional(),
217
+ captionParams: mulmoCaptionParamsSchema.optional(),
195
218
  imageNames: z.array(imageIdSchema).optional(), // list of image names to use for image generation. The default is all images in the imageParams.images.
196
219
  imagePrompt: z.string().optional(),
197
220
  moviePrompt: z.string().optional(),
@@ -218,7 +241,8 @@ export const mulmoSpeechParamsSchema = z
218
241
  })
219
242
  .strict();
220
243
  export const text2ImageProviderSchema = z.union([z.literal("openai"), z.literal("google")]).default("openai");
221
- export const text2MovieProviderSchema = z.union([z.literal("openai"), z.literal("google")]).default("google");
244
+ export const text2HtmlImageProviderSchema = z.union([z.literal("openai"), z.literal("anthropic")]).default("openai");
245
+ export const text2MovieProviderSchema = z.union([z.literal("openai"), z.literal("google"), z.literal("replicate")]).default("google");
222
246
  export const mulmoTransitionSchema = z.object({
223
247
  type: z.enum(["fade", "slideout_left"]),
224
248
  duration: z.number().min(0).max(2).default(0.3), // transition duration in seconds
@@ -228,6 +252,7 @@ export const mulmoMovieParamsSchema = z
228
252
  provider: text2MovieProviderSchema.optional(),
229
253
  model: z.string().optional(), // default: provider specific
230
254
  transition: mulmoTransitionSchema.optional(),
255
+ fillOption: mulmoFillOptionSchema.optional(),
231
256
  })
232
257
  .strict();
233
258
  export const mulmoPresentationStyleSchema = z.object({
@@ -249,8 +274,14 @@ export const mulmoPresentationStyleSchema = z.object({
249
274
  })
250
275
  .optional(),
251
276
  movieParams: mulmoMovieParamsSchema.optional(),
277
+ htmlImageParams: mulmoHtmlImageParamsSchema
278
+ .extend({
279
+ provider: text2HtmlImageProviderSchema,
280
+ })
281
+ .optional(),
252
282
  // for textSlides
253
283
  textSlideParams: textSlideParamsSchema.optional(),
284
+ captionParams: mulmoCaptionParamsSchema.optional(),
254
285
  audioParams: audioParamsSchema.default({
255
286
  introPadding: 1.0,
256
287
  padding: 0.3,
@@ -1,4 +1,4 @@
1
- import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualDataSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoImageParamsImagesSchema, mulmoMovieParamsSchema, mulmoSpeechParamsSchema, textSlideParamsSchema, speechOptionsSchema, speakerDataSchema, mulmoCanvasDimensionSchema, mulmoScriptTemplateSchema, mulmoScriptTemplateFileSchema, text2ImageProviderSchema, text2MovieProviderSchema, text2SpeechProviderSchema, mulmoPresentationStyleSchema, multiLingualTextsSchema, mulmoMermaidMediaSchema, mulmoTextSlideMediaSchema, mulmoMarkdownMediaSchema, mulmoImageMediaSchema, mulmoChartMediaSchema, mediaSourceSchema, mulmoSessionStateSchema } from "./schema.js";
1
+ import { langSchema, localizedTextSchema, mulmoBeatSchema, mulmoScriptSchema, mulmoStudioSchema, mulmoStudioBeatSchema, mulmoStoryboardSchema, mulmoStoryboardSceneSchema, mulmoStudioMultiLingualSchema, mulmoStudioMultiLingualDataSchema, speakerDictionarySchema, mulmoImageParamsSchema, mulmoImageParamsImagesSchema, mulmoFillOptionSchema, mulmoMovieParamsSchema, mulmoSpeechParamsSchema, textSlideParamsSchema, speechOptionsSchema, speakerDataSchema, mulmoCanvasDimensionSchema, mulmoScriptTemplateSchema, mulmoScriptTemplateFileSchema, text2ImageProviderSchema, text2HtmlImageProviderSchema, 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";
@@ -10,8 +10,10 @@ export type SpeechOptions = z.infer<typeof speechOptionsSchema>;
10
10
  export type SpeakerData = z.infer<typeof speakerDataSchema>;
11
11
  export type MulmoImageParams = z.infer<typeof mulmoImageParamsSchema>;
12
12
  export type MulmoImageParamsImages = z.infer<typeof mulmoImageParamsImagesSchema>;
13
+ export type MulmoFillOption = z.infer<typeof mulmoFillOptionSchema>;
13
14
  export type TextSlideParams = z.infer<typeof textSlideParamsSchema>;
14
15
  export type Text2ImageProvider = z.infer<typeof text2ImageProviderSchema>;
16
+ export type Text2HtmlImageProvider = z.infer<typeof text2HtmlImageProviderSchema>;
15
17
  export type Text2MovieProvider = z.infer<typeof text2MovieProviderSchema>;
16
18
  export type Text2SpeechProvider = z.infer<typeof text2SpeechProviderSchema>;
17
19
  export type LocalizedText = z.infer<typeof localizedTextSchema>;
@@ -49,7 +51,6 @@ export type MulmoStudioContext = {
49
51
  lang?: string;
50
52
  dryRun?: boolean;
51
53
  force: boolean;
52
- caption?: string;
53
54
  sessionState: MulmoSessionState;
54
55
  presentationStyle: MulmoPresentationStyle;
55
56
  multiLingual: MulmoStudioMultiLingual;
@@ -62,6 +63,7 @@ export type ScriptingParams = {
62
63
  filename: string;
63
64
  llm_model?: string;
64
65
  llm?: LLM;
66
+ verbose?: boolean;
65
67
  };
66
68
  export type ImageProcessorParams = {
67
69
  beat: MulmoBeat;
@@ -77,6 +79,11 @@ export type Text2ImageAgentInfo = {
77
79
  agent: string;
78
80
  imageParams: MulmoImageParams;
79
81
  };
82
+ export type Text2HtmlAgentInfo = {
83
+ provider: Text2HtmlImageProvider;
84
+ agent: string;
85
+ model: string;
86
+ };
80
87
  export type BeatMediaType = "movie" | "image";
81
88
  export type StoryToScriptGenerateMode = (typeof storyToScriptGenerateMode)[keyof typeof storyToScriptGenerateMode];
82
89
  export type SessionType = "audio" | "image" | "video" | "multiLingual" | "caption" | "pdf";
@@ -7,7 +7,7 @@ export type FfmpegContext = {
7
7
  export declare const FfmpegContextInit: () => FfmpegContext;
8
8
  export declare const FfmpegContextAddInput: (context: FfmpegContext, input: string, inputOptions?: string[]) => number;
9
9
  export declare const FfmpegContextPushFormattedAudio: (context: FfmpegContext, sourceId: string, outputId: string, duration?: number | undefined) => void;
10
- export declare const FfmpegContextInputFormattedAudio: (context: FfmpegContext, input: string, duration?: number | undefined) => string;
10
+ export declare const FfmpegContextInputFormattedAudio: (context: FfmpegContext, input: string, duration?: number | undefined, inputOptions?: string[]) => string;
11
11
  export declare const FfmpegContextGenerateOutput: (context: FfmpegContext, output: string, options?: string[]) => Promise<number>;
12
12
  export declare const ffmpegGetMediaDuration: (filePath: string) => Promise<number>;
13
13
  export declare const extractImageFromMovie: (movieFile: string, imagePath: string) => Promise<void>;
@@ -25,8 +25,8 @@ export const FfmpegContextPushFormattedAudio = (context, sourceId, outputId, dur
25
25
  context.filterComplex.push(`${sourceId}aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo${outputId}`);
26
26
  }
27
27
  };
28
- export const FfmpegContextInputFormattedAudio = (context, input, duration = undefined) => {
29
- const index = FfmpegContextAddInput(context, input);
28
+ export const FfmpegContextInputFormattedAudio = (context, input, duration = undefined, inputOptions) => {
29
+ const index = FfmpegContextAddInput(context, input, inputOptions);
30
30
  const audioId = `[a${index}]`;
31
31
  FfmpegContextPushFormattedAudio(context, `[${index}:a]`, audioId, duration);
32
32
  return audioId;
@@ -182,8 +182,8 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
182
182
  } | undefined;
183
183
  description?: string | undefined;
184
184
  imageParams?: {
185
- model?: string | undefined;
186
185
  style?: string | undefined;
186
+ model?: string | undefined;
187
187
  moderation?: string | undefined;
188
188
  images?: Record<string, {
189
189
  type: "image";
@@ -205,9 +205,21 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
205
205
  audioParams?: {
206
206
  padding?: number | undefined;
207
207
  } | undefined;
208
+ movieParams?: {
209
+ fillOption: {
210
+ style: "aspectFit" | "aspectFill";
211
+ };
212
+ } | undefined;
213
+ htmlImageParams?: {
214
+ model?: string | undefined;
215
+ } | undefined;
208
216
  textSlideParams?: {
209
217
  cssStyles: string | string[];
210
218
  } | undefined;
219
+ captionParams?: {
220
+ styles: string[];
221
+ lang?: string | undefined;
222
+ } | undefined;
211
223
  imageNames?: string[] | undefined;
212
224
  imagePrompt?: string | undefined;
213
225
  moviePrompt?: string | undefined;
@@ -223,8 +235,8 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
223
235
  description?: string | undefined;
224
236
  imageParams?: {
225
237
  provider: "openai" | "google";
226
- model?: string | undefined;
227
238
  style?: string | undefined;
239
+ model?: string | undefined;
228
240
  moderation?: string | undefined;
229
241
  images?: Record<string, {
230
242
  type: "image";
@@ -243,17 +255,28 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
243
255
  };
244
256
  }> | undefined;
245
257
  } | undefined;
246
- textSlideParams?: {
247
- cssStyles: string | string[];
248
- } | undefined;
249
258
  movieParams?: {
250
- provider?: "openai" | "google" | undefined;
259
+ provider?: "openai" | "google" | "replicate" | undefined;
251
260
  model?: string | undefined;
261
+ fillOption?: {
262
+ style: "aspectFit" | "aspectFill";
263
+ } | undefined;
252
264
  transition?: {
253
265
  type: "fade" | "slideout_left";
254
266
  duration: number;
255
267
  } | undefined;
256
268
  } | undefined;
269
+ htmlImageParams?: {
270
+ provider: "openai" | "anthropic";
271
+ model?: string | undefined;
272
+ } | undefined;
273
+ textSlideParams?: {
274
+ cssStyles: string | string[];
275
+ } | undefined;
276
+ captionParams?: {
277
+ styles: string[];
278
+ lang?: string | undefined;
279
+ } | undefined;
257
280
  references?: {
258
281
  type: "image" | "audio" | "article" | "paper" | "video";
259
282
  url: string;
@@ -1,4 +1,4 @@
1
- import { MulmoBeat, MulmoScript, MulmoScriptTemplate, MulmoStoryboard } from "../types/index.js";
1
+ import { MulmoBeat, MulmoScript, MulmoScriptTemplate, MulmoStoryboard, MulmoCanvasDimension } from "../types/index.js";
2
2
  export declare const imagePrompt: (beat: MulmoBeat, style?: string) => string;
3
3
  export declare const graphDataScriptFromUrlPrompt: (sourceTextInput: string) => string;
4
4
  export declare const graphDataScriptGeneratePrompt: (scene: string) => string;
@@ -17,3 +17,4 @@ export declare const storyToScriptPrompt: (script: MulmoScript, beatsPerScene: n
17
17
  export declare const searchQueryPrompt: (inquiry: string, followUpQueries: string) => string;
18
18
  export declare const reflectionPrompt: (researchTopic: string, searchResults: string) => string;
19
19
  export declare const finalAnswerPrompt: (userInput: string, searchResults: string, researchTopic: string) => string;
20
+ export declare const htmlImageSystemPrompt: (canvasSize: MulmoCanvasDimension) => string[];
@@ -124,3 +124,13 @@ export const finalAnswerPrompt = (userInput, searchResults, researchTopic) => {
124
124
  Current Date: ${currentDate}
125
125
  `;
126
126
  };
127
+ export const htmlImageSystemPrompt = (canvasSize) => {
128
+ return [
129
+ "Based on the provided information, create a single slide HTML page using Tailwind CSS.",
130
+ `The view port size is ${canvasSize.width}x${canvasSize.height}. Make sure the HTML fits within the view port.`,
131
+ "If charts are needed, use Chart.js to present them in a clean and visually appealing way.",
132
+ "Include a balanced mix of comments, graphs, and illustrations to enhance visual impact.",
133
+ "Output only the HTML code. Do not include any comments, explanations, or additional information outside the HTML.",
134
+ "If data is provided, use it effectively to populate the slide.",
135
+ ];
136
+ };
@@ -1,4 +1,5 @@
1
1
  import { MulmoBeat, MulmoStudioMultiLingualData } from "../types/index.js";
2
+ import type { ConfigDataDictionary, DefaultConfigData } from "graphai";
2
3
  export declare const llm: readonly ["openAI", "anthropic", "gemini", "groq"];
3
4
  export type LLM = (typeof llm)[number];
4
5
  export declare const llmConfig: Record<LLM, {
@@ -16,3 +17,5 @@ export declare const isHttp: (fileOrUrl: string) => boolean;
16
17
  export declare const text2hash: (input: string) => string;
17
18
  export declare const localizedText: (beat: MulmoBeat, multiLingualData?: MulmoStudioMultiLingualData, lang?: string) => string;
18
19
  export declare const sleep: (milliseconds: number) => Promise<unknown>;
20
+ export declare function userAssert(condition: boolean, message: string): asserts condition;
21
+ export declare const settings2GraphAIConfig: (settings?: Record<string, string>) => ConfigDataDictionary<DefaultConfigData>;
@@ -55,3 +55,50 @@ export const localizedText = (beat, multiLingualData, lang) => {
55
55
  export const sleep = async (milliseconds) => {
56
56
  return await new Promise((resolve) => setTimeout(resolve, milliseconds));
57
57
  };
58
+ export function userAssert(condition, message) {
59
+ if (!condition) {
60
+ throw new Error(message);
61
+ }
62
+ }
63
+ export const settings2GraphAIConfig = (settings) => {
64
+ const config = {};
65
+ if (settings) {
66
+ if (settings.OPENAI_API_KEY) {
67
+ config.openAIAgent = {
68
+ apiKey: settings.OPENAI_API_KEY,
69
+ };
70
+ config.ttsOpenaiAgent = {
71
+ apiKey: settings.OPENAI_API_KEY,
72
+ };
73
+ config.imageOpenaiAgent = {
74
+ apiKey: settings.OPENAI_API_KEY,
75
+ };
76
+ }
77
+ if (settings.ANTHROPIC_API_TOKEN) {
78
+ config.anthropicAgent = {
79
+ apiKey: settings.ANTHROPIC_API_TOKEN,
80
+ };
81
+ }
82
+ if (settings.REPLICATE_API_TOKEN) {
83
+ config.movieReplicateAgent = {
84
+ apiKey: settings.REPLICATE_API_TOKEN,
85
+ };
86
+ }
87
+ if (settings.NIJIVOICE_API_KEY) {
88
+ config.ttsNijivoiceAgent = {
89
+ apiKey: settings.NIJIVOICE_API_KEY,
90
+ };
91
+ }
92
+ if (settings.ELEVENLABS_API_KEY) {
93
+ config.ttsElevenlabsAgent = {
94
+ apiKey: settings.ELEVENLABS_API_KEY,
95
+ };
96
+ }
97
+ // TODO
98
+ // browserlessAgent
99
+ // ttsGoogleAgent
100
+ // geminiAgent, groqAgent for tool
101
+ // TAVILY_API_KEY ( for deep research)
102
+ }
103
+ return config;
104
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -74,11 +74,12 @@
74
74
  "dotenv": "^16.4.7",
75
75
  "fluent-ffmpeg": "^2.1.3",
76
76
  "google-auth-library": "^9.15.1",
77
- "graphai": "^2.0.8",
77
+ "graphai": "^2.0.9",
78
78
  "inquirer": "^12.6.1",
79
79
  "marked": "^15.0.12",
80
80
  "ora": "^8.2.0",
81
81
  "puppeteer": "^24.10.2",
82
+ "replicate": "^1.0.1",
82
83
  "yaml": "^2.8.0",
83
84
  "yargs": "^17.7.2",
84
85
  "zod": "^3.25.67",
@@ -0,0 +1,123 @@
1
+ {
2
+ "$mulmocast": {
3
+ "version": "1.0",
4
+ "credit": "closing"
5
+ },
6
+ "htmlImageParams": {
7
+ "provider": "anthropic",
8
+ "model": "claude-3-7-sonnet-20250219"
9
+ },
10
+ "title": "Sample Title",
11
+ "references": [
12
+ {
13
+ "url": "https://www.somegreatwebsite.com/article/123",
14
+ "title": "Title of the article we are referencing",
15
+ "type": "article"
16
+ }
17
+ ],
18
+ "lang": "en",
19
+ "beats": [
20
+ {
21
+ "speaker": "Presenter",
22
+ "text": "Book rooms with locals, not hotels.",
23
+ "htmlPrompt": {
24
+ "prompt": "Create a clean and bold title slide featuring the original name 'AirBed & Breakfast' with the tagline: 'Book rooms with locals, not hotels'. Include the old logo and a travel-themed background."
25
+ }
26
+ },
27
+ {
28
+ "speaker": "Presenter",
29
+ "text": "Hotels are expensive and detached from local culture.",
30
+ "htmlPrompt": {
31
+ "prompt": "Design a slide that lists the main problems with hotels: high prices, lack of personality, and cultural disconnection. Use simple icons for cost, generic room, and traveler."
32
+ }
33
+ },
34
+ {
35
+ "speaker": "Presenter",
36
+ "text": "Airbnb lets people rent out their spaces, offering affordable, authentic experiences.",
37
+ "htmlPrompt": {
38
+ "prompt": "Illustrate Airbnb's solution: locals listing their spare rooms or homes, travelers booking directly, and both benefiting. Use a flow diagram to represent this."
39
+ }
40
+ },
41
+ {
42
+ "speaker": "Presenter",
43
+ "text": "Craigslist and Couchsurfing prove the demand for alternative lodging.",
44
+ "htmlPrompt": {
45
+ "prompt": "Show a bar graph comparing Craigslist listings, Couchsurfing users, and early Airbnb listings to demonstrate existing demand and opportunity."
46
+ }
47
+ },
48
+ {
49
+ "speaker": "Presenter",
50
+ "text": "A massive market: over 630 million travel bookings annually.",
51
+ "htmlPrompt": {
52
+ "prompt": "Visualize the global travel booking market. Use a world map and large numbers to emphasize the size and growth potential."
53
+ }
54
+ },
55
+ {
56
+ "speaker": "Presenter",
57
+ "text": "Our platform enables hosts to list once and earn; guests search, book, and review.",
58
+ "htmlPrompt": {
59
+ "prompt": "Create a product overview slide showing how the platform works from host listing to guest review. Highlight simplicity and trust."
60
+ }
61
+ },
62
+ {
63
+ "speaker": "Presenter",
64
+ "text": "We charge a 10% commission per booking.",
65
+ "htmlPrompt": {
66
+ "prompt": "Display a slide with the monetization strategy—Airbnb earns through a 10% commission. Use a simple pie chart or booking flow with fee annotation."
67
+ }
68
+ },
69
+ {
70
+ "speaker": "Presenter",
71
+ "text": "Competitors include hotels, Craigslist, Couchsurfing — we offer a better, scalable solution.",
72
+ "htmlPrompt": {
73
+ "prompt": "Design a comparison table: price, uniqueness, trust, scalability. Airbnb should clearly stand out on all dimensions."
74
+ }
75
+ },
76
+ {
77
+ "speaker": "Presenter",
78
+ "text": "Key advantages: lower price, wide selection, ease of use, host incentives, trusted system.",
79
+ "htmlPrompt": {
80
+ "prompt": "List Airbnb’s competitive advantages using 6 icons or badges, one for each feature."
81
+ }
82
+ },
83
+ {
84
+ "speaker": "Presenter",
85
+ "text": "Founders: Brian Chesky (Design), Joe Gebbia (Marketing), Nathan Blecharczyk (Engineering).",
86
+ "htmlPrompt": {
87
+ "prompt": "Introduce the founding team with photos and brief bios. Highlight their roles and strengths in product, marketing, and tech."
88
+ }
89
+ },
90
+ {
91
+ "speaker": "Presenter",
92
+ "text": "Media buzz: featured on TechCrunch and buzz from SXSW.",
93
+ "htmlPrompt": {
94
+ "prompt": "Showcase media recognition. Include TechCrunch logo and SXSW quotes or metrics. This adds credibility and traction."
95
+ }
96
+ },
97
+ {
98
+ "speaker": "Presenter",
99
+ "text": "Early users love the authentic and affordable experiences.",
100
+ "htmlPrompt": {
101
+ "prompt": "Add 2–3 short testimonials from early users (guests and hosts), displayed in speech bubbles with faces or usernames."
102
+ }
103
+ },
104
+ {
105
+ "speaker": "Presenter",
106
+ "text": "We’re raising $600K to support 12 months of growth and reach 80K bookings with $2M in revenue.",
107
+ "htmlPrompt": {
108
+ "prompt": "Closing investment slide. Include fund usage (pie chart: 40% marketing, 30% product, 30% ops), and KPIs: 80K bookings, $2M revenue.",
109
+ "data": {
110
+ "ask": 600000,
111
+ "duration_months": 12,
112
+ "target_bookings": 80000,
113
+ "target_revenue": 2000000,
114
+ "use_of_funds": {
115
+ "marketing": 40,
116
+ "product": 30,
117
+ "operations": 30
118
+ }
119
+ }
120
+ }
121
+ }
122
+ ]
123
+ }
@@ -0,0 +1,119 @@
1
+ {
2
+ "$mulmocast": {
3
+ "version": "1.0",
4
+ "credit": "closing"
5
+ },
6
+ "title": "Sample Title",
7
+ "references": [
8
+ {
9
+ "url": "https://www.somegreatwebsite.com/article/123",
10
+ "title": "Title of the article we are referencing",
11
+ "type": "article"
12
+ }
13
+ ],
14
+ "lang": "en",
15
+ "beats": [
16
+ {
17
+ "speaker": "Presenter",
18
+ "text": "Book rooms with locals, not hotels.",
19
+ "htmlPrompt": {
20
+ "prompt": "Create a clean and bold title slide featuring the original name 'AirBed & Breakfast' with the tagline: 'Book rooms with locals, not hotels'. Include the old logo and a travel-themed background."
21
+ }
22
+ },
23
+ {
24
+ "speaker": "Presenter",
25
+ "text": "Hotels are expensive and detached from local culture.",
26
+ "htmlPrompt": {
27
+ "prompt": "Design a slide that lists the main problems with hotels: high prices, lack of personality, and cultural disconnection. Use simple icons for cost, generic room, and traveler."
28
+ }
29
+ },
30
+ {
31
+ "speaker": "Presenter",
32
+ "text": "Airbnb lets people rent out their spaces, offering affordable, authentic experiences.",
33
+ "htmlPrompt": {
34
+ "prompt": "Illustrate Airbnb's solution: locals listing their spare rooms or homes, travelers booking directly, and both benefiting. Use a flow diagram to represent this."
35
+ }
36
+ },
37
+ {
38
+ "speaker": "Presenter",
39
+ "text": "Craigslist and Couchsurfing prove the demand for alternative lodging.",
40
+ "htmlPrompt": {
41
+ "prompt": "Show a bar graph comparing Craigslist listings, Couchsurfing users, and early Airbnb listings to demonstrate existing demand and opportunity."
42
+ }
43
+ },
44
+ {
45
+ "speaker": "Presenter",
46
+ "text": "A massive market: over 630 million travel bookings annually.",
47
+ "htmlPrompt": {
48
+ "prompt": "Visualize the global travel booking market. Use a world map and large numbers to emphasize the size and growth potential."
49
+ }
50
+ },
51
+ {
52
+ "speaker": "Presenter",
53
+ "text": "Our platform enables hosts to list once and earn; guests search, book, and review.",
54
+ "htmlPrompt": {
55
+ "prompt": "Create a product overview slide showing how the platform works from host listing to guest review. Highlight simplicity and trust."
56
+ }
57
+ },
58
+ {
59
+ "speaker": "Presenter",
60
+ "text": "We charge a 10% commission per booking.",
61
+ "htmlPrompt": {
62
+ "prompt": "Display a slide with the monetization strategy—Airbnb earns through a 10% commission. Use a simple pie chart or booking flow with fee annotation."
63
+ }
64
+ },
65
+ {
66
+ "speaker": "Presenter",
67
+ "text": "Competitors include hotels, Craigslist, Couchsurfing — we offer a better, scalable solution.",
68
+ "htmlPrompt": {
69
+ "prompt": "Design a comparison table: price, uniqueness, trust, scalability. Airbnb should clearly stand out on all dimensions."
70
+ }
71
+ },
72
+ {
73
+ "speaker": "Presenter",
74
+ "text": "Key advantages: lower price, wide selection, ease of use, host incentives, trusted system.",
75
+ "htmlPrompt": {
76
+ "prompt": "List Airbnb’s competitive advantages using 6 icons or badges, one for each feature."
77
+ }
78
+ },
79
+ {
80
+ "speaker": "Presenter",
81
+ "text": "Founders: Brian Chesky (Design), Joe Gebbia (Marketing), Nathan Blecharczyk (Engineering).",
82
+ "htmlPrompt": {
83
+ "prompt": "Introduce the founding team with photos and brief bios. Highlight their roles and strengths in product, marketing, and tech."
84
+ }
85
+ },
86
+ {
87
+ "speaker": "Presenter",
88
+ "text": "Media buzz: featured on TechCrunch and buzz from SXSW.",
89
+ "htmlPrompt": {
90
+ "prompt": "Showcase media recognition. Include TechCrunch logo and SXSW quotes or metrics. This adds credibility and traction."
91
+ }
92
+ },
93
+ {
94
+ "speaker": "Presenter",
95
+ "text": "Early users love the authentic and affordable experiences.",
96
+ "htmlPrompt": {
97
+ "prompt": "Add 2–3 short testimonials from early users (guests and hosts), displayed in speech bubbles with faces or usernames."
98
+ }
99
+ },
100
+ {
101
+ "speaker": "Presenter",
102
+ "text": "We’re raising $600K to support 12 months of growth and reach 80K bookings with $2M in revenue.",
103
+ "htmlPrompt": {
104
+ "prompt": "Closing investment slide. Include fund usage (pie chart: 40% marketing, 30% product, 30% ops), and KPIs: 80K bookings, $2M revenue.",
105
+ "data": {
106
+ "ask": 600000,
107
+ "duration_months": 12,
108
+ "target_bookings": 80000,
109
+ "target_revenue": 2000000,
110
+ "use_of_funds": {
111
+ "marketing": 40,
112
+ "product": 30,
113
+ "operations": 30
114
+ }
115
+ }
116
+ }
117
+ }
118
+ ]
119
+ }