Files
2026-07-12 10:17:17 -04:00

86 lines
2.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tesseract.js Client-Side Debugging Pattern
## The Problem
`Tesseract.recognize()` in the browser has multiple silent phases before "recognizing text":
1. `loading tesseract core` — downloads WASM from CDN
2. `initializing tesseract` — sets up the engine
3. `loading language traineddata` — downloads `eng.traineddata` from CDN
4. `initializing api` — final setup
5. `recognizing text` — actual OCR (the only phase with progress %)
If any phase fails (CSP block, CDN timeout, worker crash), the promise **never resolves or rejects**.
The UI just shows "Running OCR..." forever.
## The Fix: Promise.race + Full Phase Logger
```javascript
// Show ALL phases, not just "recognizing text"
const ocrResult = await Promise.race([
Tesseract.recognize(preprocessed, 'eng', {
logger: m => {
console.log(`[OCR] ${m.status} ${m.progress ? Math.round(m.progress*100)+'%' : ''}`);
if (m.status === 'recognizing text') {
progressText.textContent = `OCR: ${Math.round(m.progress*100)}%`;
} else {
progressText.textContent = `Tesseract: ${m.status}...`;
}
},
tessedit_pageseg_mode: '4'
}),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('OCR timed out after 90s')), 90000)
)
]);
```
**Why this works:**
- `Promise.race` breaks the hang — after 90s, it rejects with a clear error
- Full phase logging shows EXACTLY where it's stuck ("loading language traineddata..." = CDN issue)
- The console gets timestamped `[OCR]` logs for post-mortem debugging
## Performance: Adaptive Upscaling
3× upscale on HD screenshots creates massive canvases (5760×3240). Use adaptive scaling:
```javascript
// 2x for large images, 3x for small ones
const scale = (img.width * img.height > 1000000) ? 2 : 3;
canvas.width = img.width * scale;
canvas.height = img.height * scale;
```
This cuts pixel count by ~55% on typical screenshots while keeping 3× for small crops.
## Second OCR Pass (Date Extraction)
The date OCR pass uses PSM 11 (sparse text) and runs on the same preprocessed blob. Apply the same
pattern with a shorter timeout (30s):
```javascript
const dateOcrResult = await Promise.race([
Tesseract.recognize(preprocessed, 'eng', {
logger: m => { /* same pattern */ },
tessedit_pageseg_mode: '11'
}),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Date OCR timed out')), 30000)
)
]);
```
## Ollama Cold-Model 502 Retry
The VPS proxy may return 502 when the local model is unloaded (KEEP_ALIVE=5m). The model takes
~3-6s to load. Retry once after a 5s delay:
```javascript
for (let attempt = 0; attempt < 2; attempt++) {
const resp = await fetch(endpoint, { ... });
if (resp.ok) break;
if (resp.status !== 502 && resp.status !== 503) throw new Error(...);
await new Promise(r => setTimeout(r, 5000)); // wait for model load
}
```