I would like to be able to select an alternative voice for my Text-To-Speech output.
I am using the ComObject SAPI.SPVoice but I am finding that I cannot change the actual voice used.
(BTW - I am using SAPI.SPVoice because it works in both PowerShell Core and PowerShell Desktop on Windows 10)
${PromptTTS} = New-Object -ComObject SAPI.SPVoice
❯ $PromptTTS | gm
TypeName: System.__ComObject#{269316d8-57bd-11d2-9eee-00c04f797396}
Name MemberType Definition
---- ---------- ----------
DisplayUI Method void DisplayUI (int hWndParent, string Title, string TypeOfUI, Variant ExtraData)
GetAudioOutputs Method ISpeechObjectTokens GetAudioOutputs (string RequiredAttributes, string OptionalAttributes)
GetVoices Method ISpeechObjectTokens GetVoices (string RequiredAttributes, string OptionalAttributes)
IsUISupported Method bool IsUISupported (string TypeOfUI, Variant ExtraData)
Pause Method void Pause ()
Resume Method void Resume ()
Skip Method int Skip (string Type, int NumItems)
Speak Method int Speak (string Text, SpeechVoiceSpeakFlags Flags)
SpeakCompleteEvent Method int SpeakCompleteEvent ()
SpeakStream Method int SpeakStream (ISpeechBaseStream Stream, SpeechVoiceSpeakFlags Flags)
WaitUntilDone Method bool WaitUntilDone (int msTimeout)
AlertBoundary Property SpeechVoiceEvents AlertBoundary () {get} {set}
AllowAudioOutputFormatChangesOnNextSet Property bool AllowAudioOutputFormatChangesOnNextSet () {get} {set}
AudioOutput Property ISpeechObjectToken AudioOutput () {get} {set by ref}
AudioOutputStream Property ISpeechBaseStream AudioOutputStream () {get} {set by ref}
EventInterests Property SpeechVoiceEvents EventInterests () {get} {set}
Priority Property SpeechVoicePriority Priority () {get} {set}
Rate Property int Rate () {get} {set}
Status Property ISpeechVoiceStatus Status () {get}
SynchronousSpeakTimeout Property int SynchronousSpeakTimeout () {get} {set}
Voice Property ISpeechObjectToken Voice () {get} {set by ref}
Volume Property int Volume () {get} {set}
queryMSDNClassInfo ScriptMethod System.Object queryMSDNClassInfo();
My research indicates that I should be able to:
❯ $PromptTTS.Voice = ${PromptTTS}.GetVoices().Item(0) ; $PromptTTS.Speak("Hello voice 0")
❯ $PromptTTS.Voice = ${PromptTTS}.GetVoices().Item(1) ; $PromptTTS.Speak("Hello voice 1")
❯ $PromptTTS.Voice = ${PromptTTS}.GetVoices().Item(2) ; $PromptTTS.Speak("Hello voice 2")
and so on.
However, whilst the commands execute without error, the voice used /heard does not change.
$PromptTTS.GetVoices()
? – Dichlorodiphenyltrichloroethane