-
-
Notifications
You must be signed in to change notification settings - Fork 0
syn speak
The desktop, out loud — syn-speak. Everything on this desktop says what it
has to say in pixels; this is the other channel. It announces the window that
has focus as focus moves, reads the text you have highlighted, and speaks any
line handed to it.
Shipped by the synui package as /usr/bin/syn-speak.
⚠ It is an announcer, not a full screen reader — and it says so itself. A real screen reader walks the accessibility tree and reads every widget under the cursor, which needs AT-SPI support in each toolkit and is a project of its own. What this does is the half that is both useful today and honest: what has focus, and what it is asked for. Orca remains the answer for the full tree, and this does not pretend otherwise.
⛔ Nothing speaks until asked. It is off on a fresh install, and the switch is per user. A desktop that started talking after an update would be the worst possible version of this feature.
| Key | What it does |
|---|---|
Super+Shift+U
|
Screen reader on/off — announce the focused window as focus moves, and press again to stop |
Super+U
|
Read whatever is highlighted right now, once |
Super+Shift+V
|
Dictate — listen once, and type what you said where the cursor is (vibe) |
They are keys, and not only a menu item, for the obvious reason: a screen reader you can only start from a terminal is not one — the person who needs it is the person who cannot read the terminal to start it.
One chord toggles, rather than a pair. A reader talking over you has to be stoppable with the key you just pressed, not with a different one you have to remember while it is talking.
Super+Shift+V is V for voice; Super+V is the clipboard.
Two panels offer the same switch, because SynapseOS can be installed with KDE or GNOME instead of synui and the setting still has to be reachable:
-
synui's control panel —
Super+C▸ Sound ▸ Speech. Two rows: Screen reader and Answer to its name (that second one is vibe's wake word, and it holds a microphone open — the bar shows a microphone icon while it does). -
syn-settings ▸ Speech — the same two switches, plus the speech
rate, the volume, the wake words, which engines this box actually has, and the
two units behind the switches:
syn-speak.service(the announcer) andvibe-wake.service(the listener). That last pair is the row to read when a switch says On and nothing happens — a switch and the thing it switches are two separate facts, and this is where the second one is visible.
Neither reimplements anything. They read the state files and run the commands below, so there is one answer to "is the reader on" and not three.
syn-speak on # announce the focused window from now on
syn-speak off # stop, and stop talking now
syn-speak toggle # whichever of those applies
syn-speak window # say the focused window once
syn-speak selection # say the highlighted text once
syn-speak say "ready" # say a line
syn-speak stop # silence what is being said
syn-speak voice NAME # syn-speak voices lists them
syn-speak rate 80..450 # words per minute (default 175)
syn-speak volume 0..100
syn-speak status # what it would do, and what this box can dosyn-speak status is the one to reach for first — it reports the switch, the
voice, the rate, the volume, which engine would actually speak, and the
window it would announce right now:
on yes
voice en
rate 175
volume 100
engine vibe
window Inbox, thunderbird
engine is vibe, or the synthesiser name (espeak-ng), or none.
⛔ syn-speak does not own a speech engine. Where vibe is installed
it speaks through vibe voice say — which is chibi's piper — so
the screen reader and the assistant sound like the same desktop, and there is
one place where "which engine does this box have" is worked out.
espeak-ng is what is left when vibe is absent, not a second opinion. It is
an optdepends of synui; on an install that took no AI stack it is the only
voice there is, so:
synpkg install espeak-ngWithout either, the switch turns on and the machine stays silent. syn-speak status reports engine none, and syn-speak say says which synthesiser it
looked for, on stderr, and exits 3.
⚠ One utterance at a time. A new line stops the one in progress. Two announcements overlapping is not twice the information, it is none — and it is what makes the announcer usable at speed: moving quickly between windows leaves you hearing the one you landed on, not a queue of the ones you passed.
syn-speak on does two things: it writes on=yes, and it enables
syn-speak.service, a user unit that runs syn-speak watch — the loop that
polls the focused window and speaks it when it changes. WantedBy=default.target,
so the choice survives a login.
systemctl --user status syn-speak.service # is the reader actually running⚠ A poll, deliberately. synui has no "focus changed" event a client can
subscribe to, and adding one to the compositor for a feature that ships off
would be a protocol for nothing. Half a second is under the threshold at which a
window switch feels unannounced, and one synctl call at that rate costs
nothing measurable.
⚠ The loop announces on change. A window is spoken once when you land on it, not once per poll.
If the switch says On and nothing is announced, check
systemctl --user status syn-speak.servicefirst — or syn-settings ▸ Speech, which shows the same thing as a row. Between synui 527 and 563 that unit was not in the package at all:syn-speak ontried to enable it, the failure was swallowed on purpose (so that a machine without systemd is not a broken install), and all three surfaces reported On with nothing behind them. Fixed in synui 0.1.0-564.
~/.config/synui/speak.state, key=value, the same shape every other synui
state file uses — so it greps, and it can be fixed with an editor.
| Key | Default | What it is |
|---|---|---|
on |
no |
is the announcer switched on |
voice |
en |
an espeak-ng voice name — syn-speak voices lists them |
rate |
175 |
words per minute, 80–450 |
volume |
100 |
0–100 |
interval |
0.5 |
seconds between focus checks; no command sets it, edit the file |
voice falls back to lang if it is not set, so an existing lang= line keeps
working.
| a voice |
vibe (piper), or espeak-ng
|
| the focused window |
synctl, from the synui package |
| the selection |
wl-clipboard — wl-paste --primary first, since on Wayland that is what "the text I just highlighted" means; the clipboard is what was deliberately copied |
python3, to read synctl's JSON |
Every one of them is checked by name rather than by running it and looking at the exit status: "not installed" and "ran and failed" want opposite answers.
The announcer asks synctl which window has focus, and synctl finds the
compositor through WAYLAND_DISPLAY. A user unit does not have one —
nothing in this session runs systemctl --user import-environment — so
syn-speak resolves the name synui publishes at
$XDG_RUNTIME_DIR/synui-display, the same file synui-foot.service and
synui-media-inhibit read.
⛔ An explicit WAYLAND_DISPLAY always wins and is never overridden. That
published file names the live desktop, so a nested or headless synui — a test
rig, a screenshot rig — must not have its announcer read the real session's
windows out loud.
- Keybindings — the three keys, in the System table
- Settings — the Speech pane
-
Vibe — the assistant:
vibe voice, dictation, and the wake word - Chibi — where piper and faster-whisper come from
Using it
- Installation
- Welcome Guide
- Updating
- Software
- Files
- Settings
- Calendar
- Editor
- Studio
- Terminal
- Keybindings
- Speech and dictation
- Remote Desktop
- Commands
- Configuration
- Nix
- Gaming
- Big Screen
- DaVinci Resolve
- Secure Boot
- Troubleshooting
Customising it
Components
Apps
Hacking on it