CS程序和BS程序文字转语音

    一、项目中一直用到了文字转语音的功能,需求也比较简单,就是将一段报警信息通过语音的方式播放出来,之前一直采用CS客户端,利用微软自带的Speech语音播放库就可以完成,

       1.1 封装winSpedk类代码如下:

namespace Speak
{
    using System;
    using System.Runtime.CompilerServices;
    using System.Speech.Synthesis;
    using System.Threading;
    using SpeechLib;

    public class WinSpeak
    {
        #region 属性
        private SpeechSynthesizer Speak;
        public event ErrorInfo ErrorInfoEvent;
        private Thread thVoice;
        private string strVoiceMsg;
        SpVoice Voice = null;
        private static WinSpeak _intence;
        #endregion

        private WinSpeak()
        {
            Voice = new SpVoice();
        }

        #region 方法
        public static WinSpeak _Init()
        {
            if (_intence == null)
                _intence = new WinSpeak();

            return _intence;
        }
        /// <summary>
        /// 读语音
        /// </summary>
        private void SpeakM()
        {
            try
            {
                if (Speak != null)
                {
                    this.Speak.SpeakAsync(strVoiceMsg);
                }
            }
            catch (Exception exception)
            {
                this.ErrInfo(exception);
            }
        }
        /// <summary>
        /// 异步播放文本语音
        /// </summary>
        /// <param name="msg"></param>
        public void BeginSpeakText(string msg)
        {
            try
            {
                if (Speak != null)
                {
                    Speak.SpeakAsyncCancelAll();
                    Speak.Dispose();
                }

                if (thVoice != null && thVoice.ThreadState == ThreadState.Running)
                {
                    thVoice.Abort();
                }

                Speak = new SpeechSynthesizer();
                Speak.SetOutputToDefaultAudioDevice();

                strVoiceMsg = msg;

                //thVoice = new Thread(new ThreadStart(SpeakM));
                //thVoice.Start();
                Speak.SpeakAsync(msg);

                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            catch (Exception exception)
            {
                this.ErrInfo(exception);
            }
        }
        /// <summary>
        /// 播放文本语音
        /// </summary>
        /// <param name="msg"></param>
        public void SpeakText(string msg)
        {
            try
            {
                this.Speak = new SpeechSynthesizer();
                this.Speak.Speak(msg);
                this.Speak.SetOutputToNull();
                this.Speak.Dispose();
            }
            catch (Exception exception)
            {
                this.ErrInfo(exception);
            }
        }
        /// <summary>
        /// Speech播放文本合成语音
        /// </summary>
        /// <param name="msg"></param>
        public void Speech_SpeakText(string msg)
        {
            try
            {
                if (Voice != null)
                {
                    Voice.Speak(null, SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
                    Voice.Speak(msg, SpeechVoiceSpeakFlags.SVSFlagsAsync);
                }
            }
            catch (Exception ex)
            {
                this.ErrInfo(ex);
            }
        }
        /// <summary>
        /// 关闭语音释放资源
        /// </summary>
        public void SpeakClose()
        {
            try
            {
                if (Speak != null)
                {
                    this.Speak.SpeakAsyncCancelAll();
                    this.Speak.Dispose();
                }

                if (Voice != null)
                {
                    Voice.Speak(null, SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
                }
            }
            catch (Exception ex)
            {
                cGlobe_Log.Error(cGlobe_Log.GetMethodInfo() + ex.Message);
            }
        }
        /// <summary>
        /// 获取错误信息
        /// </summary>
        /// <param name="str"></param>
        private void ErrInfo(Exception str)
        {
            if (this.ErrorInfoEvent != null)
            {
                this.ErrorInfoEvent(str);
            }
        }
        #endregion

        ~WinSpeak()
        {
            try
            {
                if (Speak != null)
                {
                    this.Speak.SpeakAsyncCancelAll();
                    this.Speak.Dispose();
                }
            }
            catch (Exception exception)
            {
                //this.ErrInfo(exception);
            }
        }
    }
}
View Code

      1.2  调用如下(一个同步播放、一个异步播放):  

   private void btnTest_Click(object sender, EventArgs e)
        {
            try
            {
                string strSep = txtWord.Text;
                SFBR.WinSpeak._Init().Speech_SpeakText(strSep);
            }
            catch (Exception ex)
            { }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                string strSep = txtWord.Text;
                SFBR.WinSpeak._Init().BeginSpeakText(strSep);
            }
            catch (Exception ex)
            { }
        }
View Code

