C#-Websocket应用语音合成实战 如何开发一个在线朗读的功能----科大讯飞语音合成实战

如何开发一个在线朗读的功能----科大讯飞语音合成实战

起因

天天学习强国,不过强国APP的语音朗读不错,了解之后是科大讯飞支持的,于是开始撸码。https://www.xfyun.cn/doc/tts/online_tts/API.html

注册为开发者,接口要求这些我就不赘述了,文档里面写的清楚。当然具体实现是另外一回事。

听了一下效果,怎么说呢,免费的和特色的还是有很大的差别的,免费的是刚好让你能忍的那个级别,特色的和真人差别不大。看了一下收费,分为两部分,一部分是接口费用,一部分是特色发音人的费用。基于撸码的习惯,一切先从免费开始。

  详情请看这里:https://www.xfyun.cn/services/online_tts

 开干

看了一圈没有C#的demo,这就尴尬了,虽然是有文档,但是大家都懂,好比微信公众号的开发文档,要变成实际的代码,看得见的应用那是要废一番功夫的。找了一番之后,终于发现一个开源的项目刚发布没多久,真是喜出望外就开干了: https://github.com/zuiyuewentian/XunFeiNETSDK

讯飞的这个接口是基于websock的,我们先用控制台程序做一个demo。C#其实自带了websocket,不过这里用的是WebSocketSharp,这个我觉得很好,System.Net.WebSockets.WebSocket 是基于异步方法的,后面我会讲到,而WebSocketSharp.WebSocket 是基于事件的,很符合前端的编程习惯。

扫描二维码关注公众号,回复: 11141544 查看本文章
websocket = new WebSocketSharp.WebSocket(reqUrl);
                websocket.OnMessage += Websocket_OnMessage;
                websocket.OnOpen += Websocket_OnOpen;
                websocket.Connect();

讯飞的服务器收到我们的文字内容后,会以流的形势把音频传回来,在我们的服务器上把这种流转成文件即可。

