{"slug": "text-to-speech-on-windows-the-built-in-voices-edge-tts-and-why-subtitle-dubbing", "title": "Text to speech on Windows: the built-in voices, edge-tts, and why subtitle dubbing never fits", "summary": "A developer compared text-to-speech options on Windows, showing that the built-in System.Speech API can synthesize speech to WAV files without installation or network access, while the edge-tts Python package drives Microsoft's neural Edge voices to produce MP3 output with matching subtitles. The writeup notes that voices installed through Windows Settings often fail to appear in System.Speech because SAPI 5 and OneCore voices live in separate registry hives, and that subtitle timings rarely accommodate synthesized narration, which typically overruns cue durations.", "body_md": "Narration for a video, a spoken prompt in an app, a subtitle file turned into audio: all of it starts with getting text read out and saved to a file. Windows can do it with what's already installed, and the neural voices are a `pip install` away. Here's what each route costs you.\n\nNarrator and Edge's Read Aloud use the built-in speech engine, but neither will save what it reads. `System.Speech` will:\n\n``` php\nAdd-Type -AssemblyName System.Speech\n$s = New-Object System.Speech.Synthesis.SpeechSynthesizer\n\n# What's available\n$s.GetInstalledVoices() | ForEach-Object { $_.VoiceInfo.Name + \" (\" + $_.VoiceInfo.Culture + \")\" }\n\n$s.SelectVoice(\"Microsoft Zira Desktop\")\n$s.Rate = 0                      # -10 .. 10\n$s.SetOutputToWaveFile(\"C:\\temp\\narration.wav\")\n$s.Speak((Get-Content \"C:\\temp\\script.txt\" -Raw -Encoding UTF8))\n$s.Dispose()\n```\n\nNo install, no network, and it writes a WAV. The delivery is unmistakably synthetic, so it suits prompts and beeps more than narration.\n\nAdd a voice under Settings > Time & language > Speech and it often doesn't appear in `GetInstalledVoices()`. The two generations of voices live in different registry hives:\n\n```\n# SAPI 5 - what System.Speech reads\nGet-ChildItem 'HKLM:\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens'\n\n# OneCore - what Settings installs, and Narrator uses\nGet-ChildItem 'HKLM:\\SOFTWARE\\Microsoft\\Speech_OneCore\\Voices\\Tokens'\n```\n\nOn the Windows 11 (25H2) machine I checked, the SAPI hive had two voices and the OneCore hive had a third one that `System.Speech` could never select. If a voice you installed isn't in the list, this is why.\n\nThe voices Edge reads pages with are neural, and `edge-tts` drives them directly:\n\n``` php\npip install edge-tts\n\n# text -> MP3, with a matching .srt\nedge-tts --text \"Hello, world!\" --write-media hello.mp3 --write-subtitles hello.srt\n\nedge-tts --list-voices\n\n# a script file, in a chosen voice\nedge-tts --voice en-US-AriaNeural --file script.txt --write-media narration.mp3\n\nedge-tts --rate=-50% --text \"Hello, world!\" --write-media slower.mp3\nedge-tts --volume=-50% --text \"Hello, world!\" --write-media quieter.mp3\nedge-tts --pitch=-50Hz --text \"Hello, world!\" --write-media lower.mp3\n```\n\nOptions are from the project's README and CLI help. No API key, no account, and it writes MP3 rather than WAV, which matters once a batch of scripts piles up.\n\nA subtitle file states exactly how long each line is on screen. Read that line aloud and it is nearly always longer, because people skim subtitles while a synthesizer pronounces every syllable. Translate first and the gap widens.\n\n``` php\ncue  1  00:00:00,000 --> 00:00:03,500   (3.5s)   speech 3.2s   fits\ncue  2  00:00:03,500 --> 00:00:07,000   (3.5s)   speech 4.6s   overruns into cue 3\ncue  3  00:00:07,000 --> 00:00:12,000   (5.0s)   speech 4.4s   fits\n```\n\nWhat actually works:\n\nMaking something new rather than dubbing? Generate the narration first and cut the visuals to its length. Then nothing has to be squeezed.\n\n`edge-tts`, but they are Microsoft's service, so read the terms before shipping commercial work.\nFigures are from September 2026 and these terms change often. \"Free to generate, but not for monetised content\" is a common combination, and it's the sort of thing that surfaces after the video is published.\n\nThe full version, with diagrams and a GUI option for people who don't want a terminal:\n\nWhich route do you use for narration?", "url": "https://wpnews.pro/news/text-to-speech-on-windows-the-built-in-voices-edge-tts-and-why-subtitle-dubbing", "canonical_source": "https://dev.to/_8729c5bde46be2/text-to-speech-on-windows-the-built-in-voices-edge-tts-and-why-subtitle-dubbing-never-fits-4o6l", "published_at": "2026-09-21 01:02:18+00:00", "updated_at": "2026-09-21 01:22:51.062384+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "natural-language-processing"], "entities": ["Microsoft", "Windows", "edge-tts", "System.Speech", "Microsoft Zira Desktop", "en-US-AriaNeural"], "alternates": {"html": "https://wpnews.pro/news/text-to-speech-on-windows-the-built-in-voices-edge-tts-and-why-subtitle-dubbing", "markdown": "https://wpnews.pro/news/text-to-speech-on-windows-the-built-in-voices-edge-tts-and-why-subtitle-dubbing.md", "text": "https://wpnews.pro/news/text-to-speech-on-windows-the-built-in-voices-edge-tts-and-why-subtitle-dubbing.txt", "jsonld": "https://wpnews.pro/news/text-to-speech-on-windows-the-built-in-voices-edge-tts-and-why-subtitle-dubbing.jsonld"}}