回顧上次寫博客至今都有4個多月了,最近工作比較的忙沒時間寫博文。以後會多堅持寫博文,與大家分享下最近遇到的問題。最近因為項目需要,研究了下用C#開發TTS。下面把大體的思路給大家說說,希望對大家有所幫助。
首先需要了解下MS的SAPI,它是微軟的語音API。它包括了語音識別SR引擎和語音合成SS引擎兩種語音引擎。等下會給大家看下語音合成SS引擎。它由不同的版本,操作系統的不同使用的版本不同,不過我喜歡使用其他的合成語音包,比如:NeoSpeech公司的合成語音包。回過頭來,MS 的SAPI的版本有:5.1、5.3和5.4。具體用途如下:
1. Windows Speech SDK 5.1版本支持xp系統和server 2003系統,需要下載安裝。XP系統默認只帶了個Microsoft Sam英文男聲語音庫,想要中文引擎就需要安裝Windows Speech SDK 5.1。下載地址:http://www.microsoft.com/download/en/details.aspx?id=10121
2. Windows Speech SDK 5.3版本支持Vista系統和Server 2008系統,已經集成到系統裡。Vista和Server 2003默認帶Microsoft lili中文女聲語音庫和Microsoft Anna英文女聲語音庫。
3. Windows Speech SDK 5.4版本支持Windows7系統,也已經集成到系統裡,不需要下載安裝。Win7系統同樣帶了Microsoft lili中文女聲語音庫和Microsoft Anna英文女聲語音庫。Microsoft lili支持中英文混讀。
到這裡環境就准備好了,接下來講訴下開發TTS要用到的類,我使用的是.net類庫提供的語音類System.Speech.Synthesis.SpeechSynthesizer,使用前需要添加引用:System.Speech。該類的主要方法、屬性、事件如下:
方法:
GetInstalledVoices():獲取當前系統中安裝的語音播放人,返回一個VoiceInfo對象集合,具體的對象有在控制面板中,語音項可以查看。Xp默認是Microsoft Sam。
SelectVoice(string):選擇當前朗讀的人員,參數是朗讀者名稱,如:Microsoft Sam
SpeakAsync(string):開始進行異步朗讀,參數是朗讀的文本。
Speak(string):開始進行朗讀,參數是朗讀的文本。這裡我沒有弄懂SpeakAsync和Speak的區別,我試了下效果都一樣。
Pause():暫停正在播放朗讀。
Resume():繼續播放暫停的朗讀。
SetOutputToWaveFile(string):保存語音文件,調用該方法後需要調用Speak方法。參數是保存文件的路徑。如:d:/124.wav或d:/123.MP3
SetOutputToNull():保存文件結束語句,必須調用該語句,否則生產的語音文件無法播放。
屬性:
Rate:播放語速,-10~10
Volume:音量調節:0~100
Voice:正在使用某個人員播放,返回:VoiceInfo對象。
事件:
SpeakCompleted:朗讀完成事件,朗讀完成後會觸發該時間。可以在該事件中處理播放完成後的流程。
SpeakStarted:朗讀開始事件。
SpeakProgress:朗讀過程事件,可以繼續一些進度條處理。
。。。。
其他屬性、方法、事件用得少就不多講了,自己看下API就知道了。有什麼問題可以給我留言,我們共同探討。界面如下:
還是把代碼貼上來吧,主要代碼如下:
private SpeechSynthesizer synth = null;//語音對象
/// <summary>
/// 返回一個SpeechSynthesizer對象
/// </summary>
/// <returns></returns>
private SpeechSynthesizer GetSpeechSynthesizerInstance()
{
if (synth == null)
{
synth = new SpeechSynthesizer();
}
return synth;
}
/// <summary>
/// 獲得朗讀設置對象
/// </summary>
/// <returns></returns>
private VoiceClass GetVoiceClass()
{
VoiceClass setViceClass = new VoiceClass();
setViceClass.VoiceName = cboTokens.Text;
setViceClass.Rate = int.Parse(cboSpeed.Text);
setViceClass.Volume = tbVoice.Value;
setViceClass.VoiceText = txtInput.Text;
return setViceClass;
}
/// <summary>
/// 播放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnGo_Click(object sender, EventArgs e)
{
if (IsVaild())
{
VoiceClass setViceClass = GetVoiceClass();//VoiceClass 是自己建立的一個類,裡面封轉了語速 音量 播放人 播放文本
Thread thread = new Thread(RingVoice);
thread.Start(setViceClass);
}
}
/// <summary>
/// 開始朗讀 放在線程中
/// </summary>
/// <param name="VoiceObject"></param>
public void RingVoice(object VoiceObject)
{
try
{
VoiceClass voiceClass = (VoiceClass)VoiceObject;
synth = GetSpeechSynthesizerInstance();
synth.SelectVoice(voiceClass.VoiceName);
synth.Rate = voiceClass.Rate;
synth.Volume = voiceClass.Volume;
synth.SpeakAsync(voiceClass.VoiceText);
}
catch (Exception er)
{
MessageBox.Show(er.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 保存
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSave_Click(object sender, EventArgs e)
{
if (IsVaild())
{
synth = GetSpeechSynthesizerInstance();
VoiceClass voiceClass = GetVoiceClass();
synth.SelectVoice(voiceClass.VoiceName);
synth.Rate = voiceClass.Rate;
synth.Volume = voiceClass.Volume;
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Title = "保存文檔";
saveFileDialog.Filter = "*.wav|*.wav|*.mp3|*.mp3";
saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
DialogResult saveDialog = saveFileDialog.ShowDialog();
try
{
if (saveDialog == System.Windows.Forms.DialogResult.OK)
{
synth.SetOutputToWaveFile(saveFileDialog.FileName);
synth.Speak(voiceClass.VoiceText);
synth.SetOutputToNull();
System.Diagnostics.Process.Start("Explorer.exe", string.Format(@"/select,{0}", saveFileDialog.FileName));//打開wav目錄並選中文件
}
}
catch (Exception er)
{
MessageBox.Show(er.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
/// <summary>
/// 繼續
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnContinum_Click(object sender, EventArgs e)
{
synth.Resume();
}
/// <summary>
/// 暫停
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStop_Click(object sender, EventArgs e)
{
synth.Pause();
}
有個問題,不知道是什麼原因,要播放的內容:歡迎致電12345客服服務系統,它把12345給我朗讀成:1萬2千3百4十五。這個問題還在解決中,誰知道麻煩給我留下言,謝謝。