Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LightRead

Speed-read anything on your screen, with the voice locked to the same words per minute.

Select text in any app, press Ctrl+Shift+R, and LightRead flashes it one word at a time with a red focus letter while reading it aloud at exactly the speed you set. The red letter and the voice run off one clock, so the word you hear is the word you see.

Windows only. The app lives in the tray and is named READ.exe.

Download

Grab READ.exe from the latest release and run it. Nothing to install.

  • Windows 10 or 11, 64-bit. Self-contained: no .NET install needed.
  • Voices come from Windows itself (Settings → Time & language → Speech). The bundled David and Zira voices work out of the box.
  • The exe is not code-signed, so SmartScreen will show "Windows protected your PC" the first time. Click More infoRun anyway, or build it yourself from source below.

Build from source

Needs the .NET 9 SDK.

pwsh -NoProfile -File run.ps1

Or publish a single exe:

pwsh -NoProfile -File run.ps1 -Publish

Then run dist\READ.exe. It sits in the tray.

Input Action
Select text, then Ctrl+Shift+R Grab and play
Ctrl+Shift+R with nothing selected Falls back to the clipboard
Ctrl+V in the window Paste and play
Tray → Read clipboard Same
Space Play / pause
[ ] or mouse wheel WPM
← → Sentence
, . Word
V Voice on/off
R Restart
Esc Hide to tray
PIN Keep the overlay on the desktop

Voice ON: RSVP is driven by the stretched audio. The number you set is the actual spoken+shown WPM.

Voice OFF: pure visual RSVP, 80–800 WPM, with punctuation pauses and a short start ramp.

How the voice lock works

Locking speech to an exact WPM means getting two things right that SAPI reports misleadingly.

Word positions. SpeakProgress.CharacterPosition is an offset into whatever was handed to Speak. Passing a PromptBuilder means SAPI speaks an SSML document, so every position comes back shifted by the length of the SSML preamble and maps to the wrong word. LightRead speaks the raw string, and drops any mark that does not index into it.

Word timing. SpeakProgress.AudioPosition is measured against the voice's own sample rate, not the stream being written. The bundled Windows desktop voices are 16 kHz but render at 22.05 kHz, so every timestamp arrives inflated by 22050/16000 — enough for the display to drift a quarter of the way ahead by the end of a passage. LightRead writes to a stream that records how much audio existed when each mark fired, fits the single scale factor relating the two, and corrects every timestamp. A voice whose rates already agree fits a factor of 1.

With honest timings, the rest is arithmetic: measure the natural WPM, pick the SAPI rate that gets closest on its own, and let SoundTouch stretch away the remainder. Choosing the rate first keeps the stretch near 1.0, which is where it sounds best — a 16 kHz voice at 800 WPM would otherwise need a 5x stretch.

Tokens SAPI never reports — bare punctuation, symbols it expands into a different number of words — are interpolated between their neighbours so each still gets its own slice of the clock.

Checks

dotnet test

Unit tests cover the ORP split, the visual clock and the voice binding. SpeechSyncTests drives the real SAPI stack, because both defects above lived in the seam between SAPI and the engine and neither was visible from a mock.

pwsh -NoProfile -File run.ps1 -SelfTest

The self-test additionally renders audio at 200, 500 and 800 WPM and asserts the result actually runs at that rate, that every word mark lands on the token it belongs to, and that walking the audio clock visits every word in order and ends on the last one. It writes %TEMP%\read-selftest.log and exits non-zero on failure.

Unhandled exceptions are appended to %APPDATA%\READ\crash.log rather than silently taking the tray icon down.

If Ctrl+Shift+R seems to do nothing

The hotkey depends on other processes cooperating, so run with tracing to see how far a press got:

dist\READ.exe --debug

That writes %APPDATA%\READ\debug.log with a line for the registration result, each WM_HOTKEY received, and what capture returned. The usual causes, in order:

  • LightRead is not running. It has no taskbar button — look for the tray icon.
  • Another app owns Ctrl+Shift+R. RegisterHotKey fails, and LightRead opens its window at startup to say so rather than relying on a tray balloon you might miss.
  • The app you copied from ignored the synthetic Ctrl+C (PDF viewers, canvas apps, remote desktops). LightRead falls back to whatever is already on the clipboard and says so in the status bar.

A press always opens the window, even when it captures nothing, so it never looks like nothing happened. Launching a second copy raises the running one rather than exiting silently.

Stack

WPF, .NET 9, System.Speech, NAudio, SoundTouch. No sidecar processes, no per-word WAV cache.

License

MIT — see LICENSE.

About

Speed-read anything on your screen, with the voice locked to the same WPM. Windows RSVP reader with a red focus letter.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages