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.
Files changed (58) hide show
  1. package/assets/templates/akira_comic.json +1 -1
  2. package/assets/templates/ani.json +48 -0
  3. package/assets/templates/ani_ja.json +44 -0
  4. package/assets/templates/characters.json +1 -1
  5. package/assets/templates/children_book.json +1 -1
  6. package/assets/templates/comic_strips.json +1 -1
  7. package/assets/templates/drslump_comic.json +1 -1
  8. package/assets/templates/ghibli_comic.json +1 -1
  9. package/assets/templates/ghibli_image_only.json +1 -1
  10. package/assets/templates/ghibli_shorts.json +2 -3
  11. package/assets/templates/ghost_comic.json +1 -1
  12. package/assets/templates/onepiece_comic.json +1 -1
  13. package/assets/templates/portrait_movie.json +1 -1
  14. package/assets/templates/realistic_movie.json +1 -1
  15. package/assets/templates/sensei_and_taro.json +4 -5
  16. package/assets/templates/shorts.json +1 -1
  17. package/assets/templates/trailer.json +1 -1
  18. package/lib/actions/audio.js +8 -7
  19. package/lib/actions/image_agents.d.ts +53 -98
  20. package/lib/actions/image_agents.js +14 -6
  21. package/lib/actions/images.js +42 -13
  22. package/lib/actions/movie.js +1 -1
  23. package/lib/agents/index.d.ts +2 -1
  24. package/lib/agents/index.js +2 -1
  25. package/lib/agents/movie_replicate_agent.js +18 -5
  26. package/lib/agents/sound_effect_replicate_agent.d.ts +5 -0
  27. package/lib/agents/sound_effect_replicate_agent.js +59 -0
  28. package/lib/cli/commands/tool/scripting/builder.js +1 -1
  29. package/lib/cli/commands/tool/scripting/handler.d.ts +1 -1
  30. package/lib/cli/commands/tool/story_to_script/builder.js +1 -1
  31. package/lib/cli/commands/tool/story_to_script/handler.d.ts +1 -1
  32. package/lib/mcp/server.js +2 -2
  33. package/lib/methods/index.d.ts +1 -0
  34. package/lib/methods/index.js +1 -0
  35. package/lib/methods/mulmo_presentation_style.d.ts +25 -6
  36. package/lib/methods/mulmo_presentation_style.js +33 -30
  37. package/lib/methods/mulmo_script.d.ts +4 -0
  38. package/lib/methods/mulmo_script.js +31 -0
  39. package/lib/tools/story_to_script.d.ts +1 -1
  40. package/lib/types/agent.d.ts +9 -0
  41. package/lib/types/schema.d.ts +727 -554
  42. package/lib/types/schema.js +41 -24
  43. package/lib/types/type.d.ts +4 -4
  44. package/lib/utils/assets.d.ts +18 -0
  45. package/lib/utils/assets.js +101 -0
  46. package/lib/utils/context.d.ts +98 -84
  47. package/lib/utils/context.js +2 -1
  48. package/lib/utils/ffmpeg_utils.js +6 -0
  49. package/lib/utils/file.d.ts +4 -1
  50. package/lib/utils/file.js +3 -5
  51. package/lib/utils/preprocess.d.ts +57 -47
  52. package/lib/utils/preprocess.js +7 -5
  53. package/lib/utils/provider2agent.d.ts +27 -7
  54. package/lib/utils/provider2agent.js +85 -7
  55. package/lib/utils/utils.d.ts +1 -2
  56. package/lib/utils/utils.js +4 -2
  57. package/package.json +7 -7
  58. package/scripts/templates/presentation.json~ +0 -119
