欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-14 17:26:30
一、项目中一直用到了文字转语音的功能,需求也比较简单,就是将一段报警信息通过语音的方式播放出来,之前一直采用CS客户端,利用微软自带的Speech语音播放库就可以完成, 1.1 封装winSpedk类代码如下: namespace Speak { using System; using System ......

    一、项目中一直用到了文字转语音的功能,需求也比较简单,就是将一段报警信息通过语音的方式播放出来,之前一直采用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);
            }
        }
    }
}

      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)
            { }
        }

   二、 最近客户提出需求需要在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();
        }  
    }

       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;
            }
        }

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

       2.4 前端展示

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

       2.5  运行截图如下:

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

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

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