C#文本转语音并保存wav和MP3文件


       最近因为项目需要,研究了下用C#开发TTS。下面把大体的思路给大家说说,希望对大家有所帮助。

  首先需要了解下MSSAPI,它是微软的语音API。它包括了语音识别SR引擎和语音合成SS引擎两种语音引擎。等下会给大家看下语音合成SS引擎。它由不同的版本,操作系统的不同使用的版本不同,不过我喜欢使用其他的合成语音包,比如:NeoSpeech公司的合成语音包。我们继续后面的内容,MS SAPI的版本有:5.15.35.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系统,已经集成到系统里。VistaServer 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

  SelectVoicestring):选择当前朗读的人员,参数是朗读者名称,如:Microsoft Sam

  SpeakAsyncstring):开始进行异步朗读,参数是朗读的文本。

  Speakstring):开始进行同步朗读,参数是朗读的文本。

  Pause():暂停正在播放朗读。

  Resume():继续播放暂停的朗读。

  SetOutputToWaveFile(string):保存语音文件,调用该方法后需要调用Speak方法。参数是保存文件的路径。如:d:/124.wavd:/123.MP3

  SetOutputToNull():保存文件结束语句,不调用该语句,在程序关闭之前生产的语音文件无法播放。

  属性:

  Rate:播放语速,-10~10

  Volume:音量调节:0~100

  Voice:正在使用某个人员播放,返回:VoiceInfo对象。

  事件:

  SpeakCompleted:朗读完成事件,朗读完成后会触发该时间。可以在该事件中处理播放完成后的流程。

  SpeakStarted:朗读开始事件。

  SpeakProgress:朗读过程事件,可以继续一些进度条处理。

  。。。。

其他属性、方法、事件用得少就不多讲了,自己看下API就知道了。有什么问题可以给我留言,我们共同探讨。界面如下:

 

主要代码如下:

