DEV Community

코딩나우(하늘아래)
코딩나우(하늘아래)

Posted on Originally published at coding-now.com

Text to speech on Windows: the built-in voices, edge-tts, and why subtitle dubbing never fits

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.

The voices already in Windows

Narrator and Edge's Read Aloud use the built-in speech engine, but neither will save what it reads. System.Speech will:

Add-Type -AssemblyName System.Speech
$s = New-Object System.Speech.Synthesis.SpeechSynthesizer

# What's available
$s.GetInstalledVoices() | ForEach-Object { $_.VoiceInfo.Name + " (" + $_.VoiceInfo.Culture + ")" }

$s.SelectVoice("Microsoft Zira Desktop")
$s.Rate = 0                      # -10 .. 10
$s.SetOutputToWaveFile("C:\temp\narration.wav")
$s.Speak((Get-Content "C:\temp\script.txt" -Raw -Encoding UTF8))
$s.Dispose()
Enter fullscreen mode Exit fullscreen mode

No install, no network, and it writes a WAV. The delivery is unmistakably synthetic, so it suits prompts and beeps more than narration.

The gotcha: added voices that never show up

Add 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:

# SAPI 5 - what System.Speech reads
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Speech\Voices\Tokens'

# OneCore - what Settings installs, and Narrator uses
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Speech_OneCore\Voices\Tokens'
Enter fullscreen mode Exit fullscreen mode

On 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.

Neural voices from the command line

The voices Edge reads pages with are neural, and edge-tts drives them directly:

pip install edge-tts

# text -> MP3, with a matching .srt
edge-tts --text "Hello, world!" --write-media hello.mp3 --write-subtitles hello.srt

edge-tts --list-voices

# a script file, in a chosen voice
edge-tts --voice en-US-AriaNeural --file script.txt --write-media narration.mp3

edge-tts --rate=-50% --text "Hello, world!" --write-media slower.mp3
edge-tts --volume=-50% --text "Hello, world!" --write-media quieter.mp3
edge-tts --pitch=-50Hz --text "Hello, world!" --write-media lower.mp3
Enter fullscreen mode Exit fullscreen mode

Options 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.

Dubbing subtitles: the lengths never match

A 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.

cue  1  00:00:00,000 --> 00:00:03,500   (3.5s)   speech 3.2s   fits
cue  2  00:00:03,500 --> 00:00:07,000   (3.5s)   speech 4.6s   overruns into cue 3
cue  3  00:00:07,000 --> 00:00:12,000   (5.0s)   speech 4.4s   fits
Enter fullscreen mode Exit fullscreen mode

What actually works:

  • Raise the rate. 10-20% faster still sounds natural.
  • Shorten the line. The narration doesn't have to match the subtitle word for word.
  • Merge two short cues into one sentence, which buys room either side.
  • If it has to be frame-accurate, cut per cue in an editor instead of fighting the timings.

Making something new rather than dubbing? Generate the narration first and cut the visuals to its length. Then nothing has to be squeezed.

The part people skip: licensing

  • ElevenLabs free tier: 10k credits a month, and no commercial licence on the free plan (paid starts at $6/month).
  • Naver Clova Dubbing free tier: monthly download and character limits, attribution required, ads and promotion need a paid plan.
  • The Edge neural voices have no quota through edge-tts, but they are Microsoft's service, so read the terms before shipping commercial work.

Figures 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.


The full version, with diagrams and a GUI option for people who don't want a terminal:

Which route do you use for narration?

Top comments (0)