我希望能够为我的“文字转语音”输出选择其他语音。我正在使用ComObject SAPI.SPVoice,但发现无法更改实际使用的声音。(顺便说一句-我使用的是SAPI.SPVoice,因为它在Windows 10上的PowerShell Core和PowerShell桌面上均可工作)
${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();
我的研究表明我应该能够:
❯ $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")
依此类推。
但是,尽管命令执行没有错误,但所用的声音/听到的不会改变。
不幸的是,分配给 .Voice
在PowerShell Core中(仅在Windows PowerShell中有效)。[>。NET Core对COM的支持是有限的,尽管PowerShell(Core)在某种程度上可以弥补这一点,但是有些事情仍然无法正常工作。
实际上,在PowerShell(Core)6+中,以下分配<
# !! IGNORED in PowerShell [Core] 6+
$PromptTTS.Voice = $PromptTTS.GetVoices().Item(1)
技术背景:
用.Voice
检查$PromptTTS | Get-Member Voice
属性产生:
TypeName: System.__ComObject#{269316d8-57bd-11d2-9eee-00c04f797396}
Name MemberType Definition
---- ---------- ----------
Voice Property ISpeechObjectToken Voice () {get} {set by ref}
I
怀疑。NET Core中不支持set by ref
部分是问题,可能
与以下问题有关,引用为from this GitHub issue:
ComBinder
(PowerShell Core ComInterop.ComBinder.TryBindSetMember
中的调用is a stub method)。