Как изменить голос, используемый для SAPI.SPVoice - PullRequest
1 голос
/ 26 апреля 2020

Я хотел бы иметь возможность выбрать альтернативный голос для вывода текста в речь.
Я использую ComObject SAPI.SPVoice, но обнаружил, что не могу изменить реальный используемый голос.
(Кстати, я использую SAPI.SPVoice, потому что он работает как в PowerShell Core, так и в PowerShell Desktop на 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();

Мои исследования показывают, что я должен быть в состоянии:

❯ $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")

и так далее.

Однако, хотя команды выполняются без ошибок, используемый / услышанный голос не изменяется.

1 Ответ

3 голосов
/ 26 апреля 2020

К сожалению, присвоение .Voice для изменения голоса не не работает в PowerShell Core, начиная с v7.1.0-preview.2 - работает только в Windows PowerShell (версии PowerShell до v5.1).

. NET COM-ядро Core поддержка ограничена, и хотя PowerShell (Core) частично компенсирует это, есть вещи, которые все еще не работают.

В действительности следующее назначение спокойно игнорируется в PowerShell (Core). ) 6 +:

# !! IGNORED in PowerShell [Core] 6+ - the default voice (David)
# !! is NOT changed (to Hedda).
$PromptTTS.Voice = $PromptTTS.GetVoices().Item(1)

Лично я не знаю обходного пути (по крайней мере, с одним только кодом PowerShell).


Техническая информация :

Проверка свойства .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 подозревают , что часть set by ref является проблемой, которая может связано со следующей проблемой, цитируемой из этой проблемы GitHub :

ComBinder не поддерживается в. NET Core (cal l ComInterop.ComBinder.TryBindSetMember в PowerShell Core - метод заглушки ).

...