Skip to main content

Overview

Speech synthesizer drivers enable NVDA to produce speech output through various text-to-speech engines. Each driver implements the interface between NVDA and a specific speech synthesis technology (SAPI5, eSpeak, OneCore, etc.).

Driver Architecture

Base Class

All synthesizer drivers inherit from synthDriverHandler.SynthDriver, which provides:
  • Voice and parameter management
  • Speech command processing
  • Audio output coordination
  • Configuration persistence

Core Responsibilities

  1. Speech Output: Convert text and commands to synthesized speech
  2. Voice Management: Enumerate and switch between available voices
  3. Parameter Control: Handle rate, pitch, volume, and other settings
  4. Event Notifications: Signal when speech starts, ends, or reaches bookmarks

Creating a Basic Driver

Minimal Driver Structure

synthDrivers/silence.py

Required Components

str
required
Unique identifier for the driver (should match module filename)
str
required
Human-readable name shown in NVDA’s speech settings
set[type]
required
Speech commands the synth supports. Must include IndexCommand
set
required
Notifications the synth provides: synthIndexReached, synthDoneSpeaking

Full SAPI5 Implementation

The SAPI5 driver demonstrates a complete, production-quality implementation:

Driver Initialization

Voice Management

Speech Parameters

Speech Command Processing

Command Types

Bookmark Processing

Audio Output Management

Custom Audio Stream

For fine-grained control, implement a custom audio stream:

Audio Ducking

Advanced Features

Rate Boost with Sonic

Implement rate boost using the Sonic time-stretching library:

Voice Variants

Language Support

Testing Your Driver

Debug Output

Manual Testing

1

Install the driver

Place your driver in source/synthDrivers/yourdriver.py
2

Restart NVDA

Restart NVDA or reload plugins
3

Select the driver

Open NVDA Settings > Speech and select your synthesizer
4

Test features

  • Verify basic speech output
  • Test rate, pitch, volume controls
  • Test voice switching
  • Verify index markers work
  • Test pausing and canceling

Best Practices

Asynchronous Speech

Always speak asynchronously to avoid blocking NVDA’s main thread

Index Commands

Always support IndexCommand - it’s essential for coordinating speech with braille and other features

Clean Cancellation

Implement cancel() to immediately stop speech without artifacts

Resource Cleanup

Release audio resources and COM objects in terminate()
Use synthDoneSpeaking notification to support features like “say all” that need to know when an utterance completes.

Common Issues

No Speech Output

  • Verify audio output is initialized
  • Check that speak() is actually called
  • Ensure no exceptions are silently caught
  • Test with NVDA’s speech viewer enabled

Choppy or Garbled Speech

  • Check audio buffer sizes
  • Verify sample rate matches synth output
  • Ensure proper synchronization between audio threads

Index Markers Not Working

  • Verify synthIndexReached is in supportedNotifications
  • Ensure bookmarks are correctly parsed from synth events
  • Check that indices match between speak() and notifications

Voice Selection Issues

  • Ensure voice IDs are unique and consistent
  • Verify availableVoices returns correct information
  • Check that voice tokens are properly validated

Reference

Key Modules

  • synthDriverHandler: Base synthesizer driver framework
  • speech.commands: Speech command classes (IndexCommand, etc.)
  • nvwave: Audio output and wave player
  • audioDucking: Audio ducking (reducing other app volumes)
  • languageHandler: Language and locale handling

Speech Commands

Example Drivers

Study these drivers in source/synthDrivers/ for reference:
  • sapi5.py: Full-featured SAPI5 implementation
  • espeak.py: eSpeak NG integration
  • oneCore.py: Windows OneCore voices
  • silence.py: Minimal driver structure

Developer Guide

See the NVDA Developer Guide for complete plugin development information