Name Reader - Gidntsquia/deadlock-street-brawl-helper GitHub Wiki
Name reader
The app reads three pieces of text on screen: each draft card's item name, the hero name on the loading screen (turned into dark letters on white, 60 px tall, before the read: the raw colour crop read as nothing at 1920x1080), and the "N Re-Roll Remaining" caption. After 0.4.0 these are read by Windows OCR (Windows.Media.Ocr, part of Windows 10 and 11), not Tesseract. Nothing extra is installed and no window opens: the app starts one hidden PowerShell helper when it opens, warms it with one test picture, and sends it each text crop.
How it works
electron/nameReader.tsstartswinocr-helper.ps1(shipped next to the app) hidden. The log linereader.readygives the start time. If the helper exits it is started once more; if it exits again (or never starts) the status line says Name reader not running, cards that are not read show a grey?, the hero comes from the window or your pick, and the re-roll count uses the glyph shape alone. The app keeps running.- The text is matched to item and hero names exactly as before (
matchItemName,matchHeroNameat 0.85). - Tooltips. Hovering a card makes the game draw a tooltip panel beside it, over a neighbour's name line. The panel's
text sits off centre in that line (a card's own name is always centred), so the app treats that line as covered: it is
not read and the card keeps the item it read before. A card that has never been seen uncovered shows a grey
?and gets its advice the moment it is read uncovered. A read that names the same item as another card is a tooltip title too, and both are read again. Log reasoncoveredoncard.name.unsure.
Measured (labelled crops, npm run names:compare)
544 labelled name crops: the five demo frames, the live frames, the 10 OBS video truth stretches at 1280x720 and the stored session crops. 30 are covered by a tooltip (skipped by the rule above), 514 are uncovered.
| Engine | Wrong | Sure (of 514) | Cold start | Warm p50 | Warm p95 |
|---|---|---|---|---|---|
| Windows OCR | 0 | 98.2 % (9 unsure) | 981 ms | 6.8 ms | 20.3 ms |
| Tesseract 7 (old) | 0 | 98.1 % (10 unsure) | 1135 ms | 51.8 ms | 67.5 ms |
Per size (the five demo frames scaled; 14 labelled cards each; read time per card):
| Size | Windows OCR sure / wrong | Windows OCR p50 / p95 | Tesseract sure / wrong | Tesseract p50 / p95 |
|---|---|---|---|---|
| 1280x720 | 14 / 0 | 6.0 / 18.5 ms | 14 / 0 | 49.3 / 70.0 ms |
| 1920x1080 | 14 / 0 | 7.2 / 20.3 ms | 14 / 0 | 48.5 / 62.0 ms |
| 2560x1440 | 14 / 0 | 8.0 / 19.9 ms | 14 / 0 | 61.5 / 76.3 ms |
Cold start: Windows OCR is the helper's start to its first answer (PowerShell and the OCR engine); Tesseract is its
worker and model load to its first answer. Warm: 20 reads of each of 10 crops, the first two of each dropped. Measured
2026-10-10 on the development PC (Windows 11, run from WSL). The Tesseract numbers use the same crops through the old
reader (--engine tesseract, which needs npm i --no-save tesseract.js@7 for that run only).
Unsure crops (Windows OCR)
All nine are 1280x720 frames from the OBS video truth set, and each gives no item for that frame (the card keeps waiting
for a frame that reads, and grey ? only if none does). In the video truth replay every one of these sets is still advised
with its right items.
| Frame | Card | Item | Reader text | Reason |
|---|---|---|---|---|
| s0#16 | middle | Toxic Bullets | "mage" | only part of the line read |
| s1#58 | right | Focus Lens | (nothing) | empty read |
| s2#10 | middle | Healing Tempo | "lealing Tet" | name cut off at both ends |
| s2#12 | middle | Healing Tempo | "Spilit 108 lealing Te" | tooltip text mixed into the line |
| s2#86 | right | Runed Gauntlets | (nothing) | empty read |
| s2#152 | right | Eternal Gift | "rnml G; '" | only part of the line read |
| s6#44 | right | Healing Nova | (nothing) | empty read |
| s7#2 | right | Bullet Resist Shredder | "let Resist Shred'*" | name cut off at both ends |
| s8#32 | right | Superior Duration | "erior DuW" | name cut off at both ends |
Advice time on the video truth set
Seconds from a set becoming readable to its advice, per set, replayed frame by frame (4 frames per second, so steps of
0.25 s; each read is allowed to finish before the next frame, so this measures the logic, not the reader's speed).
- means the set was not readable for 1 s. The bar is 1.0 s on every stretch (ADVICE_BY in scripts/lib/videoTruth.ts,
was 1.5 s). Before = Tesseract with the old tooltip handling, after = Windows OCR with the covered rule.
| Stretch | Before (Tesseract) | After (Windows OCR) |
|---|---|---|
| s0 | -, -, 0.25 | -, -, 0.25 |
| s1 | 0, 0.25, 0.5, - | 0, 0.25, 0.75, - |
| s2 | 0.5, 0, 0.75, 0 | 0.5, -0.25, 0.75, 0 |
| s3 | 0, 0, -, 0 | 0, 0, -, 0 |
| s4 | 0.25, -, 0 | 1, -, 0 |
| s5 | 0.25, -2, 0.25 | 0.25, -2.25, 0.25 |
| s6 | -, 0.25, 0.5 | -, 0.25, 0.5 |
| s7 | 1, 0.25, 0 | 1, 0.25, 0 |
| s8 | 0, 1, 0.25, 0.25 | -0.25, 0.25, 0.25, 0.25 |
| s9 | -, 0, 0.25 | -, 0, 0.25 |
A negative value is advice that went up before the labelled readable start (the set was read on a frame the label
counts as still settling). s4's first set is 1 s now: its right card is under a tooltip on the first readable frames (s4#10 to 14),
so it waits for an uncovered frame instead of trusting a line the tooltip covers.
All four rules (right items, advice within the bar, no drop-out, no advice with no set) pass on every stretch.
Download size
The portable exe built with this change is 105.1 MB (105,086,526 bytes); the 0.4.0 release was 125.5 MB. The Tesseract engine and model are gone; the helper script adds 3.8 KB.
Re-measuring
npm run names:compare -- --engine winocrscores recorded answers (scripts/fixtures/ocr-recorded/) anywhere;BRAWL_OCR=livereads every crop with the helper again (Windows, or WSL throughpowershell.exe),BRAWL_OCR=recordadds answers for new crops.npx tsx scripts/video-truth-report.tsprints the table above (about 3 min).