Technical guide to how the Polili on-screen OCR translator scales, filters, and recognizes Chinese subtitle characters — and how to configure your setup for maximum accuracy.
Polili uses PaddleOCR PP-OCRv3, Baidu's third-generation lightweight recognition model, compiled to ONNX format and run entirely inside the browser via ONNX Runtime Web (WASM). The model is downloaded once (~10 MB), cached in IndexedDB, and runs fully offline — no images are ever sent to a server.
PP-OCRv3 uses a CTC (Connectionist Temporal Classification) decoder against a 6,625-character dictionary covering simplified Chinese, traditional Chinese, punctuation, digits, and Latin letters. It substantially outperforms Tesseract on Chinese subtitle fonts because it was specifically trained on text-in-the-wild image data rather than document scans.
Before any image reaches the neural network, Polili applies five transformation stages to maximize character visibility:
The browser draws the current video frame onto an OffscreenCanvas cropped
to the user-defined subtitle strip. Only the strip is processed — never the full frame.
A 3% horizontal edge trim removes corner watermarks and streaming logos that would
otherwise confuse the model.
If the cropped strip is shorter than 60 pixels vertically, Polili scales it up (up to 3×) so the character height reaches the model's optimal input range. The output width is capped at 1800 px to avoid memory pressure.
Movie subtitles are almost universally white or yellow on a dark background. Polili applies a two-branch filter: pixels with luminance > 210 and low color saturation (white/grey) are rendered black. Bright yellow pixels (Taiwanese/HK-style subtitles: R > 200, G > 190, B < 40) are also rendered black. All other pixels become white. The result is clean black-on-white text that the CTC decoder reads with high confidence.
After isolation, Polili counts the fraction of black pixels in the strip (the "density"). If density is below 0.4% — no text present — the frame is skipped. If above 8% — bright scene flash or title card — the frame is also skipped. Real dialog subtitles consistently fall between 0.4% and 7%.
Inside the offscreen OCR document, Polili finds the leftmost and rightmost columns containing any black pixel and crops the image to that span (plus half-height padding). This removes blank whitespace that would cause the CTC decoder to hallucinate characters in empty regions.
The single biggest factor in OCR accuracy is the rendered height of the subtitle characters in pixels. Characters must be tall enough for the model to distinguish between visually similar glyphs (e.g., 己/已/巳, 土/士, 末/未).
| Video quality | Approx. char height | Expected accuracy | Verdict |
|---|---|---|---|
| 1080p | 32–40 px | 98–99% on standard subtitle fonts | Excellent |
| 720p | 22–28 px | 94–97% | Recommended minimum |
| 480p | 14–18 px | 80–88% — some characters confused | Acceptable |
| 360p | 10–13 px | 60–75% — frequent errors on complex chars | Not recommended |
The upscaling step (pipeline stage 2) partially compensates for low resolution, but cannot recover detail that was never captured. Set your video player to 720p or higher before starting Polili for best results.
The PP-OCRv3 model has a small set of systematic confusions on specific character pairs. Polili applies two correction layers after decoding:
Applied to any character matching the key, regardless of context:
石 → 看 — 石 (stone) and 看 (to look/watch) share similar stroke geometry at low resolution百 → 首 — 百 (hundred) misread for 首 (head/first/song)苔 → 首 — rare botanical character confused with 首设 → 没 — 设 (to set up) misread for 没 (not/without) in dialogue contextApplied to bigrams/trigrams where the wrong string is never valid Chinese:
希里 → 希望 — 望 misread as 里 after 希 (hope)失里 → 失望 — 望 misread as 里 after 失 (disappointed)范固 → 范围 — 围 (range/scope) misread as 固 (solid)白以为是 → 自以为是 — 自 (self) misread as 白 (white/blank)These corrections are updated in each release. If you encounter a systematic error not listed above, email feedback@polili.app with a screenshot and the video URL — confirmed errors are patched within two weeks.
Polili samples the subtitle strip every 250 ms. If the new OCR result is very similar to the previous one (same subtitle still on screen), rendering it again would cause the pinyin overlay to flicker. Polili uses a character-bag similarity score:
The lower threshold for longer subtitles allows Polili to catch lines that reuse common characters (你/我/了/快…) but differ in meaning — lines that a naive character-counting approach would incorrectly suppress.