import {createWorker} from 'tesseract.js'; import {AbortablePromise, Ai} from './ai.ts'; export class Vision { constructor(private ai: Ai) {} /** * Convert image to text using Optical Character Recognition * @param {string} path Path to image * @returns {AbortablePromise} Promise of extracted text with abort method */ ocr(path: string): AbortablePromise { let worker: any; let reject: (err: any) => void; const handler = (err: Error) => { if(err.stack?.includes('tesseract.js')) { process.off('uncaughtException', handler); reject?.(err); return; } throw err; }; process.on('uncaughtException', handler); const p = (async () => { worker = await createWorker(this.ai.options.ocr || 'eng', 2, {cachePath: this.ai.options.path}); return await new Promise((res, rej) => { reject = rej; worker.recognize(path) .then(({data}: any) => res(data.text.trim() || null)) .catch(rej); }); })().finally(() => { process.off('uncaughtException', handler); worker?.terminate(); }); return Object.assign(p, {abort: () => worker?.terminate()}); } }