如何停止SAPI.SpVoice读取“是”。作为“岛屿”?

时间:2014-01-16 23:40:00

标签: text-to-speech sapi

您可以配置SAPI.spVoice读取文本的方式吗?

在我的情况下,我正在使用AutoHotKey脚本读取当前剪贴板。 该脚本对SAPI.spVoice进行COM调用,从剪贴板传递文本。

;;;;;;;;;;;;;;;;;;;;TTS;;;;;;;;;;;;;;;;;;;;;;
#^!D:: ; Win + Ctrl + D + Alt 
ClipSaved := ClipboardAll   
clipboard = ; Start off empty to allow ClipWait to detect when the text has arrived.
Send ^c
ClipWait  ; Wait for the clipboard to contain text.
ComObjCreate("SAPI.SpVoice").Speak(clipboard)
Clipboard := ClipSaved 
ClipSaved = ; Free the memory 
return 

问题是...... SAPI错误地读取了一些文本。

例如:

  • “是的。我们很复杂。”读“是”。如岛,
  • “是的。这很复杂。”正确阅读。

您可以通过执行以下操作来尝试此操作:

如果您正在运行Windows 7.

  • 按下Windows键并输入“更改文字到语音设置”并选择选项。
  • 在此对话框中输入“是的。我们很复杂。”在“使用以下文本预览语音:”字段中。
  • 按“预览语音”
  • 听到它读“是”。如岛。

所以......我的问题是......

是否可以更改/配置“Microsoft Anna”读取文本的方式,以免出错?

这只是安娜声音中的错误还是所有声音?

如何让它以我想要的方式阅读文本?

2 个答案:

答案 0 :(得分:1)

这是由SAPI的文本规范化代码完成的。不幸的是,如果不构建自定义语音,这很难修改,这可能比你想要实现的工作要多得多。

答案 1 :(得分:1)

"每个问题(间接层次太多的问题除外)都可以通过另一个间接层解决。"

SAPI.spVoice对象可以传递文本(就像我正在做的那样)或SSML。

通过接受说出的文本,然后将其转换为SSML,您可以控制单词的说话方式。您有机会预处理文本并用您希望的特定发音替换未读单词。

例如:&#34;是的。我们很复杂。&#34;成为&#34; Yes it <sub alias="is">is</sub>. Ours is complex.&#34;

subsay_as似乎有效。 phoneme似乎被忽略了......但我可能错误地配置了一些东西。

注意:如果您希望XML朗读,XML会在将文本转换为SSML之前对其进行转义,否则将假定它是SSML的一部分。

所以...代码:

;;;;;;;;;;;;;;;;;;;;TTS;;;;;;;;;;;;;;;;;;;;;;
#^D:: ; Win + Ctrl + D 
ClipSaved := ClipboardAll   
Clipboard = ; Start off empty to allow ClipWait to detect when the text has arrived.
Send ^c
ClipWait  ; Wait for the clipboard to contain text.
FileDelete , c:\tmp\tmp_ahk_tts_clip.txt
FileAppend , %Clipboard% , c:\tmp\tmp_ahk_tts_clip.txt
RunWait, %comspec% /c ""F:\bin\tools\speakit.rb" c:\tmp\tmp_ahk_tts_clip.txt > c:\tmp\tmp_ahk_clip_tts_out.txt" ,,Hide
FileRead, Clipboard, c:\tmp\tmp_ahk_clip_tts_out.txt
ComObjCreate("SAPI.SpVoice").Speak(Clipboard)
Clipboard := ClipSaved 
ClipSaved = ; Free the memory 
return 

F:\bin\tools\speakit.rb有点像这样:

#!/usr/bin/env ruby
substitutions = [
[/[A-Z][A-Z][A-Z][A-Z]+((?=[^A-Za-z])|(?!.))/, lambda{|x|x.downcase}], #All caps becomes word
[/\.exe(?=[^a-z])/i, " executable "],
[/\.txt(?=[^a-z])/i, " text file "],
[/rebranded/, "re-branded"],
[/App(?=[\s\.])/, " application "],
['GUI' , " gooee "],
[/localhost/, "local host"],
[/(?<word>[A-Z][a-z]*)(?=[A-Z ,\.;:\t\/])/, "'\\k<word>' "], # CamelCaseWords should be split by spaces
['\\', '<sub alias="slash">\\</sub>'],
]


require 'cgi'

puts <<-eos
<?xml version="1.0"?>
<speak xmlns="http://www.w3.org/2001/10/synthesis" version="1.0" xml:lang="en-UK">
<voice xml:lang="en-UK">
   #{substitutions.reduce(CGI::escapeHTML(ARGF.read)){|o, (r,s)| s.is_a?(Proc) ? o.gsub(r, &s) : o.gsub(r,s) }}
</voice>
</speak>
eos