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()
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.