复制代码
 private static Stopwatch stopwatch;
        public static void Main(string[] args)
        {
            //text要合成的文字,pathUrl域名
            stopwatch = new Stopwatch();
            stopwatch.Start();
            var xunFeiNetSdk = new XunFeiTTS();
            xunFeiNetSdk.MessageUpdate_Event += XunFeiNetSdk_MessageUpdate_Event;
            xunFeiNetSdk.SendData("张家界荷花国际机场,北京大兴机场,长沙黄花机场,邵阳武冈机场,所有航班全部复航!");
            Console.Read();
        }

        static byte[] data = new byte[0];
        private static void XunFeiNetSdk_MessageUpdate_Event(TTS_Data_Model message, string error = null)
        {

            if (error != null)
            {
                Console.WriteLine(error);
                return;
            }

            try
            {
                //合成结束
                if (message.status == 2)
                {
                    Console.WriteLine("合成成功");
                    string voice = string.Format("{0}.wav", DateTime.Now.ToString("yyyyMMddHHmmssfff"));

                    Console.WriteLine("正在保存..."+voice);
                    
                    data = data.Concat(message.audioStream).ToArray();

                    var mWavWriter = new WaveFileWriter(voice, new WaveFormat(16000, 1));
                    mWavWriter.Write(data, 0, data.Length);
                    mWavWriter.Close();
                    mWavWriter.Dispose();
                    Console.WriteLine("保存成功...");
                    var sp = stopwatch.Elapsed;

                    Console.WriteLine("用时" + sp);


                }
                else
                {
                    data = data.Concat(message.audioStream).ToArray();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

    }
复制代码

文件的存储用的是NAudio,XunFeiNETSDK里面的代码我独立出来。

(最近2个月航班太少了,工资骤减,原谅我说出我的内心话) 

这样就得到了语音了。听一听,还能接受。但是怎么做到web页面里面呢?

改造成web应用

首先的思路是,前端把文字发过来,然后交给sdk去获取音频,得到文件的地址后返回给前端。所以最合适的方案还是前端也用websocket,因为发送消息和收到消息是分开的。那么这又需要后端有一个websocket服务了

 

我又不想单独去开一个websocket服务,那就可以将这个websocket做成api的形式,如下:

  View Code
复制代码
 var webSocket;
        var player = document.getElementById("player");
        function sendSocketMsg() {
            var msg = $("#msg").val();
            webSocket.send(msg);
            showMsg("发送消息:" + msg, "blue");
        }

        openSocket();

        function openSocket() {
            if (webSocket != null && typeof (webSocket) != "undefined") {
                closeSocket();
            }
            webSocket = new WebSocket("ws://" + location.hostname + ":" + location.port + "/api/msg");
            webSocket.onopen = function () {
                showMsg("连接建立");
            }
            webSocket.onerror = function () {
                showMsg("发生异常");
            }

            webSocket.onmessage = function (event) {
                showMsg("收到消息:" + event.data, "yellow");
                if (event.data.indexOf("voice:") > -1) {
                    var src = event.data.split("voice:")[1];
                    player.src = src;
                    player.play();
                }
            }

            webSocket.onclose = function () {
                showMsg("连接关闭");
            }
        }

        function closeSocket() {
            if (webSocket != null && typeof (webSocket) != "undefined") {
                webSocket.close();
            }
        }

        function showMsg(msg, type) {
            if (type === null || typeof (type) === "undefined") type = "gray";
            $("#show").append("<span class='" + type + "'>" + msg + "</span><br>");
        }
复制代码

这样就得到产品的雏形了。后续要考虑的是文字的长短、音频播放器的展示效果,还能换一下播放的声音等等,每次给你说一个功能,其实这个功能背后有太多细节了。

 Console版源码:https://download.csdn.net/download/stoneniqiu/12347028 

 Web版源码:https://download.csdn.net/download/stoneniqiu/12347167 

起因

天天学习强国,不过强国APP的语音朗读不错,了解之后是科大讯飞支持的,于是开始撸码。https://www.xfyun.cn/doc/tts/online_tts/API.html

注册为开发者,接口要求这些我就不赘述了,文档里面写的清楚。当然具体实现是另外一回事。

听了一下效果,怎么说呢,免费的和特色的还是有很大的差别的,免费的是刚好让你能忍的那个级别,特色的和真人差别不大。看了一下收费,分为两部分,一部分是接口费用,一部分是特色发音人的费用。基于撸码的习惯,一切先从免费开始。

  详情请看这里:https://www.xfyun.cn/services/online_tts

 开干

看了一圈没有C#的demo,这就尴尬了,虽然是有文档,但是大家都懂,好比微信公众号的开发文档,要变成实际的代码,看得见的应用那是要废一番功夫的。找了一番之后,终于发现一个开源的项目刚发布没多久,真是喜出望外就开干了: https://github.com/zuiyuewentian/XunFeiNETSDK

讯飞的这个接口是基于websock的,我们先用控制台程序做一个demo。C#其实自带了websocket,不过这里用的是WebSocketSharp,这个我觉得很好,System.Net.WebSockets.WebSocket 是基于异步方法的,后面我会讲到,而WebSocketSharp.WebSocket 是基于事件的,很符合前端的编程习惯。

websocket = new WebSocketSharp.WebSocket(reqUrl);
                websocket.OnMessage += Websocket_OnMessage;
                websocket.OnOpen += Websocket_OnOpen;
                websocket.Connect();

讯飞的服务器收到我们的文字内容后,会以流的形势把音频传回来,在我们的服务器上把这种流转成文件即可。

复制代码
 private static Stopwatch stopwatch;
        public static void Main(string[] args)
        {
            //text要合成的文字,pathUrl域名
            stopwatch = new Stopwatch();
            stopwatch.Start();
            var xunFeiNetSdk = new XunFeiTTS();
            xunFeiNetSdk.MessageUpdate_Event += XunFeiNetSdk_MessageUpdate_Event;
            xunFeiNetSdk.SendData("张家界荷花国际机场,北京大兴机场,长沙黄花机场,邵阳武冈机场,所有航班全部复航!");
            Console.Read();
        }

        static byte[] data = new byte[0];
        private static void XunFeiNetSdk_MessageUpdate_Event(TTS_Data_Model message, string error = null)
        {

            if (error != null)
            {
                Console.WriteLine(error);
                return;
            }

            try
            {
                //合成结束
                if (message.status == 2)
                {
                    Console.WriteLine("合成成功");
                    string voice = string.Format("{0}.wav", DateTime.Now.ToString("yyyyMMddHHmmssfff"));

                    Console.WriteLine("正在保存..."+voice);
                    
                    data = data.Concat(message.audioStream).ToArray();

                    var mWavWriter = new WaveFileWriter(voice, new WaveFormat(16000, 1));
                    mWavWriter.Write(data, 0, data.Length);
                    mWavWriter.Close();
                    mWavWriter.Dispose();
                    Console.WriteLine("保存成功...");
                    var sp = stopwatch.Elapsed;

                    Console.WriteLine("用时" + sp);


                }
                else
                {
                    data = data.Concat(message.audioStream).ToArray();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

    }
复制代码

文件的存储用的是NAudio,XunFeiNETSDK里面的代码我独立出来。

(最近2个月航班太少了,工资骤减,原谅我说出我的内心话) 

这样就得到了语音了。听一听,还能接受。但是怎么做到web页面里面呢?

改造成web应用

首先的思路是,前端把文字发过来,然后交给sdk去获取音频,得到文件的地址后返回给前端。所以最合适的方案还是前端也用websocket,因为发送消息和收到消息是分开的。那么这又需要后端有一个websocket服务了

 

我又不想单独去开一个websocket服务,那就可以将这个websocket做成api的形式,如下:

  View Code
复制代码
 var webSocket;
        var player = document.getElementById("player");
        function sendSocketMsg() {
            var msg = $("#msg").val();
            webSocket.send(msg);
            showMsg("发送消息:" + msg, "blue");
        }

        openSocket();

        function openSocket() {
            if (webSocket != null && typeof (webSocket) != "undefined") {
                closeSocket();
            }
            webSocket = new WebSocket("ws://" + location.hostname + ":" + location.port + "/api/msg");
            webSocket.onopen = function () {
                showMsg("连接建立");
            }
            webSocket.onerror = function () {
                showMsg("发生异常");
            }

            webSocket.onmessage = function (event) {
                showMsg("收到消息:" + event.data, "yellow");
                if (event.data.indexOf("voice:") > -1) {
                    var src = event.data.split("voice:")[1];
                    player.src = src;
                    player.play();
                }
            }

            webSocket.onclose = function () {
                showMsg("连接关闭");
            }
        }

        function closeSocket() {
            if (webSocket != null && typeof (webSocket) != "undefined") {
                webSocket.close();
            }
        }

        function showMsg(msg, type) {
            if (type === null || typeof (type) === "undefined") type = "gray";
            $("#show").append("<span class='" + type + "'>" + msg + "</span><br>");
        }
复制代码

这样就得到产品的雏形了。后续要考虑的是文字的长短、音频播放器的展示效果,还能换一下播放的声音等等,每次给你说一个功能,其实这个功能背后有太多细节了。

 Console版源码:https://download.csdn.net/download/stoneniqiu/12347028 

 Web版源码:https://download.csdn.net/download/stoneniqiu/12347167 

猜你喜欢

转载自www.cnblogs.com/Leo_wl/p/12791993.html