Inclusion (Audio Guide / TTS)
Hosanna provides an audio guide pipeline with priorities and flushing, backed by an ITextToSpeechManager
that proxies the Roku system and adds queueing and debug support.
Overview
Accessibility ensures your TV app is usable by everyone, including users who rely on screen readers or audio cues. Hosanna UI integrates accessibility patterns inspired by platforms like SwiftUI (tvOS) and React Native for TV.
By default, non-semantic views (like containers or spacers) do not announce anything to avoid clutter. Meaningful elements like text labels, buttons, and media items can provide spoken feedback through a dedicated accessibility label.
Getting Speech in Dev (Web)
- Run with
?textToSpeech=true
to enable TTS in the browser emulator. - The debug extension shows the queue, current item, and timings; it also provides tools to flush/inspect.
View Fields & Labels
Views expose two fields for the audio guide:
audioGuideHint
: a brief suffix used by components to construct spoken text.audioGuideItem
: an optionalIAudioGuideItem
you can set directly.
For simple labels, provide a short, human-readable string via audioGuideHint
.
Example
Button({ text: 'Rent', audioGuideHint: 'Rent this movie' })
Default Fallback Behavior
If audioGuideLabel
is not provided:
- Text: falls back to "Button [
text
field]". - Button: falls back to "Button [
text
field]". - ComboBox: falls back to "ComboBox [
value
field]". - Image: falls back to "Image [
id
field]". - Non-semantic containers: speak nothing by default.
Custom Views
You can override the default behavior by implementing getAudioGuideItem()
in your view to return an IAudioGuideItem
.
This provides full control over what your component announces when focused.
Priorities, Flushing, and Timing
To avoid rapid, repetitive speech while navigating quickly between controls:
- The focus manager introduces a short delay (typically 250–400ms) before announcing a label.
- If the user moves focus before the delay completes, the previous label is cancelled.
Internally, items are queued with a priority
(default 10). Higher priority interrupts equal-or-lower priority items. When flushPrevious
is true (default at the manager unless overridden), the manager flushes queued items with priority ≥ the incoming item’s priority and interrupts the current item at or below that level.
Programmatic speech helper:
static sayText(text: string, priority?: number, origin?: IHosannaView<ViewState>, flushPrevious?: boolean): void {
if (priority === undefined) priority = 10;
if (flushPrevious === undefined) flushPrevious = false;
const tts = AppUtils.resolve<ITextToSpeechManager>('textToSpeechManager');
tts.sayAudioItem({ text, priority, flushPrevious });
}
Advanced Enhancements
You can further improve accessibility by supporting:
- Localization of spoken strings
- Semantic roles (e.g. "button", "image") for internal prioritization
- Focus zones (e.g. rows or grids that announce a group label before items)
- Live region updates to announce dynamic changes in content
Best Practices
- Don’t rely on internal IDs or variable names as spoken text.
- Provide a meaningful
audioGuideHint
for buttons and actions. - Keep labels concise, clear, and user-facing.
- Use structured override methods for complex or dynamic views.
Summary
Element Type | Spoken Label Defaults |
---|---|
Text | supply audioGuideHint |
Button | uses text + audioGuideHint |
Custom Components | override getAudioGuideItem() |
Containers | Return "" unless explicitly labeled |
You can preview and debug spoken labels in your app using Hosanna’s focus manager logs or audio simulation tools.