mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(tools): 2.0 phase 5 wave 5b - ai pool: ocr-pdf, transcription, background composites (5 tools) (#226)
This commit is contained in:
@@ -18,10 +18,13 @@ export type { FaceLandmarkPoint, FaceLandmarks, FaceLandmarksResult } from "./fa
|
||||
export { detectFaceLandmarks } from "./face-landmarks.js";
|
||||
export { inpaint } from "./inpainting.js";
|
||||
export { noiseRemoval } from "./noise-removal.js";
|
||||
export { extractText } from "./ocr.js";
|
||||
export type { PdfOcrOptions, PdfOcrResult } from "./ocr.js";
|
||||
export { extractPdfText, extractText } from "./ocr.js";
|
||||
export type { OutpaintOptions } from "./outpainting.js";
|
||||
export { outpaint } from "./outpainting.js";
|
||||
export { removeRedEye } from "./red-eye-removal.js";
|
||||
export { restorePhoto } from "./restoration.js";
|
||||
export { seamCarve } from "./seam-carving.js";
|
||||
export type { TranscribeOptions, TranscriptionResult, TranscriptSegment } from "./transcription.js";
|
||||
export { transcribeAudio } from "./transcription.js";
|
||||
export { upscale } from "./upscaling.js";
|
||||
|
||||
@@ -53,3 +53,48 @@ export async function extractText(
|
||||
engine: result.engine,
|
||||
};
|
||||
}
|
||||
|
||||
// ── PDF OCR ───────────────────────────────────────────────────────────
|
||||
|
||||
export interface PdfOcrOptions {
|
||||
quality?: OcrQuality;
|
||||
language?: string;
|
||||
pages?: string;
|
||||
}
|
||||
|
||||
export interface PdfOcrResult {
|
||||
text: string;
|
||||
engine: string;
|
||||
pages: number;
|
||||
}
|
||||
|
||||
export async function extractPdfText(
|
||||
inputPath: string,
|
||||
opts: PdfOcrOptions = {},
|
||||
onProgress?: ProgressCallback,
|
||||
): Promise<PdfOcrResult> {
|
||||
const optionsJson = JSON.stringify({
|
||||
quality: opts.quality ?? "balanced",
|
||||
language: opts.language ?? "auto",
|
||||
pages: opts.pages ?? "all",
|
||||
});
|
||||
|
||||
const { stdout } = await runPythonWithProgress("ocr_pdf.py", [inputPath, optionsJson], {
|
||||
timeout: 30 * 60_000,
|
||||
onProgress,
|
||||
});
|
||||
|
||||
const result = parseStdoutJson(stdout);
|
||||
if (result.error) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
if (!result.success) {
|
||||
throw new Error(result.error || "PDF OCR failed");
|
||||
}
|
||||
|
||||
return {
|
||||
text: result.text ?? "",
|
||||
engine: result.engine ?? "unknown",
|
||||
pages: result.pages ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { type ProgressCallback, parseStdoutJson, runPythonWithProgress } from "./bridge.js";
|
||||
|
||||
/**
|
||||
* A single timed segment of transcribed speech.
|
||||
* Defined locally (packages/ai cannot depend on apps/api);
|
||||
* the route layer adapts to the api-side TranscriptSegment shape.
|
||||
*/
|
||||
export interface TranscriptSegment {
|
||||
startS: number;
|
||||
endS: number;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface TranscriptionResult {
|
||||
language: string;
|
||||
text: string;
|
||||
segments: TranscriptSegment[];
|
||||
}
|
||||
|
||||
export interface TranscribeOptions {
|
||||
language: string;
|
||||
}
|
||||
|
||||
export async function transcribeAudio(
|
||||
inputPath: string,
|
||||
opts: TranscribeOptions,
|
||||
onProgress?: ProgressCallback,
|
||||
): Promise<TranscriptionResult> {
|
||||
const optionsJson = JSON.stringify({
|
||||
language: opts.language,
|
||||
task: "transcribe",
|
||||
});
|
||||
|
||||
const { stdout } = await runPythonWithProgress("transcribe.py", [inputPath, optionsJson], {
|
||||
timeout: 30 * 60_000,
|
||||
onProgress,
|
||||
});
|
||||
|
||||
const result = parseStdoutJson(stdout);
|
||||
if (result.error) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
// Map python segment keys {start, end, text} to {startS, endS, text}.
|
||||
// Defensive: if segments is missing or not an array, default to [].
|
||||
const rawSegments: Array<{ start?: number; end?: number; text?: string }> = Array.isArray(
|
||||
result.segments,
|
||||
)
|
||||
? result.segments
|
||||
: [];
|
||||
|
||||
const segments: TranscriptSegment[] = rawSegments.map((seg) => ({
|
||||
startS: seg.start ?? 0,
|
||||
endS: seg.end ?? 0,
|
||||
text: (seg.text ?? "").trim(),
|
||||
}));
|
||||
|
||||
return {
|
||||
language: result.language ?? "en",
|
||||
text: result.text ?? "",
|
||||
segments,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user