Accessibility statement

Last reviewed 1 October 2026 · surstreaming-support@sahin.tech

The short version

surstreaming turns live chat into speech. That part works and does not depend on sight: comments, gifts, likes and follows are read aloud in your browser, and each chat user can be given their own voice so you can hear who is talking.

The dashboard's controls are a different story. They are fully keyboard-reachable and increasingly named, but several operational states are still only shown visually. We therefore recommend running surstreaming as a two-person stream: whoever is at the screen manages the setup, and the person listening does not need to touch the interface mid-stream.

What this page is not

This is not a WCAG conformance claim, and we have not commissioned a third-party accessibility audit. There is no VPAT. Everything below is observed behaviour of the application as shipped.

What already works

  • Every control in the dashboard is a real focusable element. There is no click-handler attached to a bare <div> or <span> anywhere in the live app, so the keyboard reaches all of it.
  • Focus is visible: buttons and inputs draw a brand-coloured outline on :focus-visible, and comment-feed rows get the same treatment via :focus-within.
  • All eleven per-utterance settings toggles carry an accessible name — "Read Nickname", "Read gifts aloud", "Only read comments from Moderators", and so on.
  • Long-running state changes are announced: the voice-model download, stream errors, the trial-exhausted notice and connection warnings are live regions.
  • Comment-feed row actions name their target, and muting is a two-step confirmation whose button label changes to "Mute <name>?"
  • The speech queue keeps draining while the tab is in the background — it does not depend on requestAnimationFrame or interval timers, which browsers throttle in hidden tabs.

Known gaps

These are real and unresolved. We would rather list them than have you discover them.

Handles are never spoken aloud

Chat is announced with the sender's display name, but every management action — muting, assigning a custom voice — is keyed on the stable @handle, which is a different and changeable-looking string. A non-visual user hears a nickname and then has to work out which handle it belongs to. This is the most significant remaining gap for solo use.

The comment feed is not reachable by keyboard

The scrolling feed region has no tabindex, so arrow keys do not scroll it. Past the most recent ~500 events there is no way to reach older messages by keyboard at all, and no control to load them.

Feed filter buttons are abbreviated and don't expose their state

The per-type filters read "COM", "GIF", "LIK", "FOL" and convey the selected state only through colour. The All / Auto-scroll / JSON buttons carry no accessible name.

Telemetry is removed from the accessibility tree on narrow viewports

Below 1200px the TTS status card is hidden with display:none rather than visually hidden, so a screen-reader user on a small window or at high zoom loses all engine and queue status.

Inert filter controls still take keyboard focus

When the comment trigger is off, the audience filter block is dimmed with pointer-events:none — which affects the mouse only. Its controls stay tabbable and operable, and the fact that the block is inactive is not announced.

The spoken text is not a faithful transcript

Before synthesis, emoji are stripped, runs of three or more repeated words are collapsed, digit runs longer than four are truncated, and blocklisted terms are dropped. None of this is announced, so a listener cannot tell that something was removed. This is deliberate — it is what makes chat bearable to listen to — but it does mean the audio is an edited version.

No skip link or focus management

There is no skip-to-content link, and the page does not move focus when the stream connects or disconnects, so navigation is linear.

The interface language does not follow the speech language

The page is always lang="en". The TTS language is independently selectable across 31 languages, so you can select Japanese speech while a screen reader continues reading the interface in English.

Two speech sources can collide

If your screen reader and surstreaming both play through the same output device their output interleaves. surstreaming is a separate page, so it can be routed to its own audio device — which is the workaround the blind-streamer community already uses in reverse — but nothing in the app configures this for you.

Hands-off mode

The dashboard has a Hands-off toggle in its header. It hides the setup-only cards — voice, language, filters and the blocklist — leaving connection state, volume, the live actions and the feed. Nothing is disabled, only hidden, and the same toggle brings the settings back. It exists so the audio role in a two-person stream has no settings card to navigate at all.

Found something we've missed?

Please mail surstreaming-support@sahin.tech with what you hit and which browser and screen reader you were using. Reports from people who actually use this are worth more to us than a generic audit, and we will tell you honestly whether something is fixable, is on the roadmap, or is a limitation of the platform the live happens on.

We use analytics cookies to improve your experience. By clicking Accept, you consent to these cookies. Disabling them stops all analytics tracking and removes their cookies.