ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
翻译准备中
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Pacer and RSVP epub reader for language learners (GTK4)
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Pacer and RSVP reader for epub/txt, built for language learners. GTK4 / libadwaita, one Python file.查看完整 README ↗Pacer and RSVP reader for epub/txt, built for language learners. GTK4 / libadwaita, one Python file.
unknown.txtP reads the current sentence aloud (piper TTS, offline, voice downloaded on first use); the popup has a pronounce buttonA read-along: piper reads sentence by sentence and the highlight follows the voice. WPM sets the speech speed~/.config/speedready/vocab.tsv with its sentence, importable into Anki as-isB toggles one, Shift+B opens the list)L): every book you have opened, newest first, with how far through it you are. Add several at once from the file picker, or drag epub and txt files straight onto the window. Titles come from the epub's own metadata, so the list reads like a shelf and not like a download folder./install.sh # venv with simplemma + piper-tts, launcher + icon
./run.sh book.epub # or open "Speedready" from your app launcher
| key | action |
|---|---|
| space | play / pause |
| ← → | ±10 words |
| PageUp / PageDown | ±one page |
| ↑ ↓ | speed ±5 (shift: ±25) |
| [ ] | words per step |
| M | pacer / rsvp |
| R | replay sentence |
| D | define current word |
| click / double-click / right-click | continue from there / dictionary popup / mark unknown |
| P | speak from here to the end of the sentence, again to stop |
| A | read-along |
| B / Shift+B | toggle bookmark / open bookmarks |
| C | chapters |
| L | library |
| F11, S, O | fullscreen, settings, open |
Beginner mode glosses each word from an offline pack, gloss-<src>-<tgt>.sqlite, which the app
downloads once per language pair on first use. The packs are built from English Wiktionary and each
language's own Wiktionary edition (kaikki.org) and hermitdave/FrequencyWords.
See DATA-LICENSES.md for upstream licence and attribution details.
python tools/fetch_sources.py # ~2 GB of extracts -> ~/.cache/speedready/build
python tools/release_packs.py --jobs 6 # build every pair, measure, keep the good ones
python tools/release_packs.py --upload # gh release upload to the "packs" release
A pack is only published if it glosses at least half of the 2000 commonest words in its source
language (--min-coverage). Pairs below the floor are dropped rather than shipped, because a pack
that exists but glosses nothing would have the app report the dictionary ready over a page of blank
glosses. An unpublished pair is reported as such in the app.
MUSE-free pack build, 2026-09-25: all 90 language pairs passed the 50% threshold. Median coverage
was 92.1%; best was sv->en at 96.7%, worst ru->nl at 54.8%. Total size was 4.66 GB. These
figures come from tools/release_packs.py measured against each pair's top 2,000 source words.
Content words are reliable across every pair. The commonest grammar words often are not: Wiktionary
picks the wrong homograph for them (sv->de gives är as "Gut, Ware", nl->pt gives is as
"seu"). GLOSS_OVERRIDES in speedready.py fixes these by hand for de->pt only. Curating that list
once for de->en and pivoting it would fix every de->X pair at once, since knowing that wollen is
"want" and not "woollen" does not depend on the target language.
In German books every noun is colored by gender: blue for der, red for die, green for das (Settings → Deutsch).
gender.py holds the logic, with no GTK code so a browser extension can port it line for line. It takes the
gender from the article in front (die stille See is the sea, der See the lake), splits unknown compounds
(Hahnenfeder → Feder), colors plurals by their singular, and leaves pronouns, names, plural-only nouns and
ambiguous sentence-initial words alone. web/gender.js is the same logic for the web reader, and web/textclean.js is the book cleanup; tests/test_web_parity.py
fails if the Python and JavaScript versions ever disagree (PYTHONPATH=. python tests/test_web_parity.py *.epub checks real books). The data, web/genders-de.json.gz (0.6 MB, noun form → genders), comes from
the kaikki.org English Wiktionary extract:
python tools/build_genders.py ~/.cache/speedready/build/en-German.jsonl.gz
python gender.py # self-check
web/ is a self-contained reader for learners, and it is also what the Android and iOS
apps load: a book in any of 10 languages with a translation in your own language above
every word you have not marked as known yet. Tap a translation to mark the word learned
and it disappears everywhere; tap a word for its dictionary entry. Books you add stay in
a library (the apps can also scan a folder for books and let you pick which to add). The
interface is in all 10 languages. It ships with a public-domain German book, speaks
through the device's own voice, and works offline once loaded (installable to the home
screen). It is a separate implementation from the desktop reader; they share the data
pipeline (tools/export_web.py, coreglosses.py), not the reading code.
core/ holds hand-checked glosses for each language's ~300 most frequent words, which a
context-free dictionary gets wrong most often. python tools/export_web.py --patch <dict files>
writes them into exported dictionaries; pairs without English go through English.
Read-along drives the highlight from its own estimated clock rather than from
onboundary, which iOS reports unreliably, and re-syncs whenever a boundary event does
arrive. Devices with no speech voices installed say so instead of failing silently.
Build its data from a desktop pack:
python tools/export_web.py de pt # -> web/dict-de-pt.json (8.5 MB, ~1.7 MB gzipped)
The shipped language pair is named in web/bundle.json and nowhere else; index.html and sw.js
both read it, and the reader takes its source language from the dictionary's own src field. So
changing which pair the website and the Android APK carry is that one command plus a starter book,
with no code edit. A test enforces it: neither file may name a dictionary or a language again.
One APK still ships one pair, because the dictionary is bundled and the app asks for no permissions at all. Shipping more than one means either a bigger APK or network access, which is a trade worth making deliberately.
ios/ is a native shell around web/, the same way android/ is: the page does the reading, and
ios/Speedready/App.swift serves it offline from the app bundle and adds dialogs, the Anki export via the
share sheet, links out to Safari, and speech that plays with the silent switch on. It needs iOS 16.4+
(the offline dictionary unpacks with DecompressionStream).
open ios/Speedready.xcodeproj # run in the simulator from Xcode
ASC_KEY_PATH=… ASC_KEY_ID=… ASC_ISSUER=… ios/release.sh # signed .ipa for App Store Connect, from Terminal on the Mac
Create the app record (bundle id io.github.cyoren.speedready) in App Store Connect before the first upload.