最近经常和外国友人网上聊天,可惜我外语很蹩脚,只能通过翻译软件和他们交流。但是我外语听说读写中的听力很强,英语和日语基本能听懂。在这种情况下我希望有一种便捷的方式来直接朗读我选中的外文文本。
我最先考虑的是Google翻译的API,但是碍于资料太少只好作罢。之后我找到Microsoft Speech,相较于其他一些方案配置简单而且资料丰富,也不用科学上网,采用!
我的目标是这样,选中文本后使用BackupSupport的辅助菜单调用一个程式按指定语言朗读。
为了应对一些焦点转移问题,当没有选中文本时,直接朗读剪切板中的内容。
动工前首先需要安装MicrosoftSpeechPlatformSDK和MSSpeech TTS来配置开发环境和运行环境,这方面直接Microsoft官网搜一下就好了,多说无益。
配置完环境后先写一个MSSpeech的包装类,直接放代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SpeechLib;
using ZTools;
namespace MSSpeechTest {
public class MSSpeechTools {
///
/// 获取安装的所有的Voice的Id列表
///
///
public static List<string> GetInstalledVoiceIdList() {
List<string> resultList = new List<string>();
try {
SpVoice voice = new SpVoice();
ISpeechObjectTokens ss = voice.GetVoices(string.Empty, string.Empty);
if (ss != null && ss.Count > 0) {
for (int i = 0; i < ss.Count; i++) {
resultList.Add(ss.Item(i).Id);
}
}
} catch (Exception) {
}
return resultList;
}
///
/// 根据指定Voice Tag选择Voice朗读文本
/// 会简单进行Voice名的匹配
///
/// 朗读的文本
/// 指定Voice Tag
///
public static void Speak(string text, string voiceTag, SpeechVoiceSpeakFlags flag = SpeechVoiceSpeakFlags.SVSFDefault) {
int index = 0;
if (voiceTag != null && voiceTag.Length > 0) {
try {
SpVoice voice = new SpVoice();
ISpeechObjectTokens ss = voice.GetVoices(string.Empty, string.Empty);
if (ss != null && ss.Count > 0) {
//匹配1
for (int i = 0; i < ss.Count; i++) {
SpObjectToken token = ss.Item(i);
//获取Id的最后一段
string temp = FileTools.GetFileName(token.Id);
if (temp.ToUpper().IndexOf(voiceTag.ToUpper()) >= 0) {
index = i;
break;
}
}
if (index == 0) {
//匹配2
for (int i = 0; i < ss.Count; i++) {
SpObjectToken token = ss.Item(i);
if (token.Id.ToUpper().IndexOf(voiceTag.ToUpper()) >= 0) {
index = i;
break;
}
}
}
}
} catch (Exception) {
}
}
Speak(text, index, flag);
}
///
/// 根据指定Voice Index选择Voice朗读文本
///
/// 朗读的文本
/// Voice Index
///
public static void Speak(string text, int index, SpeechVoiceSpeakFlags flag = SpeechVoiceSpeakFlags.SVSFDefault) {
try {
SpVoice voice = new SpVoice();
voice.Voice = voice.GetVoices(string.Empty, string.Empty).Item(index);
voice.Speak(text, flag);
} catch (Exception) {
}
}
///
/// 异步朗读
///
///
///
public static void SpeakAsync(string text, int index) {
Speak(text, index, SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
///
/// 异步朗读
///
///
///
public static void SpeakAsync(string text, string tag) {
Speak(text, tag, SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
}
}
MSSpeech的需要功能包装完毕,接下来做个UI界面测试一下。
测试没问题,接下来绑定几个命令行参数,做个启动器。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics;
using SpeechLib;
using ZTools;
namespace MSSpeechTest {
class Program {
[STAThread]
static void Main(string[] args) {
//关闭之前运行的语音朗读
Process[] process = Process.GetProcessesByName("MSSpeechTest");
if (process.Length > 0) {
for (int i = 0; i < process.Length; i++) {
if (process[i].Id != Process.GetCurrentProcess().Id) {
try {
process[i].Kill();
} catch (Exception) {
}
}
}
}
int index = 0;
string tag = null;
string content = "";
if (args.Length > 0) {
//读取命令行参数
for (int i = 0; i < args.Length; i++) {
if (args[i].TrimStart().ToLower().IndexOf("/i:") == 0) {
KeyValuePair<string, string> tv = ConfigTools.ConvertStringToTagValue(args[i]);
index = NumericConvertTools.ConvertToInteger(tv.Value);
} else if (args[i].TrimStart().ToLower().IndexOf("/tag:") == 0) {
KeyValuePair<string, string> tv = ConfigTools.ConvertStringToTagValue(args[i]);
tag = tv.Value;
} else {
content += args[i];
}
}
//获取需要朗读的文本
if (content.Length == 0) {
string temp = ClipboardTools.GetText();
SendKeys.SendWait("^c");
SendKeys.SendWait("^c");
SendKeys.SendWait("^c");
Thread.Sleep(100);
string temp2 = ClipboardTools.GetText();
if (temp2 == null || temp2.Length < 0) {
content = temp;
ClipboardTools.SetText(temp);
} else {
content = temp2;
ClipboardTools.SetText(temp);
}
}
//调用MSSpeech工具朗读文本
if (content != null && content.Length > 0) {
if (tag != null && tag.Length > 0) {
MSSpeechTools.Speak(content, tag);
} else {
MSSpeechTools.Speak(content, index);
}
}
} else {
Application.Run(new VoiceSelectForm());
}
}
}
}
由于BackupSupport的辅助菜单没有参数设定的功能,所以还需要脚本来调用朗读程式。
这里我使用VBS作为启动脚本。
里面差不多是这样,只是带参数地调用一下
Set ws = CreateObject("Wscript.Shell")
var = "/tag:jp"
ws.run """D:\Program Files (x86)\BackupSupporter\msspeech_test\MSSpeechTest.exe""" & var, 0
最后和BackupSupport的辅助菜单绑定一下就完成了
使用的一些效果视频和BackupSupport的配置见twitter:@photonaaa。
为了避免可能碰到的问题,我直接把这个功能做到BackupSupport里了,版本是1.4.2。
效果差不多是这样,避免了启动脚本
配置的时候,打开MSSpeechTrigger.exe点上面的链接把Runtime和Runtime Languages的安装包下载来安装一下就行了。