   二、 最近客户提出需求需要在BS系统实现文字语音播放的功能,因不能接入外网不能调用第三方服务等,最后想到了一个解决方案:先把文字转化为音频文件,再把音频文件以流的形式推送到BS端进行播放;

       2.1  同样可以利用微软自带的Speech语音播放库将一段文本转化为音频文件:

       2.2 封装 SpeechService文字转换音频文件类

    public class SpeechService
    {
        private static SpeechSynthesizer synth = null;
        /// <summary>
        /// 返回一个SpeechSynthesizer对象
        /// </summary>
        /// <returns></returns>
        private static SpeechSynthesizer GetSpeechSynthesizerInstance()
        {
            if (synth == null)
            {
                synth = new SpeechSynthesizer();
            }
            return synth;
        }
        /// <summary>
        /// 保存语音文件
        /// </summary>
        /// <param name="text"></param>
        public static void SaveMp3(string strFileName,string spText)
        {    
            synth = GetSpeechSynthesizerInstance();
            synth.Rate = 1;
            synth.Volume = 100;      
            synth.SetOutputToWaveFile(strFileName);
            synth.Speak(spText);
            synth.SetOutputToNull();
        }  
    }
View Code

       2.3  接下来就是将音频文件以文件流的形式推送到前端播放:

  public async Task<ActionResult> PlayWav(string id,string spText)
        {    
            string strPath = Server.MapPath("~\\MP4\\" + id + ".wav");
            SpeechService.SaveMp3(strPath, spText);
            try
            {     
                using (FileStream fileStream = new FileStream(strPath, FileMode.Open))
                {
                    byte[] fileByte = new byte[fileStream.Length];
                    fileStream.Seek(0, SeekOrigin.Begin);
                    fileStream.Read(fileByte, 0, (int)fileStream.Length);
                    long fSize = fileStream.Length;
                    long startbyte = 0;
                    long endbyte = fSize - 1;
                    int statusCode = 200;
                    if ((Request.Headers["Range"] != null))
                    {
                        //Get the actual byte range from the range header string, and set the starting byte.
                        string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
                        startbyte = Convert.ToInt64(range[1]);
                        if (range.Length > 2 && range[2] != "") endbyte = Convert.ToInt64(range[2]);
                        //If the start byte is not equal to zero, that means the user is requesting partial content.
                        if (startbyte != 0 || endbyte != fSize - 1 || range.Length > 2 && range[2] == "")
                        { statusCode = 206; }//Set the status code of the response to 206 (Partial Content) and add a content range header.                                    
                    }
                    long desSize = endbyte - startbyte + 1;
                    //Headers
                    Response.StatusCode = statusCode;
                    Response.ContentType = "audio/mpeg";
                    Response.AddHeader("Content-Accept", Response.ContentType);
                    Response.AddHeader("Content-Length", desSize.ToString());
                    Response.AddHeader("Content-Range", string.Format("bytes {0}-{1}/{2}", startbyte, endbyte, fSize));
                    return File(fileByte, Response.ContentType);
               
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
View Code

    注意:返回的必须为异步( async Task)不然会报错,因为文字音频转换涉及到异步调用

       2.4 前端展示

   

       2.5  运行截图如下:

 BS实现文字音频调用demo地址如下:

  https://github.com/lxshwyan/SpeechBSDemo.git

 

posted @ 2019-07-15 12:41 lxsh_wyan 阅读(...) 评论(...) 编辑 收藏