@@ -1,5 +1,5 @@
1
- import { MulmoStudio, MulmoScript } from "../types/index.js";
2
- export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, currentStudio: MulmoStudio | undefined, fileName: string, videoCaption?: string) => {
1
+ import { MulmoStudio, MulmoScript, MulmoPresentationStyle } from "../types/index.js";
2
+ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, currentStudio: MulmoStudio | undefined, fileName: string, videoCaption?: string, presentationStyle?: MulmoPresentationStyle | null) => {
3
3
  beats: {
4
4
  duration?: number | undefined;
5
5
  startAt?: number | undefined;
@@ -11,9 +11,35 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
11
11
  audioFile?: string | undefined;
12
12
  imageFile?: string | undefined;
13
13
  movieFile?: string | undefined;
14
+ soundEffectFile?: string | undefined;
14
15
  captionFile?: string | undefined;
15
16
  }[];
16
17
  script: {
18
+ imageParams: {
19
+ provider: string;
20
+ model?: string | undefined;
21
+ style?: string | undefined;
22
+ moderation?: string | undefined;
23
+ images?: Record<string, {
24
+ type: "image";
25
+ source: {
26
+ url: string;
27
+ kind: "url";
28
+ } | {
29
+ kind: "base64";
30
+ data: string;
31
+ } | {
32
+ text: string;
33
+ kind: "text";
34
+ } | {
35
+ path: string;
36
+ kind: "path";
37
+ };
38
+ } | {
39
+ type: "imagePrompt";
40
+ prompt: string;
41
+ }> | undefined;
42
+ };
17
43
  audioParams: {
18
44
  padding: number;
19
45
  introPadding: number;
@@ -36,8 +62,23 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
36
62
  kind: "path";
37
63
  } | undefined;
38
64
  };
65
+ movieParams: {
66
+ provider?: string | undefined;
67
+ model?: string | undefined;
68
+ fillOption?: {
69
+ style: "aspectFit" | "aspectFill";
70
+ } | undefined;
71
+ transition?: {
72
+ type: "fade" | "slideout_left";
73
+ duration: number;
74
+ } | undefined;
75
+ };
76
+ soundEffectParams: {
77
+ provider?: string | undefined;
78
+ model?: string | undefined;
79
+ };
39
80
  $mulmocast: {
40
- version: "1.0";
81
+ version: "1.1";
41
82
  credit?: "closing" | undefined;
42
83
  };
43
84
  canvasSize: {
@@ -45,10 +86,10 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
45
86
  height: number;
46
87
  };
47
88
  speechParams: {
48
- provider: string;
49
89
  speakers: Record<string, {
50
90
  voiceId: string;
51
91
  displayName?: Record<string, string> | undefined;
92
+ isDefault?: boolean | undefined;
52
93
  speechOptions?: {
53
94
  speed?: number | undefined;
54
95
  instruction?: string | undefined;
@@ -56,16 +97,9 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
56
97
  provider?: string | undefined;
57
98
  model?: string | undefined;
58
99
  }>;
59
- model?: string | undefined;
60
100
  };
61
101
  beats: {
62
102
  text: string;
63
- speaker: string;
64
- duration?: number | undefined;
65
- speechOptions?: {
66
- speed?: number | undefined;
67
- instruction?: string | undefined;
68
- } | undefined;
69
103
  image?: {
70
104
  type: "markdown";
71
105
  markdown: string | string[];
@@ -170,6 +204,11 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
170
204
  type: "voice_over";
171
205
  startAt?: number | undefined;
172
206
  } | undefined;
207
+ duration?: number | undefined;
208
+ speechOptions?: {
209
+ speed?: number | undefined;
210
+ instruction?: string | undefined;
211
+ } | undefined;
173
212
  id?: string | undefined;
174
213
  audio?: {
175
214
  type: "audio";
@@ -191,6 +230,7 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
191
230
  source: string;
192
231
  } | undefined;
193
232
  imagePrompt?: string | undefined;
233
+ speaker?: string | undefined;
194
234
  description?: string | undefined;
195
235
  imageParams?: {
196
236
  provider: string;
@@ -223,11 +263,16 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
223
263
  } | undefined;
224
264
  movieParams?: {
225
265
  speed?: number | undefined;
266
+ provider?: string | undefined;
226
267
  model?: string | undefined;
227
268
  fillOption?: {
228
269
  style: "aspectFit" | "aspectFill";
229
270
  } | undefined;
230
271
  } | undefined;
272
+ soundEffectParams?: {
273
+ provider?: string | undefined;
274
+ model?: string | undefined;
275
+ } | undefined;
231
276
  htmlImageParams?: {
232
277
  model?: string | undefined;
233
278
  } | undefined;
@@ -240,6 +285,7 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
240
285
  } | undefined;
241
286
  imageNames?: string[] | undefined;
242
287
  moviePrompt?: string | undefined;
288
+ soundEffectPrompt?: string | undefined;
243
289
  htmlPrompt?: {
244
290
  prompt: string;
245
291
  data?: any;
@@ -250,42 +296,6 @@ export declare const createOrUpdateStudioData: (_mulmoScript: MulmoScript, curre
250
296
  lang?: string | undefined;
251
297
  title?: string | undefined;
252
298
  description?: string | undefined;
253
- imageParams?: {
254
- provider: string;
255
- model?: string | undefined;
256
- style?: string | undefined;
257
- moderation?: string | undefined;
258
- images?: Record<string, {
259
- type: "image";
260
- source: {
261
- url: string;
262
- kind: "url";
263
- } | {
264
- kind: "base64";
265
- data: string;
266
- } | {
267
- text: string;
268
- kind: "text";
269
- } | {
270
- path: string;
271
- kind: "path";
272
- };
273
- } | {
274
- type: "imagePrompt";
275
- prompt: string;
276
- }> | undefined;
277
- } | undefined;
278
- movieParams?: {
279
- provider?: string | undefined;
280
- model?: string | undefined;
281
- fillOption?: {
282
- style: "aspectFit" | "aspectFill";
283
- } | undefined;
284
- transition?: {
285
- type: "fade" | "slideout_left";
286
- duration: number;
287
- } | undefined;
288
- } | undefined;
289
299
  htmlImageParams?: {
290
300
  provider: string;
291
301
  model?: string | undefined;
@@ -1,5 +1,6 @@
1
1
  import { GraphAILogger } from "graphai";
2
- import { mulmoScriptSchema, mulmoStudioSchema, mulmoCaptionParamsSchema } from "../types/index.js";
2
+ import { mulmoStudioSchema, mulmoCaptionParamsSchema } from "../types/index.js";
3
+ import { MulmoPresentationStyleMethods, MulmoScriptMethods } from "../methods/index.js";
3
4
  const rebuildStudio = (currentStudio, mulmoScript, fileName) => {
4
5
  const isTest = process.env.NODE_ENV === "test";
5
6
  const parsed = isTest && currentStudio ? { data: mulmoStudioSchema.parse(currentStudio), success: true, error: null } : mulmoStudioSchema.safeParse(currentStudio);
@@ -36,15 +37,16 @@ const mulmoCredit = (speaker) => {
36
37
  },
37
38
  };
38
39
  };
39
- export const createOrUpdateStudioData = (_mulmoScript, currentStudio, fileName, videoCaption) => {
40
- const mulmoScript = _mulmoScript.__test_invalid__ ? _mulmoScript : mulmoScriptSchema.parse(_mulmoScript); // validate and insert default value
40
+ export const createOrUpdateStudioData = (_mulmoScript, currentStudio, fileName, videoCaption, presentationStyle) => {
41
+ const mulmoScript = _mulmoScript.__test_invalid__ ? _mulmoScript : MulmoScriptMethods.validate(_mulmoScript); // validate and insert default value
41
42
  const studio = rebuildStudio(currentStudio, mulmoScript, fileName);
42
43
  // TODO: Move this code out of this function later
43
44
  // Addition cloing credit
44
45
  if (mulmoScript.$mulmocast.credit === "closing") {
45
- mulmoScript.beats.push(mulmoCredit(mulmoScript.beats[0].speaker)); // First speaker
46
+ const defaultSpeaker = MulmoPresentationStyleMethods.getDefaultSpeaker(presentationStyle ?? studio.script);
47
+ mulmoScript.beats.push(mulmoCredit(mulmoScript.beats[0].speaker ?? defaultSpeaker)); // First speaker
46
48
  }
47
- studio.script = mulmoScriptSchema.parse(mulmoScript); // update the script
49
+ studio.script = MulmoScriptMethods.validate(mulmoScript); // update the script
48
50
  studio.beats = studio.script.beats.map((_, index) => studio.beats[index] ?? {});
49
51
  if (videoCaption) {
50
52
  studio.script.captionParams = mulmoCaptionParamsSchema.parse({
@@ -1,10 +1,3 @@
1
- export declare const defaultProviders: {
2
- tts: string;
3
- text2image: string;
4
- text2movie: string;
5
- text2Html: string;
6
- llm: string;
7
- };
8
1
  export declare const provider2TTSAgent: {
9
2
  nijivoice: {
10
3
  agentName: string;
@@ -39,16 +32,35 @@ export declare const provider2ImageAgent: {
39
32
  models: string[];
40
33
  };
41
34
  };
35
+ export type ReplicateModel = `${string}/${string}`;
42
36
  export declare const provider2MovieAgent: {
43
37
  replicate: {
44
38
  agentName: string;
39
+ defaultModel: ReplicateModel;
45
40
  models: string[];
41
+ modelParams: Record<ReplicateModel, {
42
+ durations: number[];
43
+ start_image: string | undefined;
44
+ last_image?: string;
45
+ price_per_sec: number;
46
+ }>;
46
47
  };
47
48
  google: {
48
49
  agentName: string;
50
+ defaultModel: string;
49
51
  models: string[];
50
52
  };
51
53
  };
54
+ export declare const provider2SoundEffectAgent: {
55
+ replicate: {
56
+ agentName: string;
57
+ defaultModel: ReplicateModel;
58
+ models: ReplicateModel[];
59
+ modelParams: Record<ReplicateModel, {
60
+ identifier?: `${string}/${string}:${string}`;
61
+ }>;
62
+ };
63
+ };
52
64
  export declare const provider2LLMAgent: {
53
65
  readonly openai: {
54
66
  readonly agentName: "openAIAgent";
@@ -71,6 +83,14 @@ export declare const provider2LLMAgent: {
71
83
  readonly max_tokens: 4096;
72
84
  };
73
85
  };
86
+ export declare const defaultProviders: {
87
+ tts: keyof typeof provider2TTSAgent;
88
+ text2image: keyof typeof provider2ImageAgent;
89
+ text2movie: keyof typeof provider2MovieAgent;
90
+ text2Html: keyof typeof provider2LLMAgent;
91
+ llm: keyof typeof provider2LLMAgent;
92
+ soundEffect: keyof typeof provider2SoundEffectAgent;
93
+ };
74
94
  export declare const llm: (keyof typeof provider2LLMAgent)[];
75
95
  export type LLM = keyof typeof provider2LLMAgent;
76
96
  export declare const htmlLLMProvider: string[];
@@ -1,10 +1,3 @@
1
- export const defaultProviders = {
2
- tts: "openai",
3
- text2image: "openai",
4
- text2movie: "google",
5
- text2Html: "openai",
6
- llm: "openai",
7
- };
8
1
  export const provider2TTSAgent = {
9
2
  nijivoice: {
10
3
  agentName: "ttsNijivoiceAgent",
@@ -44,22 +37,99 @@ export const provider2ImageAgent = {
44
37
  export const provider2MovieAgent = {
45
38
  replicate: {
46
39
  agentName: "movieReplicateAgent",
40
+ defaultModel: "bytedance/seedance-1-lite",
47
41
  models: [
48
42
  "bytedance/seedance-1-lite",
49
43
  "bytedance/seedance-1-pro",
50
44
  "kwaivgi/kling-v1.6-pro",
51
45
  "kwaivgi/kling-v2.1",
46
+ "kwaivgi/kling-v2.1-master",
52
47
  "google/veo-2",
53
48
  "google/veo-3",
54
49
  "google/veo-3-fast",
55
50
  "minimax/video-01",
51
+ "minimax/hailuo-02",
52
+ "pixverse/pixverse-v4.5",
56
53
  ],
54
+ modelParams: {
55
+ "bytedance/seedance-1-lite": {
56
+ durations: [5, 10],
57
+ start_image: "image",
58
+ last_image: "last_frame_image",
59
+ price_per_sec: 0.036, // in USD
60
+ },
61
+ "bytedance/seedance-1-pro": {
62
+ durations: [5, 10],
63
+ start_image: "image",
64
+ last_image: "last_frame_image",
65
+ price_per_sec: 0.15,
66
+ },
67
+ "kwaivgi/kling-v1.6-pro": {
68
+ durations: [5, 10],
69
+ start_image: "start_image",
70
+ price_per_sec: 0.095,
71
+ },
72
+ "kwaivgi/kling-v2.1": {
73
+ durations: [5, 10],
74
+ start_image: "start_image",
75
+ price_per_sec: 0.05,
76
+ },
77
+ "kwaivgi/kling-v2.1-master": {
78
+ durations: [5, 10],
79
+ start_image: "start_image",
80
+ price_per_sec: 0.28,
81
+ },
82
+ "google/veo-2": {
83
+ durations: [5, 6, 7, 8],
84
+ start_image: "image",
85
+ price_per_sec: 0.5,
86
+ },
87
+ "google/veo-3": {
88
+ durations: [8],
89
+ start_image: undefined,
90
+ price_per_sec: 0.75,
91
+ },
92
+ "google/veo-3-fast": {
93
+ durations: [8],
94
+ start_image: undefined,
95
+ price_per_sec: 0.4,
96
+ },
97
+ "minimax/video-01": {
98
+ durations: [6],
99
+ start_image: "first_frame_image",
100
+ price_per_sec: 0.5,
101
+ },
102
+ "minimax/hailuo-02": {
103
+ durations: [6], // NOTE: 10 for only 720p
104
+ start_image: "first_frame_image",
105
+ price_per_sec: 0.08,
106
+ },
107
+ "pixverse/pixverse-v4.5": {
108
+ durations: [5, 8],
109
+ start_image: "image",
110
+ last_image: "last_frame_image",
111
+ price_per_sec: 0.12,
112
+ },
113
+ },
57
114
  },
58
115
  google: {
59
116
  agentName: "movieGoogleAgent",
117
+ defaultModel: "veo-2.0-generate-001",
60
118
  models: ["veo-2.0-generate-001"],
61
119
  },
62
120
  };
121
+ export const provider2SoundEffectAgent = {
122
+ replicate: {
123
+ agentName: "soundEffectReplicateAgent",
124
+ defaultModel: "zsxkib/mmaudio",
125
+ models: ["zsxkib/mmaudio"],
126
+ modelParams: {
127
+ "zsxkib/mmaudio": {
128
+ identifier: "zsxkib/mmaudio:62871fb59889b2d7c13777f08deb3b36bdff88f7e1d53a50ad7694548a41b484",
129
+ },
130
+ },
131
+ },
132
+ };
63
133
  // : Record<LLM, { agent: string; defaultModel: string; max_tokens: number }>
64
134
  export const provider2LLMAgent = {
65
135
  openai: {
@@ -83,5 +153,13 @@ export const provider2LLMAgent = {
83
153
  max_tokens: 4096,
84
154
  },
85
155
  };
156
+ export const defaultProviders = {
157
+ tts: "openai",
158
+ text2image: "openai",
159
+ text2movie: "replicate",
160
+ text2Html: "openai",
161
+ llm: "openai",
162
+ soundEffect: "replicate",
163
+ };
86
164
  export const llm = Object.keys(provider2LLMAgent);
87
165
  export const htmlLLMProvider = ["openai", "anthropic"];
@@ -1,8 +1,6 @@
1
1
  import type { ConfigDataDictionary, DefaultConfigData } from "graphai";
2
2
  import { MulmoBeat, MulmoStudioMultiLingualData } from "../types/index.js";
3
- import { llm } from "./provider2agent.js";
4
3
  import type { LLM } from "./provider2agent.js";
5
- export { LLM, llm };
6
4
  export declare const llmPair: (_llm?: LLM, _model?: string) => {
7
5
  agent: "openAIAgent" | "anthropicAgent" | "geminiAgent" | "groqAgent";
8
6
  model: string;
@@ -22,3 +20,4 @@ type CleanableObject = {
22
20
  [key: string]: CleanableValue;
23
21
  };
24
22
  export declare const deepClean: <T extends CleanableValue>(input: T) => T | undefined;
23
+ export {};
@@ -1,6 +1,5 @@
1
1
  import * as crypto from "crypto";
2
- import { provider2LLMAgent, llm } from "./provider2agent.js";
3
- export { llm };
2
+ import { provider2LLMAgent } from "./provider2agent.js";
4
3
  export const llmPair = (_llm, _model) => {
5
4
  const llmKey = _llm ?? "openai";
6
5
  const agent = provider2LLMAgent[llmKey]?.agentName ?? provider2LLMAgent.openai.agentName;
@@ -74,6 +73,9 @@ export const settings2GraphAIConfig = (settings, env) => {
74
73
  ttsElevenlabsAgent: {
75
74
  apiKey: getKey("TTS", "ELEVENLABS_API_KEY"),
76
75
  },
76
+ soundEffectReplicateAgent: {
77
+ apiKey: getKey("SOUND_EFFECT", "REPLICATE_API_TOKEN"),
78
+ },
77
79
  // TODO
78
80
  // browserlessAgent
79
81
  // ttsGoogleAgent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast",
3
- "version": "0.1.6",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.node.js",
@@ -67,7 +67,7 @@
67
67
  "@graphai/input_agents": "^1.0.1",
68
68
  "@graphai/openai_agent": "^2.0.3",
69
69
  "@graphai/stream_agent_filter": "^2.0.2",
70
- "@graphai/vanilla": "^2.0.5",
70
+ "@graphai/vanilla": "^2.0.6",
71
71
  "@graphai/vanilla_node_agents": "^2.0.1",
72
72
  "@modelcontextprotocol/sdk": "^1.15.1",
73
73
  "@tavily/core": "^0.5.9",
@@ -76,11 +76,11 @@
76
76
  "dotenv": "^17.2.0",
77
77
  "fluent-ffmpeg": "^2.1.3",
78
78
  "google-auth-library": "^10.1.0",
79
- "graphai": "^2.0.12",
79
+ "graphai": "^2.0.13",
80
80
  "inquirer": "^12.7.0",
81
- "marked": "^16.0.0",
81
+ "marked": "^16.1.1",
82
82
  "ora": "^8.2.0",
83
- "puppeteer": "^24.12.1",
83
+ "puppeteer": "^24.14.0",
84
84
  "replicate": "^1.0.1",
85
85
  "yaml": "^2.8.0",
86
86
  "yargs": "^18.0.0",
@@ -94,8 +94,8 @@
94
94
  "@types/fluent-ffmpeg": "^2.1.26",
95
95
  "@types/yargs": "^17.0.33",
96
96
  "eslint": "^9.31.0",
97
- "eslint-config-prettier": "^10.1.5",
98
- "eslint-plugin-prettier": "^5.5.1",
97
+ "eslint-config-prettier": "^10.1.8",
98
+ "eslint-plugin-prettier": "^5.5.3",
99
99
  "eslint-plugin-sonarjs": "^3.0.4",
100
100
  "prettier": "^3.6.2",
101
101
  "ts-node": "^10.9.2",
@@ -1,119 +0,0 @@
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
- }