hugmys0ul
hugmys0ul

Reputation: 143

How to use Windows System.Speech for TTS in PowerShell 7 (or is there an alternative)

I have the same profile.ps1 in both WindowsPowerShell and PowerShell. It includes commands that invoke Windows Text-To-Speech However, these commands fail when run in PowerShell 7.

The errors occur when I try to use the $PomrptTTS object I create with the following code:

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

In PowerShell 7, any attempt to access or use my $PormptTTS object, produces the following:

SetValueInvocationException: ....\profile.ps1:82
Line |
  82 |  $PromptTTS.Rate = 0 ; $PromptTTS.Speak("Time for the $((Get-Date).DayofWeek) shuffle")
     |  ~~~~~~~~~~~~~~~~~~~
     | Exception setting "Rate": "Object reference not set to an instance of an object."

MethodInvocationException: ....\profile.ps1:82
Line |
  82 |  … e = 0 ; $PromptTTS.Speak("Time for the $((Get-Date).DayofWeek) shuffle")
     |                                             ~~~~~~~~~~~~~~~~~~~~
     | Exception calling "Speak" with "1" argument(s): "Object reference not set to an instance of an object."

Upvotes: 5

Views: 3169

Answers (3)

Proshanto
Proshanto

Reputation: 1

No, the System.Speech type does work on PowerShell 7.6 preview.0. There's what I did:

Add-Type -AssemblyName System.speech
$PromptTTS = New-Object System.Speech.Synthesis.SpeechSynthesizer
$PromptTTS.Speak("Hello")

(but it does not returns something like in Windows PowerShell)

Upvotes: 0

mklement0
mklement0

Reputation: 439777

As of PowerShell 7.0 / .NET Core 3.1, System.Speech.Synthesis.SpeechSynthesizer is considered a .NET Framework-only API and therefore not supported in .NET Core.

  • A discussion about this is ongoing in this GitHub issue; since the underlying API is specific to Windows, the question is whether it's worth exposing via the cross-platform .NET Core framework.

The workaround is to use the SAPI.SpVoice COM object (which the .NET Framework API is ultimately based on, I presume):

$sp = New-Object -ComObject SAPI.SpVoice
$sp.Speak("Time for the $((Get-Date).DayOfWeek) shuffle")

A related question asks about changing the speaking voice, which, unfortunately doesn't seem to be supported in PowerShell Core as of PowerShell 7.0, due to limited COM support - see this answer.

Upvotes: 9

Luke
Luke

Reputation: 949

mklement0's answer is better, but if you want a slightly hacky Windows 10+ option that works with version 7 (but not version 5) you can use the Windows Media Foundation speech api instead.

Here's a gist that uses this option.

The nice thing about using the Windows Media Foundation is you can use all of the "OneCore" voices that are supported in Windows Narrator, whereas SAPI only supports the three default voices

Upvotes: 1

Related Questions