SpeechSynthesizer  reader = new SpeechSynthesizer();

 

        //基础数据初始化

        public void dataInit() {

 

            foreach (InstalledVoice voice in reader.GetInstalledVoices())

            {

                VoiceInfo info = voice.VoiceInfo;

                cmbVoiceType.Items.Add(info.Name);

            }

 

            cmbVoiceGender.SelectedIndex = 0;

        }

       

        //阅读按钮单击事件方法

         private void btnRead_Click(object sender, EventArgs e)

            {

 

                tbRate.Visible = false;

                if (RtxtWords.TextLength == 0) {

                    MessageBox.Show("请输入要阅读或转换的文字内容!", "提示");

                    return;

                }

                

             //开始将文本转换成语音并播放

                text_reader();

            }

        

        //文本成语音方法

        public void text_reader()

        {

            reader.Volume = 100;//设置音量(默认就是100

            //判断阅读的状态

            if (reader.State == SynthesizerState.Ready)

            {

                //PromptBuilder pb = new PromptBuilder();

                btnRead.Visible = false;

                reader.Rate = int.Parse(txbRate.Text);//获取语速设置

                //处理语音库下拉选择的值

                if (cmbVoiceType.SelectedIndex >= 0)

                {

                    reader.SelectVoice(cmbVoiceType.Text);

                }

 

                //处理性别下拉选择的值(男性 Male, 女性 Female,中性 Neutral,未设置 NotSet

                if (cmbVoiceGender.SelectedIndex == 1)

                {

                    reader.SelectVoiceByHints(VoiceGender.Male);

                }

                else if (cmbVoiceGender.SelectedIndex == 2)

                {

                    reader.SelectVoiceByHints(VoiceGender.Female);

                }

                else if (cmbVoiceGender.SelectedIndex == 3)

                {

                    reader.SelectVoiceByHints(VoiceGender.Neutral);

                }

                else

                {

                    reader.SelectVoiceByHints(VoiceGender.NotSet);

                }

                //开始异步阅读

                reader.SpeakAsync(RtxtWords.Text);

            }

            else {

                MessageBox.Show("阅读引擎正在工作或者还未准备好!", "提示");

            }

            //激活阅读过程事件

            reader.SpeakProgress += new EventHandler<SpeakProgressEventArgs>(reader_SpeakProgress);

            //激活阅读开始事件

            reader.SpeakStarted += new EventHandler<SpeakStartedEventArgs>(speak_SpeakStarted);

            //激活阅读完成事件

            reader.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(speak_SpeakCompleted);

        }

        //阅读过程事件

        void reader_SpeakProgress(object sender, SpeakProgressEventArgs e)

        {

 

            this.RtxtWords.HideSelection = false;

            this.RtxtWords.Select(0, e.CharacterPosition + e.CharacterCount);//自动选择已经阅读的文本

        }

        //阅读开始事件

        void speak_SpeakStarted(object sender, SpeakStartedEventArgs e)

        {

            btnRead.Visible = false;

        }

        //阅读完成事件

        void speak_SpeakCompleted(object sender, SpeakCompletedEventArgs e)

        {

            btnRead.Visible = true;

           

        }

 

        //阅读暂停/继续事件

        private void btnPause_Click(object sender, EventArgs e)

        {

            tbRate.Visible = false;

            if (reader.State == SynthesizerState.Speaking)

            {

                reader.Pause();//阅读暂停

                btnPause.Text = "继续";

            }

            else if (reader.State == SynthesizerState.Paused)

            {

                reader.Resume();//阅读继续

                btnPause.Text = "暂停";

            }

        }

 

       //浏览按钮事件

        private void btnBrow_Click(object sender, EventArgs e)

        {

            tbRate.Visible = false;

 

            saveFile.Filter = "Mp3(*.mp3)|*.mp3|Wav(*.wav)|*.wav";//设置保存的文件类型下拉选择

            saveFile.ShowDialog();//显示SaveFileDialog窗口

            saveFile.AddExtension = true;//自动在文件名中加扩展名

            FilePath.Text=saveFile.FileName;//将文件路径显示在输入路径文本框中

        }

 

        //转换按钮事件

        private void btnSave_Click(object sender, EventArgs e)

        {

            if (string.IsNullOrEmpty(FilePath.Text)) {

                MessageBox.Show("请指定文件路径及文件名!");

                return;

            }

 

            //判断文件已存在询问是否覆盖

            if (System.IO.File.Exists(FilePath.Text))

            {

                DialogResult result = MessageBox.Show("文件名已在是否覆盖保存?", "提示", MessageBoxButtons.OKCancel);

                if (result != DialogResult.OK)

                {

                    return;

                }

            }

            //输出文件

            reader.SetOutputToWaveFile(FilePath.Text);//指定输出的文件路径及名称

            reader.SpeakAsync(RtxtWords.Text);//开始输出文件

            MessageBox.Show("文件生成成功!");

        }

 

        //语速标尺变化事件

        private void tbRate_Changed(object sender, EventArgs e)

        {

            txbRate.Text = tbRate.Value.ToString();//显示当前的语速值

            RtxtWords.Focus();

        }

 

        //速标尺鼠标放开事件

        private void tbRate_MouseUp(object sender, MouseEventArgs e)

        {

            tbRate.Visible = false;//隐藏语速标尺

        }

 

        //设置语速事件

        private void txbRate_Click(object sender, EventArgs e)

        {

            tbRate.Visible = true;//显示语速标尺

        }

 

        //语音标尺滑动事件

        private void tbRate_Scroll(object sender, EventArgs e)

        {

            txbRate.Text = tbRate.Value.ToString();//显示当前的语速值

        }

 

 

有兴趣的朋友可以到以下地址下载完整的代码:https://pan.baidu.com/s/1a5IznXZdhG-fYhsn7zr-xQ

欢迎朋友们在留言区批语指正。