Switching to processes and whisper.cpp to avoid transformers.js memory leaks
All checks were successful
Publish Library / Build NPM Project (push) Successful in 38s
Publish Library / Tag Version (push) Successful in 5s

This commit is contained in:
2026-02-20 21:50:01 -05:00
parent 790608f020
commit 39537a4a8f
9 changed files with 215 additions and 262 deletions

View File

@@ -2,43 +2,22 @@ import {createWorker} from 'tesseract.js';
import {AbortablePromise, Ai} from './ai.ts';
export class Vision {
private worker: any = null;
private queue: Array<{ path: string, resolve: any, reject: any }> = [];
private busy = false;
constructor(private ai: Ai) {}
private async processQueue() {
if(this.busy || !this.queue.length) return;
this.busy = true;
const job = this.queue.shift()!;
if(!this.worker) this.worker = await createWorker(this.ai.options.ocr || 'eng', 2, {cachePath: this.ai.options.path});
try {
const {data} = await this.worker.recognize(job.path);
job.resolve(data.text.trim() || null);
} catch(err) {
job.reject(err);
}
this.busy = false;
this.processQueue();
}
/**
* Convert image to text using Optical Character Recognition
* @param {string} path Path to image
* @returns {AbortablePromise<string | null>} Promise of extracted text with abort method
*/
ocr(path: string): AbortablePromise<string | null> {
let aborted = false;
const abort = () => { aborted = true; };
const p = new Promise<string | null>((resolve, reject) => {
this.queue.push({
path,
resolve: (text: string | null) => !aborted && resolve(text),
reject: (err: Error) => !aborted && reject(err)
});
this.processQueue();
let worker: any;
const p = new Promise<string | null>(async res => {
worker = await createWorker(this.ai.options.ocr || 'eng', 2, {cachePath: this.ai.options.path});
const {data} = await worker.recognize(path);
await worker.terminate();
res(data.text.trim() || null);
});
return Object.assign(p, {abort});
return Object.assign(p, {abort: () => worker?.terminate()});
}
}