@mulmocast/slide 0.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 (47) hide show
  1. package/README.md +458 -0
  2. package/lib/actions/bundle.d.ts +3 -0
  3. package/lib/actions/bundle.d.ts.map +1 -0
  4. package/lib/actions/bundle.js +60 -0
  5. package/lib/actions/bundle.js.map +1 -0
  6. package/lib/actions/common.d.ts +21 -0
  7. package/lib/actions/common.d.ts.map +1 -0
  8. package/lib/actions/common.js +159 -0
  9. package/lib/actions/common.js.map +1 -0
  10. package/lib/actions/movie.d.ts +3 -0
  11. package/lib/actions/movie.d.ts.map +1 -0
  12. package/lib/actions/movie.js +58 -0
  13. package/lib/actions/movie.js.map +1 -0
  14. package/lib/actions/upload.d.ts +6 -0
  15. package/lib/actions/upload.d.ts.map +1 -0
  16. package/lib/actions/upload.js +172 -0
  17. package/lib/actions/upload.js.map +1 -0
  18. package/lib/cli.d.ts +3 -0
  19. package/lib/cli.d.ts.map +1 -0
  20. package/lib/cli.js +301 -0
  21. package/lib/cli.js.map +1 -0
  22. package/lib/convert/marp.d.ts +22 -0
  23. package/lib/convert/marp.d.ts.map +1 -0
  24. package/lib/convert/marp.js +375 -0
  25. package/lib/convert/marp.js.map +1 -0
  26. package/lib/convert/pdf.d.ts +14 -0
  27. package/lib/convert/pdf.d.ts.map +1 -0
  28. package/lib/convert/pdf.js +130 -0
  29. package/lib/convert/pdf.js.map +1 -0
  30. package/lib/convert/pptx.d.ts +13 -0
  31. package/lib/convert/pptx.d.ts.map +1 -0
  32. package/lib/convert/pptx.js +138 -0
  33. package/lib/convert/pptx.js.map +1 -0
  34. package/lib/utils/lang.d.ts +16 -0
  35. package/lib/utils/lang.d.ts.map +1 -0
  36. package/lib/utils/lang.js +37 -0
  37. package/lib/utils/lang.js.map +1 -0
  38. package/lib/utils/llm.d.ts +21 -0
  39. package/lib/utils/llm.d.ts.map +1 -0
  40. package/lib/utils/llm.js +200 -0
  41. package/lib/utils/llm.js.map +1 -0
  42. package/lib/utils/pdf.d.ts +37 -0
  43. package/lib/utils/pdf.d.ts.map +1 -0
  44. package/lib/utils/pdf.js +142 -0
  45. package/lib/utils/pdf.js.map +1 -0
  46. package/package.json +67 -0
  47. package/tools/keynote/extract.scpt +195 -0
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.convertPptx = convertPptx;
40
+ const ppt_png_1 = __importDefault(require("ppt-png"));
41
+ const node_pptx_parser_1 = __importDefault(require("node-pptx-parser"));
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ const yargs_1 = __importDefault(require("yargs"));
45
+ const helpers_1 = require("yargs/helpers");
46
+ const lang_1 = require("../utils/lang");
47
+ const pdf_1 = require("../utils/pdf");
48
+ async function convertPptx(options) {
49
+ const { inputPath, lang, generateText = false } = options;
50
+ const resolvedLang = (0, lang_1.resolveLang)(lang);
51
+ const pptxFile = path.resolve(inputPath);
52
+ if (!fs.existsSync(pptxFile)) {
53
+ throw new Error(`File not found: ${pptxFile}`);
54
+ }
55
+ const basename = path.basename(pptxFile, ".pptx");
56
+ const outputDir = options.outputDir || path.join("scripts", basename);
57
+ const imagesDir = path.join(outputDir, "images");
58
+ // Create output directories
59
+ if (!fs.existsSync(outputDir)) {
60
+ fs.mkdirSync(outputDir, { recursive: true });
61
+ }
62
+ console.log(`Converting ${pptxFile} to ${outputDir}/`);
63
+ // Convert PPTX to PDF (using ppt-png for LibreOffice conversion)
64
+ const converter = ppt_png_1.default.create({
65
+ files: [pptxFile],
66
+ output: outputDir + "/",
67
+ density: 96,
68
+ });
69
+ await converter.convert();
70
+ // Convert PDF to PNG images using shared utility
71
+ const pdfPath = path.join(outputDir, `${basename}.pdf`);
72
+ if (!fs.existsSync(pdfPath)) {
73
+ throw new Error(`PDF conversion failed: ${pdfPath} not found`);
74
+ }
75
+ console.log("Re-converting PDF with antialias...");
76
+ const { slideCount } = (0, pdf_1.convertPdfToImages)({
77
+ pdfPath,
78
+ imagesDir,
79
+ basename,
80
+ });
81
+ // Extract text from PPTX
82
+ const parser = new node_pptx_parser_1.default(pptxFile);
83
+ const textContent = await parser.extractText();
84
+ const slideTexts = textContent.map((slide) => slide.text.join("\n"));
85
+ // Build MulmoScript using shared utility
86
+ // Pass slideTexts as both default text and extracted text for LLM
87
+ const { mulmoScript } = await (0, pdf_1.buildMulmoScriptFromImages)({
88
+ slideCount,
89
+ imagesDir,
90
+ basename,
91
+ lang: resolvedLang,
92
+ slideTexts,
93
+ extractedTexts: slideTexts,
94
+ generateText,
95
+ title: basename,
96
+ });
97
+ // Write MulmoScript to JSON file
98
+ const jsonPath = path.join(outputDir, "mulmo_script.json");
99
+ (0, pdf_1.writeMulmoScript)(mulmoScript, jsonPath);
100
+ return {
101
+ mulmoScriptPath: jsonPath,
102
+ slideCount,
103
+ };
104
+ }
105
+ async function main() {
106
+ const argv = await (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
107
+ .usage("Usage: $0 <pptx-file> [options]")
108
+ .command("$0 <file>", "Convert PPTX to MulmoScript", (yargs) => {
109
+ return yargs.positional("file", {
110
+ describe: "PPTX file to convert",
111
+ type: "string",
112
+ demandOption: true,
113
+ });
114
+ })
115
+ .options({
116
+ ...lang_1.langOption,
117
+ g: {
118
+ alias: "generate-text",
119
+ type: "boolean",
120
+ description: "Generate narration text using LLM",
121
+ default: false,
122
+ },
123
+ })
124
+ .help()
125
+ .parse();
126
+ await convertPptx({
127
+ inputPath: argv.file,
128
+ lang: argv.l,
129
+ generateText: argv.g,
130
+ });
131
+ }
132
+ if (require.main === module) {
133
+ main().catch((error) => {
134
+ console.error("Error:", error.message);
135
+ process.exit(1);
136
+ });
137
+ }
138
+ //# sourceMappingURL=pptx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pptx.js","sourceRoot":"","sources":["../../src/convert/pptx.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export declare const SUPPORTED_LANGS: readonly ["en", "ja", "fr", "de"];
2
+ export type SupportedLang = (typeof SUPPORTED_LANGS)[number];
3
+ export declare const DEFAULT_LANG: SupportedLang;
4
+ export declare function isValidLang(lang: string): lang is SupportedLang;
5
+ export declare function getLangFromEnv(): SupportedLang | undefined;
6
+ export declare function resolveLang(cliLang?: string): SupportedLang;
7
+ export declare const langOption: {
8
+ l: {
9
+ alias: string;
10
+ type: "string";
11
+ choices: string[];
12
+ description: string;
13
+ default: undefined;
14
+ };
15
+ };
16
+ //# sourceMappingURL=lang.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang.d.ts","sourceRoot":"","sources":["../../src/utils/lang.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,eAAe,mCAAoC,CAAC;AACjE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,eAAO,MAAM,YAAY,EAAE,aAAoB,CAAC;AAEhD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,aAAa,CAE/D;AAED,wBAAgB,cAAc,IAAI,aAAa,GAAG,SAAS,CAM1D;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAM3D;AAGD,eAAO,MAAM,UAAU;;;;iBAIoB,MAAM,EAAE;;;;CAIlD,CAAC"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.langOption = exports.DEFAULT_LANG = exports.SUPPORTED_LANGS = void 0;
4
+ exports.isValidLang = isValidLang;
5
+ exports.getLangFromEnv = getLangFromEnv;
6
+ exports.resolveLang = resolveLang;
7
+ // Supported languages
8
+ exports.SUPPORTED_LANGS = ["en", "ja", "fr", "de"];
9
+ exports.DEFAULT_LANG = "en";
10
+ function isValidLang(lang) {
11
+ return exports.SUPPORTED_LANGS.includes(lang);
12
+ }
13
+ function getLangFromEnv() {
14
+ const envLang = process.env.MULMO_LANG;
15
+ if (envLang && isValidLang(envLang)) {
16
+ return envLang;
17
+ }
18
+ return undefined;
19
+ }
20
+ function resolveLang(cliLang) {
21
+ // Priority: CLI option > environment variable > default
22
+ if (cliLang && isValidLang(cliLang)) {
23
+ return cliLang;
24
+ }
25
+ return getLangFromEnv() ?? exports.DEFAULT_LANG;
26
+ }
27
+ // Yargs option configuration for lang
28
+ exports.langOption = {
29
+ l: {
30
+ alias: "lang",
31
+ type: "string",
32
+ choices: exports.SUPPORTED_LANGS,
33
+ description: "Language for the MulmoScript",
34
+ default: undefined,
35
+ },
36
+ };
37
+ //# sourceMappingURL=lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang.js","sourceRoot":"","sources":["../../src/utils/lang.ts"],"names":[],"mappings":";;;AAMA,kCAEC;AAED,wCAMC;AAED,kCAMC;AAxBD,sBAAsB;AACT,QAAA,eAAe,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAGpD,QAAA,YAAY,GAAkB,IAAI,CAAC;AAEhD,SAAgB,WAAW,CAAC,IAAY;IACtC,OAAO,uBAAe,CAAC,QAAQ,CAAC,IAAqB,CAAC,CAAC;AACzD,CAAC;AAED,SAAgB,cAAc;IAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IACvC,IAAI,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,WAAW,CAAC,OAAgB;IAC1C,wDAAwD;IACxD,IAAI,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,cAAc,EAAE,IAAI,oBAAY,CAAC;AAC1C,CAAC;AAED,sCAAsC;AACzB,QAAA,UAAU,GAAG;IACxB,CAAC,EAAE;QACD,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,QAAiB;QACvB,OAAO,EAAE,uBAAsC;QAC/C,WAAW,EAAE,8BAA8B;QAC3C,OAAO,EAAE,SAAS;KACnB;CACF,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { SupportedLang } from "./lang";
2
+ interface SlideContent {
3
+ index: number;
4
+ markdown?: string[];
5
+ imagePath?: string;
6
+ existingText?: string;
7
+ extractedText?: string;
8
+ }
9
+ interface GenerateTextOptions {
10
+ slides: SlideContent[];
11
+ lang: SupportedLang;
12
+ title?: string;
13
+ }
14
+ interface GeneratedText {
15
+ index: number;
16
+ text: string;
17
+ }
18
+ export declare function generateTextFromMarkdown(options: GenerateTextOptions): Promise<GeneratedText[]>;
19
+ export declare function generateTextFromImages(options: GenerateTextOptions): Promise<GeneratedText[]>;
20
+ export {};
21
+ //# sourceMappingURL=llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/utils/llm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAW5C,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,mBAAmB;IAC3B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAuBD,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,aAAa,EAAE,CAAC,CAyD1B;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,aAAa,EAAE,CAAC,CAuF1B"}
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.generateTextFromMarkdown = generateTextFromMarkdown;
40
+ exports.generateTextFromImages = generateTextFromImages;
41
+ const openai_1 = __importDefault(require("openai"));
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ let openaiClient = null;
45
+ function getOpenAIClient() {
46
+ if (!openaiClient) {
47
+ openaiClient = new openai_1.default();
48
+ }
49
+ return openaiClient;
50
+ }
51
+ function getLanguageName(lang) {
52
+ const langNames = {
53
+ en: "English",
54
+ ja: "Japanese",
55
+ fr: "French",
56
+ de: "German",
57
+ };
58
+ return langNames[lang];
59
+ }
60
+ function imageToBase64(imagePath) {
61
+ const absolutePath = path.resolve(imagePath);
62
+ const imageBuffer = fs.readFileSync(absolutePath);
63
+ return imageBuffer.toString("base64");
64
+ }
65
+ function getImageMediaType(imagePath) {
66
+ const ext = path.extname(imagePath).toLowerCase();
67
+ return ext === ".jpg" || ext === ".jpeg" ? "image/jpeg" : "image/png";
68
+ }
69
+ async function generateTextFromMarkdown(options) {
70
+ const { slides, lang, title } = options;
71
+ const languageName = getLanguageName(lang);
72
+ const slideContents = slides
73
+ .map((s, i) => {
74
+ const content = s.markdown?.join("\n") || "(no content)";
75
+ return `--- Slide ${i + 1} ---\n${content}`;
76
+ })
77
+ .join("\n\n");
78
+ const targetIndices = slides.map((s) => s.index);
79
+ const prompt = `You are a professional presenter delivering a live presentation to an audience.
80
+
81
+ Title: ${title || "Untitled Presentation"}
82
+
83
+ Here are all the slides in the presentation:
84
+
85
+ ${slideContents}
86
+
87
+ Generate narration text for slides: ${targetIndices.map((i) => i + 1).join(", ")}
88
+
89
+ Critical style requirements:
90
+ - Write in ${languageName}
91
+ - Speak directly to the audience as if presenting live - NEVER use meta-references like "this slide shows", "here we see", "このスライドでは", "ここでは", "この図は"
92
+ - Flow naturally from one idea to the next, as a skilled presenter would
93
+ - Deliver substantive, insightful explanations - not surface-level descriptions
94
+ - Explain concepts and technical terms accurately and clearly
95
+ - Connect ideas to help the audience understand the bigger picture
96
+ - Use a confident, engaging speaking style suitable for text-to-speech
97
+ - Don't just read bullet points - explain what they mean and why they matter
98
+
99
+ Bad example: "このスライドでは、3つのポイントを説明します。"
100
+ Good example: "効果的な実装には3つの重要な要素があります。まず..."
101
+
102
+ Respond in JSON format:
103
+ {
104
+ "slides": [
105
+ {"index": <0-based index>, "text": "<narration text>"},
106
+ ...
107
+ ]
108
+ }`;
109
+ const response = await getOpenAIClient().chat.completions.create({
110
+ model: "gpt-4o",
111
+ messages: [{ role: "user", content: prompt }],
112
+ response_format: { type: "json_object" },
113
+ });
114
+ const content = response.choices[0]?.message?.content;
115
+ if (!content) {
116
+ throw new Error("No response from OpenAI");
117
+ }
118
+ const result = JSON.parse(content);
119
+ return result.slides;
120
+ }
121
+ async function generateTextFromImages(options) {
122
+ const { slides, lang, title } = options;
123
+ const languageName = getLanguageName(lang);
124
+ const targetIndices = slides.map((s) => s.index);
125
+ // Check if any slides have extracted text
126
+ const hasExtractedText = slides.some((s) => s.extractedText && s.extractedText.trim().length > 0);
127
+ const extractedTextSection = hasExtractedText
128
+ ? `
129
+ Additionally, here is the extracted text from each slide for reference. Use this to understand technical details, proper nouns, and specific information that may not be clearly visible in the images:
130
+
131
+ ${slides
132
+ .map((s, i) => {
133
+ const text = s.extractedText?.trim() || "(no text extracted)";
134
+ return `--- Slide ${i + 1} Text ---\n${text}`;
135
+ })
136
+ .join("\n\n")}
137
+ `
138
+ : "";
139
+ const prompt = `You are a professional presenter delivering a live presentation to an audience.
140
+
141
+ Title: ${title || "Untitled Presentation"}
142
+
143
+ I'm showing you all slides in the presentation as images.${extractedTextSection}
144
+
145
+ Generate narration text for slides: ${targetIndices.map((i) => i + 1).join(", ")}
146
+
147
+ Critical style requirements:
148
+ - Write in ${languageName}
149
+ - Speak directly to the audience as if presenting live - NEVER use meta-references like "this slide shows", "here we see", "このスライドでは", "ここでは", "この図は"
150
+ - Flow naturally from one idea to the next, as a skilled presenter would
151
+ - Deliver substantive, insightful explanations - not surface-level descriptions
152
+ - Explain concepts, data, and technical terms accurately and clearly
153
+ - Connect ideas to help the audience understand the bigger picture
154
+ - Use a confident, engaging speaking style suitable for text-to-speech
155
+ - When discussing charts, data, or diagrams, explain what the information means and why it matters - don't just describe what's visible
156
+ - Use the extracted text to ensure accuracy of technical terms, names, numbers, and specific details
157
+
158
+ Bad example: "このスライドでは、AIロボティクスの市場動向を示しています。"
159
+ Good example: "AIロボティクス市場は急速に拡大しており、2030年には60兆円規模に達すると予測されています。"
160
+
161
+ Respond in JSON format:
162
+ {
163
+ "slides": [
164
+ {"index": <0-based index>, "text": "<narration text>"},
165
+ ...
166
+ ]
167
+ }`;
168
+ const slideImageContents = slides
169
+ .filter((slide) => slide.imagePath && fs.existsSync(slide.imagePath))
170
+ .flatMap((slide, i) => {
171
+ const base64 = imageToBase64(slide.imagePath);
172
+ const mediaType = getImageMediaType(slide.imagePath);
173
+ return [
174
+ { type: "text", text: `--- Slide ${i + 1} ---` },
175
+ {
176
+ type: "image_url",
177
+ image_url: {
178
+ url: `data:${mediaType};base64,${base64}`,
179
+ detail: "high",
180
+ },
181
+ },
182
+ ];
183
+ });
184
+ const imageContents = [
185
+ { type: "text", text: prompt },
186
+ ...slideImageContents,
187
+ ];
188
+ const response = await getOpenAIClient().chat.completions.create({
189
+ model: "gpt-4o",
190
+ messages: [{ role: "user", content: imageContents }],
191
+ response_format: { type: "json_object" },
192
+ });
193
+ const content = response.choices[0]?.message?.content;
194
+ if (!content) {
195
+ throw new Error("No response from OpenAI");
196
+ }
197
+ const result = JSON.parse(content);
198
+ return result.slides;
199
+ }
200
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/utils/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { mulmoScriptSchema, type MulmoBeat } from "mulmocast";
2
+ import type { z } from "zod";
3
+ import type { SupportedLang } from "./lang";
4
+ type MulmoScriptOutput = z.output<typeof mulmoScriptSchema>;
5
+ export interface ExtractedPageText {
6
+ pageNumber: number;
7
+ text: string;
8
+ }
9
+ export declare function extractTextFromPdf(pdfPath: string): Promise<ExtractedPageText[]>;
10
+ export interface PdfToImagesOptions {
11
+ pdfPath: string;
12
+ imagesDir: string;
13
+ basename: string;
14
+ }
15
+ export interface PdfToImagesResult {
16
+ imageFiles: string[];
17
+ slideCount: number;
18
+ }
19
+ export declare function convertPdfToImages(options: PdfToImagesOptions): PdfToImagesResult;
20
+ export interface BuildMulmoScriptOptions {
21
+ slideCount: number;
22
+ imagesDir: string;
23
+ basename: string;
24
+ lang: SupportedLang;
25
+ slideTexts?: string[];
26
+ extractedTexts?: string[];
27
+ generateText?: boolean;
28
+ title?: string;
29
+ }
30
+ export interface BuildMulmoScriptResult {
31
+ mulmoScript: MulmoScriptOutput;
32
+ beats: MulmoBeat[];
33
+ }
34
+ export declare function buildMulmoScriptFromImages(options: BuildMulmoScriptOptions): Promise<BuildMulmoScriptResult>;
35
+ export declare function writeMulmoScript(mulmoScript: MulmoScriptOutput, outputPath: string): void;
36
+ export {};
37
+ //# sourceMappingURL=pdf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../../src/utils/pdf.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAI5C,KAAK,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAetF;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CAkCjF;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,iBAAiB,CAAC;IAC/B,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CAqEjC;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAIzF"}
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.extractTextFromPdf = extractTextFromPdf;
37
+ exports.convertPdfToImages = convertPdfToImages;
38
+ exports.buildMulmoScriptFromImages = buildMulmoScriptFromImages;
39
+ exports.writeMulmoScript = writeMulmoScript;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const child_process_1 = require("child_process");
43
+ const mulmocast_1 = require("mulmocast");
44
+ const llm_1 = require("./llm");
45
+ async function extractTextFromPdf(pdfPath) {
46
+ const { PDFParse } = await Promise.resolve().then(() => __importStar(require("pdf-parse")));
47
+ const dataBuffer = fs.readFileSync(pdfPath);
48
+ const uint8Array = new Uint8Array(dataBuffer);
49
+ const parser = new PDFParse(uint8Array);
50
+ await parser.load();
51
+ const textResult = await parser.getText();
52
+ // textResult.pages is an array of { text: string, num: number }
53
+ return textResult.pages.map((page) => ({
54
+ pageNumber: page.num - 1, // Convert to 0-based index
55
+ text: page.text.trim(),
56
+ }));
57
+ }
58
+ function convertPdfToImages(options) {
59
+ const { pdfPath, imagesDir, basename } = options;
60
+ if (!fs.existsSync(pdfPath)) {
61
+ throw new Error(`PDF not found: ${pdfPath}`);
62
+ }
63
+ // Create images directory if it doesn't exist
64
+ if (!fs.existsSync(imagesDir)) {
65
+ fs.mkdirSync(imagesDir, { recursive: true });
66
+ }
67
+ // Delete old PNGs from images directory
68
+ const oldPngs = fs.readdirSync(imagesDir).filter((f) => f.endsWith(".png"));
69
+ oldPngs.forEach((f) => fs.unlinkSync(path.join(imagesDir, f)));
70
+ // Convert with ImageMagick (better antialias) to images/ directory
71
+ // Use 'magick' on macOS/Windows (ImageMagick 7), 'convert' on Linux (ImageMagick 6)
72
+ const magickCmd = process.platform === "linux" ? "convert" : "magick";
73
+ (0, child_process_1.execSync)(`${magickCmd} -density 300 -antialias "${pdfPath}" -background white -alpha remove -quality 95 "${imagesDir}/${basename}-%d.png"`, { stdio: "inherit" });
74
+ // Count generated images
75
+ const imageFiles = fs
76
+ .readdirSync(imagesDir)
77
+ .filter((f) => f.startsWith(`${basename}-`) && f.endsWith(".png"))
78
+ .sort();
79
+ return {
80
+ imageFiles,
81
+ slideCount: imageFiles.length,
82
+ };
83
+ }
84
+ async function buildMulmoScriptFromImages(options) {
85
+ const { slideCount, imagesDir, basename, lang, slideTexts = [], extractedTexts = [], generateText = false, title, } = options;
86
+ const beats = Array.from({ length: slideCount }, (_, index) => {
87
+ const imagePath = `./images/${basename}-${index}.png`;
88
+ const text = slideTexts[index] || "";
89
+ return {
90
+ text,
91
+ image: {
92
+ type: "image",
93
+ source: {
94
+ kind: "path",
95
+ path: imagePath,
96
+ },
97
+ },
98
+ };
99
+ });
100
+ // Generate text using LLM if requested
101
+ if (generateText) {
102
+ console.log("Generating narration text with LLM...");
103
+ const slides = beats.map((_, index) => ({
104
+ index,
105
+ imagePath: path.join(imagesDir, `${basename}-${index}.png`),
106
+ existingText: "",
107
+ extractedText: extractedTexts[index] || "",
108
+ }));
109
+ const generatedTexts = await (0, llm_1.generateTextFromImages)({
110
+ slides,
111
+ lang,
112
+ title: title || basename,
113
+ });
114
+ generatedTexts.forEach((generated) => {
115
+ if (beats[generated.index]) {
116
+ beats[generated.index].text = generated.text;
117
+ }
118
+ });
119
+ console.log(`Generated text for ${generatedTexts.length} slides`);
120
+ }
121
+ const mulmoScript = {
122
+ $mulmocast: {
123
+ version: "1.1",
124
+ },
125
+ lang,
126
+ beats,
127
+ };
128
+ // Validate mulmoScript
129
+ const result = mulmocast_1.mulmoScriptSchema.safeParse(mulmoScript);
130
+ if (!result.success) {
131
+ console.error("MulmoScript validation failed:");
132
+ console.error(result.error.format());
133
+ throw new Error("Invalid MulmoScript generated");
134
+ }
135
+ return { mulmoScript: result.data, beats };
136
+ }
137
+ function writeMulmoScript(mulmoScript, outputPath) {
138
+ fs.writeFileSync(outputPath, JSON.stringify(mulmoScript, null, 2));
139
+ console.log(`Generated: ${outputPath}`);
140
+ console.log(`Total slides: ${mulmoScript.beats.length}`);
141
+ }
142
+ //# sourceMappingURL=pdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf.js","sourceRoot":"","sources":["../../src/utils/pdf.ts"],"names":[],"mappings":"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"}