@mulmocast/slide 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/extend/SKILL.md +6 -6
- package/.claude/skills/extend/references/extended-script-schema.md +5 -5
- package/.claude/skills/md-to-mulmo/SKILL.md +8 -8
- package/.claude/skills/narrate/SKILL.md +8 -8
- package/.claude/skills/narrate/references/extended-script-schema.md +5 -5
- package/README.md +17 -17
- package/lib/actions/extend-scaffold.d.ts +2 -2
- package/lib/actions/extend-scaffold.d.ts.map +1 -1
- package/lib/actions/extend-scaffold.js +3 -3
- package/lib/actions/extend-scaffold.js.map +1 -1
- package/lib/actions/extend-validate.js +3 -3
- package/lib/actions/extend-validate.js.map +1 -1
- package/lib/actions/md-to-extended.d.ts +7 -7
- package/lib/actions/md-to-extended.d.ts.map +1 -1
- package/lib/actions/md-to-extended.js +20 -20
- package/lib/actions/md-to-extended.js.map +1 -1
- package/lib/actions/narrate.d.ts.map +1 -1
- package/lib/actions/narrate.js +6 -6
- package/lib/actions/narrate.js.map +1 -1
- package/lib/actions/preview.js +1 -1
- package/lib/actions/preview.js.map +1 -1
- package/lib/cli.js +7 -7
- package/lib/cli.js.map +1 -1
- package/lib/convert/marp.js +1 -1
- package/lib/convert/marp.js.map +1 -1
- package/lib/convert/movie.d.ts.map +1 -1
- package/lib/convert/movie.js +2 -2
- package/lib/convert/movie.js.map +1 -1
- package/package.json +7 -6
- package/lib/convert/pdfvision.d.ts +0 -14
- package/lib/convert/pdfvision.d.ts.map +0 -1
- package/lib/convert/pdfvision.js +0 -247
- package/lib/convert/pdfvision.js.map +0 -1
- package/lib/utils/document-analysis.d.ts +0 -43
- package/lib/utils/document-analysis.d.ts.map +0 -1
- package/lib/utils/document-analysis.js +0 -118
- package/lib/utils/document-analysis.js.map +0 -1
- package/lib/utils/narration-generator.d.ts +0 -14
- package/lib/utils/narration-generator.d.ts.map +0 -1
- package/lib/utils/narration-generator.js +0 -68
- package/lib/utils/narration-generator.js.map +0 -1
- package/lib/utils/vision-provider.d.ts +0 -12
- package/lib/utils/vision-provider.d.ts.map +0 -1
- package/lib/utils/vision-provider.js +0 -105
- package/lib/utils/vision-provider.js.map +0 -1
- package/lib/vue/assets/index-D6am8L57.css +0 -1
- package/lib/vue/assets/index-xq-ZNfmX.js +0 -2
- package/lib/vue/index.html +0 -13
package/lib/convert/pdfvision.js
DELETED
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
import { execSync } from "child_process";
|
|
4
|
-
import { mulmoScriptSchema } from "mulmocast";
|
|
5
|
-
import { resolveLang } from "../utils/lang.js";
|
|
6
|
-
import { convertPdfToImages, extractTextFromPdf, writeMulmoScript } from "../utils/pdf.js";
|
|
7
|
-
import { checkDependencies } from "../utils/dependencies.js";
|
|
8
|
-
import { resolveVisionProvider, callVisionAPI, callTextLLM, } from "../utils/vision-provider.js";
|
|
9
|
-
import { buildDocumentAnalysisPrompt, parseDocumentAnalysis, } from "../utils/document-analysis.js";
|
|
10
|
-
import { buildNarrationPrompt, parseNarrationResponse } from "../utils/narration-generator.js";
|
|
11
|
-
const CROP_PADDING_PERCENT = 5;
|
|
12
|
-
const CROP_DPI = 600;
|
|
13
|
-
const TRIM_BORDER_PX = 20;
|
|
14
|
-
const getMagickCmd = () => {
|
|
15
|
-
return process.platform === "linux" ? "convert" : "magick";
|
|
16
|
-
};
|
|
17
|
-
const buildPageImages = (imagesDir, basename, pageCount) => {
|
|
18
|
-
return Array.from({ length: pageCount }, (_, i) => ({
|
|
19
|
-
path: path.join(imagesDir, `${basename}-${i}.png`),
|
|
20
|
-
})).filter((img) => fs.existsSync(img.path));
|
|
21
|
-
};
|
|
22
|
-
const sanitizeLabel = (label) => {
|
|
23
|
-
return label.replace(/[^a-zA-Z0-9_-]/g, "_").toLowerCase();
|
|
24
|
-
};
|
|
25
|
-
const getImageDimensions = (imagePath) => {
|
|
26
|
-
try {
|
|
27
|
-
const magick = getMagickCmd();
|
|
28
|
-
const identifyCmd = magick === "magick" ? "magick identify" : "identify";
|
|
29
|
-
const output = execSync(`${identifyCmd} -format "%w %h" "${imagePath}"`, { encoding: "utf-8" });
|
|
30
|
-
const [w, h] = output.trim().split(" ").map(Number);
|
|
31
|
-
return { width: w, height: h };
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
const convertPageHighRes = (pdfPath, page, outputPath) => {
|
|
38
|
-
try {
|
|
39
|
-
const magick = getMagickCmd();
|
|
40
|
-
const cmd = `${magick} -density ${CROP_DPI} -antialias "${pdfPath}[${page}]" -background white -alpha remove -quality 95 "${outputPath}"`;
|
|
41
|
-
execSync(cmd, { stdio: "pipe" });
|
|
42
|
-
return fs.existsSync(outputPath);
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
const addPadding = (bbox, padding) => {
|
|
49
|
-
const x = Math.max(0, bbox.x - padding);
|
|
50
|
-
const y = Math.max(0, bbox.y - padding);
|
|
51
|
-
const width = Math.min(100 - x, bbox.width + padding * 2);
|
|
52
|
-
const height = Math.min(100 - y, bbox.height + padding * 2);
|
|
53
|
-
return { x, y, width, height };
|
|
54
|
-
};
|
|
55
|
-
const cropFigure = (pageImagePath, outputPath, bbox) => {
|
|
56
|
-
try {
|
|
57
|
-
const dims = getImageDimensions(pageImagePath);
|
|
58
|
-
if (!dims)
|
|
59
|
-
return false;
|
|
60
|
-
const padded = addPadding(bbox, CROP_PADDING_PERCENT);
|
|
61
|
-
const cropX = Math.round((padded.x / 100) * dims.width);
|
|
62
|
-
const cropY = Math.round((padded.y / 100) * dims.height);
|
|
63
|
-
const cropW = Math.round((padded.width / 100) * dims.width);
|
|
64
|
-
const cropH = Math.round((padded.height / 100) * dims.height);
|
|
65
|
-
const magick = getMagickCmd();
|
|
66
|
-
const cropCmd = [
|
|
67
|
-
`${magick} "${pageImagePath}"`,
|
|
68
|
-
`-crop ${cropW}x${cropH}+${cropX}+${cropY} +repage`,
|
|
69
|
-
`-trim +repage`,
|
|
70
|
-
`-bordercolor white -border ${TRIM_BORDER_PX}`,
|
|
71
|
-
`"${outputPath}"`,
|
|
72
|
-
].join(" ");
|
|
73
|
-
execSync(cropCmd, { stdio: "pipe" });
|
|
74
|
-
return fs.existsSync(outputPath);
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
const cropFigures = (analysis, imagesDir, basename, pdfPath) => {
|
|
81
|
-
const figureImageMap = new Map();
|
|
82
|
-
// Identify pages that need high-res conversion
|
|
83
|
-
const pagesWithFigures = new Set();
|
|
84
|
-
analysis.figures.forEach((figure) => {
|
|
85
|
-
if (figure.bbox && figure.label) {
|
|
86
|
-
pagesWithFigures.add(figure.page);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
// Convert those pages at high DPI
|
|
90
|
-
const highResDir = path.join(imagesDir, "_highres");
|
|
91
|
-
if (pagesWithFigures.size > 0) {
|
|
92
|
-
if (!fs.existsSync(highResDir)) {
|
|
93
|
-
fs.mkdirSync(highResDir, { recursive: true });
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const highResMap = new Map();
|
|
97
|
-
pagesWithFigures.forEach((page) => {
|
|
98
|
-
const highResPath = path.join(highResDir, `${basename}-${page}-hires.png`);
|
|
99
|
-
if (convertPageHighRes(pdfPath, page, highResPath)) {
|
|
100
|
-
highResMap.set(page, highResPath);
|
|
101
|
-
console.log(` High-res (${CROP_DPI}dpi): page ${page}`);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
// Crop figures from high-res images (fallback to standard images)
|
|
105
|
-
analysis.figures.forEach((figure) => {
|
|
106
|
-
if (!figure.bbox || !figure.label)
|
|
107
|
-
return;
|
|
108
|
-
const sourceImage = highResMap.get(figure.page) ?? path.join(imagesDir, `${basename}-${figure.page}.png`);
|
|
109
|
-
if (!fs.existsSync(sourceImage))
|
|
110
|
-
return;
|
|
111
|
-
const sanitized = sanitizeLabel(figure.label);
|
|
112
|
-
const croppedFilename = `${basename}-fig-${sanitized}.png`;
|
|
113
|
-
const croppedPath = path.join(imagesDir, croppedFilename);
|
|
114
|
-
if (cropFigure(sourceImage, croppedPath, figure.bbox)) {
|
|
115
|
-
figureImageMap.set(figure.label, `./images/${croppedFilename}`);
|
|
116
|
-
console.log(` Cropped: ${figure.label} → ${croppedFilename}`);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
// Clean up high-res temp images
|
|
120
|
-
if (fs.existsSync(highResDir)) {
|
|
121
|
-
fs.readdirSync(highResDir).forEach((f) => fs.unlinkSync(path.join(highResDir, f)));
|
|
122
|
-
fs.rmdirSync(highResDir);
|
|
123
|
-
}
|
|
124
|
-
return figureImageMap;
|
|
125
|
-
};
|
|
126
|
-
const analyzeDocument = async (provider, images, extractedTexts, lang) => {
|
|
127
|
-
console.log(`Analyzing document with ${provider} Vision API...`);
|
|
128
|
-
const prompt = buildDocumentAnalysisPrompt({
|
|
129
|
-
pageCount: images.length,
|
|
130
|
-
extractedTexts,
|
|
131
|
-
lang,
|
|
132
|
-
});
|
|
133
|
-
const response = await callVisionAPI(provider, { prompt, images });
|
|
134
|
-
return parseDocumentAnalysis(response);
|
|
135
|
-
};
|
|
136
|
-
const generateNarrations = async (provider, analysis, extractedTexts, lang) => {
|
|
137
|
-
console.log("Generating narration with text LLM...");
|
|
138
|
-
const prompt = buildNarrationPrompt({
|
|
139
|
-
documentAnalysis: analysis,
|
|
140
|
-
extractedTexts,
|
|
141
|
-
lang,
|
|
142
|
-
});
|
|
143
|
-
const response = await callTextLLM(provider, prompt);
|
|
144
|
-
const entries = parseNarrationResponse(response, analysis.slides.length);
|
|
145
|
-
return entries.map((e) => e.text);
|
|
146
|
-
};
|
|
147
|
-
const buildMulmoScript = (analysis, narrations, basename, lang, figureImageMap) => {
|
|
148
|
-
const beats = analysis.slides.map((slide, i) => {
|
|
149
|
-
const imagePage = slide.imagePage ?? slide.sourcePages[0] ?? 0;
|
|
150
|
-
const pageImagePath = `./images/${basename}-${imagePage}.png`;
|
|
151
|
-
const imagePath = slide.figureRef && figureImageMap.has(slide.figureRef)
|
|
152
|
-
? figureImageMap.get(slide.figureRef)
|
|
153
|
-
: pageImagePath;
|
|
154
|
-
return {
|
|
155
|
-
text: narrations[i] || "",
|
|
156
|
-
image: {
|
|
157
|
-
type: "image",
|
|
158
|
-
source: {
|
|
159
|
-
kind: "path",
|
|
160
|
-
path: imagePath,
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
});
|
|
165
|
-
const mulmoScript = {
|
|
166
|
-
$mulmocast: { version: "1.1" },
|
|
167
|
-
lang,
|
|
168
|
-
beats,
|
|
169
|
-
};
|
|
170
|
-
const result = mulmoScriptSchema.safeParse(mulmoScript);
|
|
171
|
-
if (!result.success) {
|
|
172
|
-
console.error("MulmoScript validation failed:");
|
|
173
|
-
console.error(result.error.format());
|
|
174
|
-
throw new Error("Invalid MulmoScript generated");
|
|
175
|
-
}
|
|
176
|
-
return result.data;
|
|
177
|
-
};
|
|
178
|
-
export const convertPdfVision = async (options) => {
|
|
179
|
-
const { inputPath, provider: providerArg } = options;
|
|
180
|
-
const pdfFile = path.resolve(inputPath);
|
|
181
|
-
if (!fs.existsSync(pdfFile)) {
|
|
182
|
-
throw new Error(`File not found: ${pdfFile}`);
|
|
183
|
-
}
|
|
184
|
-
checkDependencies("pdf");
|
|
185
|
-
const provider = resolveVisionProvider(providerArg);
|
|
186
|
-
console.log(`Using Vision provider: ${provider}`);
|
|
187
|
-
const basename = path.basename(pdfFile, ".pdf");
|
|
188
|
-
const outputDir = path.join("scripts", basename);
|
|
189
|
-
const imagesDir = path.join(outputDir, "images");
|
|
190
|
-
if (!fs.existsSync(outputDir)) {
|
|
191
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
192
|
-
}
|
|
193
|
-
// Step 1: Convert PDF to page images
|
|
194
|
-
console.log("Converting PDF to images...");
|
|
195
|
-
const { slideCount: pageCount } = convertPdfToImages({
|
|
196
|
-
pdfPath: pdfFile,
|
|
197
|
-
imagesDir,
|
|
198
|
-
basename,
|
|
199
|
-
});
|
|
200
|
-
// Step 2: Extract text
|
|
201
|
-
console.log("Extracting text from PDF...");
|
|
202
|
-
const pageTexts = await extractTextFromPdf(pdfFile);
|
|
203
|
-
const extractedTexts = [];
|
|
204
|
-
pageTexts.forEach((page) => {
|
|
205
|
-
extractedTexts[page.pageNumber] = page.text;
|
|
206
|
-
});
|
|
207
|
-
console.log(`Extracted text from ${pageTexts.length} pages`);
|
|
208
|
-
const resolvedLang = resolveLang(options.lang, extractedTexts.filter(Boolean));
|
|
209
|
-
// Save extracted texts
|
|
210
|
-
const hasExtractedText = extractedTexts.some((t) => t && t.length > 0);
|
|
211
|
-
let extractedTextsPath = null;
|
|
212
|
-
if (hasExtractedText) {
|
|
213
|
-
extractedTextsPath = path.join(outputDir, "extracted_texts.json");
|
|
214
|
-
fs.writeFileSync(extractedTextsPath, JSON.stringify(extractedTexts, null, 2));
|
|
215
|
-
}
|
|
216
|
-
// Step 3: Vision API - analyze document (1 API call)
|
|
217
|
-
const images = buildPageImages(imagesDir, basename, pageCount);
|
|
218
|
-
const analysis = await analyzeDocument(provider, images, extractedTexts, resolvedLang);
|
|
219
|
-
// Save analysis
|
|
220
|
-
const analysisPath = path.join(outputDir, "analysis.json");
|
|
221
|
-
fs.writeFileSync(analysisPath, JSON.stringify(analysis, null, 2));
|
|
222
|
-
console.log(`Document analysis saved: ${analysisPath}`);
|
|
223
|
-
console.log(` Sections: ${analysis.sections.length}`);
|
|
224
|
-
console.log(` Figures: ${analysis.figures.length}`);
|
|
225
|
-
console.log(` Planned slides: ${analysis.slides.length}`);
|
|
226
|
-
// Step 4: Crop figures from high-res page images
|
|
227
|
-
console.log("Cropping figures from page images...");
|
|
228
|
-
const figureImageMap = cropFigures(analysis, imagesDir, basename, pdfFile);
|
|
229
|
-
console.log(` Cropped ${figureImageMap.size} figures`);
|
|
230
|
-
// Step 5: Text LLM - generate narration (1 API call)
|
|
231
|
-
const narrations = await generateNarrations(provider, analysis, extractedTexts, resolvedLang);
|
|
232
|
-
// Step 6: Build and write MulmoScript
|
|
233
|
-
const mulmoScript = buildMulmoScript(analysis, narrations, basename, resolvedLang, figureImageMap);
|
|
234
|
-
const jsonPath = path.join(outputDir, `${basename}.json`);
|
|
235
|
-
writeMulmoScript(mulmoScript, jsonPath);
|
|
236
|
-
console.log(`\n✓ pdfvision conversion complete!`);
|
|
237
|
-
console.log(` Provider: ${provider}`);
|
|
238
|
-
console.log(` Pages: ${pageCount} → Slides: ${analysis.slides.length}`);
|
|
239
|
-
console.log(` Output: ${jsonPath}`);
|
|
240
|
-
return {
|
|
241
|
-
mulmoScriptPath: jsonPath,
|
|
242
|
-
extractedTextsPath,
|
|
243
|
-
analysisPath,
|
|
244
|
-
slideCount: analysis.slides.length,
|
|
245
|
-
};
|
|
246
|
-
};
|
|
247
|
-
//# sourceMappingURL=pdfvision.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pdfvision.js","sourceRoot":"","sources":["../../src/convert/pdfvision.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { SupportedLang } from "./lang.js";
|
|
2
|
-
export interface SectionInfo {
|
|
3
|
-
name: string;
|
|
4
|
-
pages: number[];
|
|
5
|
-
summary: string;
|
|
6
|
-
}
|
|
7
|
-
export interface BoundingBox {
|
|
8
|
-
x: number;
|
|
9
|
-
y: number;
|
|
10
|
-
width: number;
|
|
11
|
-
height: number;
|
|
12
|
-
}
|
|
13
|
-
export interface FigureInfo {
|
|
14
|
-
page: number;
|
|
15
|
-
type: "figure" | "table" | "chart" | "diagram";
|
|
16
|
-
label?: string;
|
|
17
|
-
description: string;
|
|
18
|
-
importance: "high" | "medium" | "low";
|
|
19
|
-
bbox?: BoundingBox;
|
|
20
|
-
}
|
|
21
|
-
export interface SlideSpec {
|
|
22
|
-
title: string;
|
|
23
|
-
section: string;
|
|
24
|
-
sourcePages: number[];
|
|
25
|
-
imagePage?: number;
|
|
26
|
-
figureRef?: string;
|
|
27
|
-
narrationHint: string;
|
|
28
|
-
}
|
|
29
|
-
export interface DocumentAnalysis {
|
|
30
|
-
title: string;
|
|
31
|
-
authors?: string;
|
|
32
|
-
sections: SectionInfo[];
|
|
33
|
-
figures: FigureInfo[];
|
|
34
|
-
slides: SlideSpec[];
|
|
35
|
-
}
|
|
36
|
-
export interface BuildAnalysisPromptOptions {
|
|
37
|
-
pageCount: number;
|
|
38
|
-
extractedTexts: string[];
|
|
39
|
-
lang: SupportedLang;
|
|
40
|
-
}
|
|
41
|
-
export declare const buildDocumentAnalysisPrompt: (options: BuildAnalysisPromptOptions) => string;
|
|
42
|
-
export declare const parseDocumentAnalysis: (content: string) => DocumentAnalysis;
|
|
43
|
-
//# sourceMappingURL=document-analysis.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"document-analysis.d.ts","sourceRoot":"","sources":["../../src/utils/document-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,eAAO,MAAM,2BAA2B,GAAI,SAAS,0BAA0B,KAAG,MAwEjF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,KAAG,gBA+CvD,CAAC"}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { getLanguageName, extractJsonFromResponse } from "./llm.js";
|
|
2
|
-
export const buildDocumentAnalysisPrompt = (options) => {
|
|
3
|
-
const { pageCount, extractedTexts, lang } = options;
|
|
4
|
-
const languageName = getLanguageName(lang);
|
|
5
|
-
const textSummaries = extractedTexts
|
|
6
|
-
.map((text, i) => {
|
|
7
|
-
if (!text || text.trim().length === 0)
|
|
8
|
-
return `--- Page ${i} ---\n(no text)`;
|
|
9
|
-
const truncated = text.length > 2000 ? text.slice(0, 2000) + "..." : text;
|
|
10
|
-
return `--- Page ${i} ---\n${truncated}`;
|
|
11
|
-
})
|
|
12
|
-
.join("\n\n");
|
|
13
|
-
return `You are analyzing a PDF document to create an engaging presentation.
|
|
14
|
-
|
|
15
|
-
The document has ${pageCount} pages. I'm showing you all pages as images and providing extracted text.
|
|
16
|
-
|
|
17
|
-
Extracted text per page:
|
|
18
|
-
${textSummaries}
|
|
19
|
-
|
|
20
|
-
Analyze the document and create a presentation plan. Respond in JSON:
|
|
21
|
-
|
|
22
|
-
{
|
|
23
|
-
"title": "document title",
|
|
24
|
-
"authors": "author names if identifiable",
|
|
25
|
-
"sections": [
|
|
26
|
-
{
|
|
27
|
-
"name": "section name",
|
|
28
|
-
"pages": [0, 1],
|
|
29
|
-
"summary": "brief section summary"
|
|
30
|
-
}
|
|
31
|
-
],
|
|
32
|
-
"figures": [
|
|
33
|
-
{
|
|
34
|
-
"page": 0,
|
|
35
|
-
"type": "figure|table|chart|diagram",
|
|
36
|
-
"label": "Figure 1",
|
|
37
|
-
"description": "what the figure shows",
|
|
38
|
-
"importance": "high|medium|low",
|
|
39
|
-
"bbox": {"x": 10, "y": 30, "width": 80, "height": 40}
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
"slides": [
|
|
43
|
-
{
|
|
44
|
-
"title": "slide title in ${languageName}",
|
|
45
|
-
"section": "section name",
|
|
46
|
-
"sourcePages": [0, 1],
|
|
47
|
-
"imagePage": 0,
|
|
48
|
-
"figureRef": "Figure 1",
|
|
49
|
-
"narrationHint": "key points to explain in this slide"
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
Guidelines:
|
|
55
|
-
- "sections": identify the logical structure of the document (intro, main sections, conclusion, etc.)
|
|
56
|
-
- "figures": identify ALL figures, tables, charts, and diagrams. Mark important ones as "high"
|
|
57
|
-
- "bbox": bounding box as percentage of page dimensions (0-100). x = left edge %, y = top edge %, width and height in %.
|
|
58
|
-
IMPORTANT: err on the side of LARGER bounding boxes. Add 3-5% extra margin on all sides. It is much better to include a bit of surrounding whitespace than to cut off any part of the figure, its axis labels, legends, title, or caption.
|
|
59
|
-
Include the full figure with ALL labels, axis text, legends, and captions.
|
|
60
|
-
For a figure in the lower-left quadrant: {"x": 2, "y": 50, "width": 50, "height": 48}
|
|
61
|
-
- "slides": create a presentation that explains the document to an audience
|
|
62
|
-
- NOT 1:1 with pages. Group related content, split dense pages
|
|
63
|
-
- Each important figure (high importance) should get its own slide
|
|
64
|
-
- "imagePage": which page image to show for this slide (0-based)
|
|
65
|
-
- "title": write in ${languageName}
|
|
66
|
-
- "narrationHint": describe what the presenter should explain (in English for clarity)
|
|
67
|
-
- Typical slide count: 8-15 slides for a 10-20 page document
|
|
68
|
-
- Include an introduction slide and a conclusion/summary slide
|
|
69
|
-
- Skip appendix/reference pages unless they contain critical content
|
|
70
|
-
- "figureRef": reference a figure label from the figures array when the slide focuses on that figure
|
|
71
|
-
|
|
72
|
-
Respond ONLY with valid JSON.`;
|
|
73
|
-
};
|
|
74
|
-
export const parseDocumentAnalysis = (content) => {
|
|
75
|
-
const jsonStr = extractJsonFromResponse(content);
|
|
76
|
-
const parsed = JSON.parse(jsonStr);
|
|
77
|
-
const analysis = {
|
|
78
|
-
title: parsed.title ?? "Untitled",
|
|
79
|
-
authors: parsed.authors,
|
|
80
|
-
sections: (parsed.sections ?? []).map((s) => ({
|
|
81
|
-
name: String(s.name ?? ""),
|
|
82
|
-
pages: Array.isArray(s.pages) ? s.pages.map(Number) : [],
|
|
83
|
-
summary: String(s.summary ?? ""),
|
|
84
|
-
})),
|
|
85
|
-
figures: (parsed.figures ?? []).map((f) => {
|
|
86
|
-
const bbox = f.bbox;
|
|
87
|
-
const parsedBbox = bbox && bbox.x != null && bbox.y != null && bbox.width != null && bbox.height != null
|
|
88
|
-
? {
|
|
89
|
-
x: Number(bbox.x),
|
|
90
|
-
y: Number(bbox.y),
|
|
91
|
-
width: Number(bbox.width),
|
|
92
|
-
height: Number(bbox.height),
|
|
93
|
-
}
|
|
94
|
-
: undefined;
|
|
95
|
-
return {
|
|
96
|
-
page: Number(f.page ?? 0),
|
|
97
|
-
type: String(f.type ?? "figure"),
|
|
98
|
-
label: f.label ? String(f.label) : undefined,
|
|
99
|
-
description: String(f.description ?? ""),
|
|
100
|
-
importance: String(f.importance ?? "medium"),
|
|
101
|
-
bbox: parsedBbox,
|
|
102
|
-
};
|
|
103
|
-
}),
|
|
104
|
-
slides: (parsed.slides ?? []).map((s) => ({
|
|
105
|
-
title: String(s.title ?? ""),
|
|
106
|
-
section: String(s.section ?? ""),
|
|
107
|
-
sourcePages: Array.isArray(s.sourcePages) ? s.sourcePages.map(Number) : [],
|
|
108
|
-
imagePage: s.imagePage != null ? Number(s.imagePage) : undefined,
|
|
109
|
-
figureRef: s.figureRef ? String(s.figureRef) : undefined,
|
|
110
|
-
narrationHint: String(s.narrationHint ?? ""),
|
|
111
|
-
})),
|
|
112
|
-
};
|
|
113
|
-
if (analysis.slides.length === 0) {
|
|
114
|
-
throw new Error("DocumentAnalysis has no slides");
|
|
115
|
-
}
|
|
116
|
-
return analysis;
|
|
117
|
-
};
|
|
118
|
-
//# sourceMappingURL=document-analysis.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"document-analysis.js","sourceRoot":"","sources":["../../src/utils/document-analysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { SupportedLang } from "./lang.js";
|
|
2
|
-
import type { DocumentAnalysis } from "./document-analysis.js";
|
|
3
|
-
export interface NarrationInput {
|
|
4
|
-
documentAnalysis: DocumentAnalysis;
|
|
5
|
-
extractedTexts: string[];
|
|
6
|
-
lang: SupportedLang;
|
|
7
|
-
}
|
|
8
|
-
export interface NarrationEntry {
|
|
9
|
-
index: number;
|
|
10
|
-
text: string;
|
|
11
|
-
}
|
|
12
|
-
export declare const buildNarrationPrompt: (input: NarrationInput) => string;
|
|
13
|
-
export declare const parseNarrationResponse: (content: string, slideCount: number) => NarrationEntry[];
|
|
14
|
-
//# sourceMappingURL=narration-generator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"narration-generator.d.ts","sourceRoot":"","sources":["../../src/utils/narration-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,oBAAoB,GAAI,OAAO,cAAc,KAAG,MA0D5D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,EAAE,YAAY,MAAM,KAAG,cAAc,EAa1F,CAAC"}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { getLanguageName, extractJsonFromResponse } from "./llm.js";
|
|
2
|
-
export const buildNarrationPrompt = (input) => {
|
|
3
|
-
const { documentAnalysis, extractedTexts, lang } = input;
|
|
4
|
-
const languageName = getLanguageName(lang);
|
|
5
|
-
const slideSpecs = documentAnalysis.slides
|
|
6
|
-
.map((slide, i) => {
|
|
7
|
-
const sourceTexts = slide.sourcePages
|
|
8
|
-
.map((p) => extractedTexts[p])
|
|
9
|
-
.filter(Boolean)
|
|
10
|
-
.join("\n---\n");
|
|
11
|
-
const truncatedText = sourceTexts.length > 3000 ? sourceTexts.slice(0, 3000) + "..." : sourceTexts;
|
|
12
|
-
const parts = [
|
|
13
|
-
`--- Slide ${i} ---`,
|
|
14
|
-
`Title: ${slide.title}`,
|
|
15
|
-
`Section: ${slide.section}`,
|
|
16
|
-
`Narration hint: ${slide.narrationHint}`,
|
|
17
|
-
];
|
|
18
|
-
if (slide.figureRef) {
|
|
19
|
-
parts.push(`Key visual: ${slide.figureRef}`);
|
|
20
|
-
}
|
|
21
|
-
if (truncatedText) {
|
|
22
|
-
parts.push(`Source text:\n${truncatedText}`);
|
|
23
|
-
}
|
|
24
|
-
return parts.join("\n");
|
|
25
|
-
})
|
|
26
|
-
.join("\n\n");
|
|
27
|
-
return `You are a professional presenter creating narration for a presentation.
|
|
28
|
-
|
|
29
|
-
Document: "${documentAnalysis.title}"${documentAnalysis.authors ? ` by ${documentAnalysis.authors}` : ""}
|
|
30
|
-
|
|
31
|
-
Here are the slides with their source content and narration hints:
|
|
32
|
-
|
|
33
|
-
${slideSpecs}
|
|
34
|
-
|
|
35
|
-
Generate narration text for ALL ${documentAnalysis.slides.length} slides.
|
|
36
|
-
|
|
37
|
-
Requirements:
|
|
38
|
-
- Write in ${languageName}
|
|
39
|
-
- Speak directly to the audience as if presenting live
|
|
40
|
-
- NEVER use meta-references like "this slide shows", "here we see", "このスライドでは"
|
|
41
|
-
- When a slide has a key visual (figure/table/chart), explain what it shows and why it matters
|
|
42
|
-
- Flow naturally between slides as a coherent presentation
|
|
43
|
-
- Be substantive - explain concepts, don't just list bullet points
|
|
44
|
-
- Use a confident, engaging speaking style suitable for text-to-speech
|
|
45
|
-
- Each narration should be 2-5 sentences
|
|
46
|
-
|
|
47
|
-
Respond in JSON:
|
|
48
|
-
{
|
|
49
|
-
"narrations": [
|
|
50
|
-
{"index": 0, "text": "narration text"},
|
|
51
|
-
{"index": 1, "text": "narration text"}
|
|
52
|
-
]
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
Respond ONLY with valid JSON.`;
|
|
56
|
-
};
|
|
57
|
-
export const parseNarrationResponse = (content, slideCount) => {
|
|
58
|
-
const jsonStr = extractJsonFromResponse(content);
|
|
59
|
-
const parsed = JSON.parse(jsonStr);
|
|
60
|
-
const narrations = (parsed.narrations ?? []).map((n) => ({
|
|
61
|
-
index: Number(n.index ?? 0),
|
|
62
|
-
text: String(n.text ?? ""),
|
|
63
|
-
}));
|
|
64
|
-
// Fill missing indices with empty text
|
|
65
|
-
const resultMap = new Map(narrations.map((n) => [n.index, n]));
|
|
66
|
-
return Array.from({ length: slideCount }, (_, i) => resultMap.get(i) ?? { index: i, text: "" });
|
|
67
|
-
};
|
|
68
|
-
//# sourceMappingURL=narration-generator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"narration-generator.js","sourceRoot":"","sources":["../../src/utils/narration-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type VisionProvider = "gemini" | "openai";
|
|
2
|
-
export interface VisionImage {
|
|
3
|
-
path: string;
|
|
4
|
-
}
|
|
5
|
-
export interface VisionRequest {
|
|
6
|
-
prompt: string;
|
|
7
|
-
images: VisionImage[];
|
|
8
|
-
}
|
|
9
|
-
export declare const resolveVisionProvider: (preferred?: string) => VisionProvider;
|
|
10
|
-
export declare const callVisionAPI: (provider: VisionProvider, request: VisionRequest) => Promise<string>;
|
|
11
|
-
export declare const callTextLLM: (provider: VisionProvider, prompt: string) => Promise<string>;
|
|
12
|
-
//# sourceMappingURL=vision-provider.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vision-provider.d.ts","sourceRoot":"","sources":["../../src/utils/vision-provider.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAOD,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,KAAG,cAkB1D,CAAC;AA8DF,eAAO,MAAM,aAAa,GACxB,UAAU,cAAc,EACxB,SAAS,aAAa,KACrB,OAAO,CAAC,MAAM,CAOhB,CAAC;AA2BF,eAAO,MAAM,WAAW,GAAU,UAAU,cAAc,EAAE,QAAQ,MAAM,KAAG,OAAO,CAAC,MAAM,CAO1F,CAAC"}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
2
|
-
import { getOpenAIClient, imageToBase64, getImageMediaType, extractResponseContent, } from "./llm.js";
|
|
3
|
-
const GEMINI_VISION_MODEL = "gemini-2.0-flash";
|
|
4
|
-
const GEMINI_TEXT_MODEL = "gemini-2.0-flash";
|
|
5
|
-
const OPENAI_VISION_MODEL = "gpt-4o";
|
|
6
|
-
const OPENAI_TEXT_MODEL = "gpt-4o";
|
|
7
|
-
export const resolveVisionProvider = (preferred) => {
|
|
8
|
-
if (preferred) {
|
|
9
|
-
if (preferred !== "gemini" && preferred !== "openai") {
|
|
10
|
-
throw new Error(`Unknown provider: ${preferred}. Use 'gemini' or 'openai'.`);
|
|
11
|
-
}
|
|
12
|
-
return preferred;
|
|
13
|
-
}
|
|
14
|
-
if (process.env.GEMINI_API_KEY) {
|
|
15
|
-
return "gemini";
|
|
16
|
-
}
|
|
17
|
-
if (process.env.OPENAI_API_KEY) {
|
|
18
|
-
return "openai";
|
|
19
|
-
}
|
|
20
|
-
throw new Error("No Vision API key found. Set GEMINI_API_KEY or OPENAI_API_KEY environment variable.");
|
|
21
|
-
};
|
|
22
|
-
const getGeminiClient = () => {
|
|
23
|
-
const apiKey = process.env.GEMINI_API_KEY;
|
|
24
|
-
if (!apiKey) {
|
|
25
|
-
throw new Error("GEMINI_API_KEY environment variable is not set");
|
|
26
|
-
}
|
|
27
|
-
return new GoogleGenerativeAI(apiKey);
|
|
28
|
-
};
|
|
29
|
-
const callGeminiVision = async (request) => {
|
|
30
|
-
const genAI = getGeminiClient();
|
|
31
|
-
const model = genAI.getGenerativeModel({ model: GEMINI_VISION_MODEL });
|
|
32
|
-
const imageParts = request.images.map((img) => {
|
|
33
|
-
const base64 = imageToBase64(img.path);
|
|
34
|
-
const mimeType = getImageMediaType(img.path);
|
|
35
|
-
return {
|
|
36
|
-
inlineData: { data: base64, mimeType },
|
|
37
|
-
};
|
|
38
|
-
});
|
|
39
|
-
const result = await model.generateContent([request.prompt, ...imageParts]);
|
|
40
|
-
const response = result.response;
|
|
41
|
-
const text = response.text();
|
|
42
|
-
if (!text) {
|
|
43
|
-
throw new Error("No response from Gemini Vision API");
|
|
44
|
-
}
|
|
45
|
-
return text;
|
|
46
|
-
};
|
|
47
|
-
const callOpenAIVision = async (request) => {
|
|
48
|
-
const client = getOpenAIClient();
|
|
49
|
-
const imageContents = request.images.flatMap((img) => {
|
|
50
|
-
const base64 = imageToBase64(img.path);
|
|
51
|
-
const mediaType = getImageMediaType(img.path);
|
|
52
|
-
return [
|
|
53
|
-
{
|
|
54
|
-
type: "image_url",
|
|
55
|
-
image_url: { url: `data:${mediaType};base64,${base64}`, detail: "auto" },
|
|
56
|
-
},
|
|
57
|
-
];
|
|
58
|
-
});
|
|
59
|
-
const content = [
|
|
60
|
-
{ type: "text", text: request.prompt },
|
|
61
|
-
...imageContents,
|
|
62
|
-
];
|
|
63
|
-
const response = await client.chat.completions.create({
|
|
64
|
-
model: OPENAI_VISION_MODEL,
|
|
65
|
-
messages: [{ role: "user", content }],
|
|
66
|
-
response_format: { type: "json_object" },
|
|
67
|
-
});
|
|
68
|
-
return extractResponseContent(response);
|
|
69
|
-
};
|
|
70
|
-
export const callVisionAPI = async (provider, request) => {
|
|
71
|
-
switch (provider) {
|
|
72
|
-
case "gemini":
|
|
73
|
-
return callGeminiVision(request);
|
|
74
|
-
case "openai":
|
|
75
|
-
return callOpenAIVision(request);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
const callGeminiText = async (prompt) => {
|
|
79
|
-
const genAI = getGeminiClient();
|
|
80
|
-
const model = genAI.getGenerativeModel({ model: GEMINI_TEXT_MODEL });
|
|
81
|
-
const result = await model.generateContent(prompt);
|
|
82
|
-
const text = result.response.text();
|
|
83
|
-
if (!text) {
|
|
84
|
-
throw new Error("No response from Gemini Text API");
|
|
85
|
-
}
|
|
86
|
-
return text;
|
|
87
|
-
};
|
|
88
|
-
const callOpenAIText = async (prompt) => {
|
|
89
|
-
const client = getOpenAIClient();
|
|
90
|
-
const response = await client.chat.completions.create({
|
|
91
|
-
model: OPENAI_TEXT_MODEL,
|
|
92
|
-
messages: [{ role: "user", content: prompt }],
|
|
93
|
-
response_format: { type: "json_object" },
|
|
94
|
-
});
|
|
95
|
-
return extractResponseContent(response);
|
|
96
|
-
};
|
|
97
|
-
export const callTextLLM = async (provider, prompt) => {
|
|
98
|
-
switch (provider) {
|
|
99
|
-
case "gemini":
|
|
100
|
-
return callGeminiText(prompt);
|
|
101
|
-
case "openai":
|
|
102
|
-
return callOpenAIText(prompt);
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
//# sourceMappingURL=vision-provider.js.map
|