DEV Community

Carl Henderson
Carl Henderson

Posted on

Help and advice needed Please!

Hey everyone! πŸ‘‹

I'm currently building a little learning app for my son, and I’ve run into a snag with text-to-speech on Windows.

The app works great overall, but while it picks up the correct voice on macOS (say), on Windows it seems to ignore the HD Narrator/Natural voice we installed and defaults to the generic system voice instead.

Here is the code I’m using for the speech synthesis:

@staticmethod
def speak(text: str) -> None:
    """Synthesize and play text-to-speech using OS native APIs.
    Runs on background thread to avoid blocking UI. Supports macOS (say) and Windows (PowerShell).
    Args:
        text: Text string to speak aloud.
    """
    def _run_speech() -> None:
        """Execute speech synthesis on background thread."""
        system_name = platform.system()
        try:
            # macOS uses native 'say' command.
            if system_name == "Darwin":
                subprocess.run(["say", text], check=False)
            # Windows uses System.Speech which respects the user's selected narrator voice.
            elif system_name == "Windows":
                safe_text = text.replace("'", "''")  # Escape single quotes for PowerShell.
                cmd = (
                    "Add-Type -AssemblyName System.Speech; "
                    "$synth = New-Object System.Speech.Synthesis.SpeechSynthesizer; "
                    f"$synth.Speak('{safe_text}');"
                )
                subprocess.run(
                    ["powershell", "-NoProfile", "-Command", cmd],
                    check=False,
                    creationflags=0x08000000,  # CREATE_NO_WINDOW β€” keeps it silent in background.
                )
            else:
                print(f"Speech not supported on platform: {system_name}")
        except (OSError, subprocess.SubprocessError) as e:
            print(f"Speech error: {e}")

    # Start speech in daemon thread so UI remains responsive.
    threading.Thread(target=_run_speech, daemon=True).start()
Enter fullscreen mode Exit fullscreen mode

Has anyone run into an issue with System.Speech.Synthesis.SpeechSynthesizer in PowerShell failing to pick up newly installed Windows HD/Natural voices? Do I need to explicitly select the voice by name in the PowerShell script rather than relying on the default?

Any tips or pointers would be massively appreciated! πŸ™

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.