赞
踩
本文节选自洪流学堂公众号技术专栏《大话Unity2019》,未经允许不可转载。
洪流学堂公众号回复语音识别
获取源码工程。
洪流学堂,让你快人几步。你好,我是郑洪智。
大智:“今天给你来点刺激的。”
小新满面红光:“啥刺激的?人家可还是个小孩子。”
大智:“带你实战!”
小新:“啊?智哥你变了!”
大智:“变是不可能的,带你实战百度语音识别。”
小新:“嗨,您这说话能不大喘气不,我还以为是那个啥呢”
大智:“你说的那个啥我可不懂啊,走了上战场。”
大智:“百度语音识别用来学习HTTP通信是个特别好的例子。”
首先要做一些准备工作:
大智:“看完文档了没?”
小新:“看完了”
大智:“那我们就开始了。”
语音识别主要有两个过程:
鉴权认证的流程在百度语音识别的文档中有详细介绍,我们在这把流程再梳理一下:
使用Client Credentials获取Access Token需要应用在其服务端发送请求(推荐用POST方法)到百度OAuth2.0授权服务的“ https://openapi.baidu.com/oauth/2.0/token ”地址上,并带上以下参数:
- grant_type:必须参数,固定为“client_credentials”;
- client_id:必须参数,应用的 API Key;
- client_secret:必须参数,应用的 Secret Key;
例如:
https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=Va5yQRHl********LT0vuXV4&client_secret= 0rDSjzQ20XUj5i********PQSzr5pVw2
参数是什么呢?
URL中的参数(paramter)部分:
参数部分:从“?”开始到“#”为止之间(如果没有#那就是到url结束)的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为grant_type=client_credentials&client_id=Va5yQRHl********LT0vuXV4&client_secret= 0rDSjzQ20XUj5i********PQSzr5pVw2
。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。
using System; using System.Collections; using UnityEngine; using UnityEngine.Networking; public class BaiduAsr : MonoBehaviour { public string APIKey; public string SecretKey; private string Token; // 用于解析返回的json [Serializable] class TokenResponse { public string access_token = null; } IEnumerator Start() { // 拼接请求的URL,使用到了C#中新的字符串拼接的方法 var uri = $"https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id={APIKey}&client_secret={SecretKey}"; var www = UnityWebRequest.Get(uri); yield return www.SendWebRequest(); if (www.isHttpError || www.isNetworkError) { Debug.Log("[BaiduAip]" + www.downloadHandler.text); var result = JsonUtility.FromJson<TokenResponse>(www.downloadHandler.text); Token = result.access_token; Debug.Log("[WitBaiduAip]Token has been fetched successfully"); } else { Debug.LogError("[BaiduAip]" + www.error); Debug.LogError("[BaiduAip]Token was fetched failed. Please check your APIKey and SecretKey"); } } }
获取请求结果后,使用JsonUtility将json字符串解析出来,将Toekn保存下来留作后用,我们的鉴权认证就完成了。
录制音频的核心代码如下。
其中方法的参数可以参考文档:https://docs.unity3d.com/ScriptReference/Microphone.html
_clipRecord = Microphone.Start(null, false, 30, 16000);
Microphone.End(null);
百度语音识别支持两种方式请求:
为了更好的学习HTTP请求,在这我们选用Raw方式进行请求。
使用Raw方式需要处理几点:
Content-Type: audio/pcm;rate=16000
,具体说明见百度语音文档具体代码如下:
using System; using System.Collections; using UnityEngine; using UnityEngine.Networking; public class BaiduAsr : MonoBehaviour { public string APIKey; public string SecretKey; private string Token; private AudioClip _clipRecord; // 用于解析返回的json [Serializable] class TokenResponse { public string access_token = null; } [Serializable] public class AsrResponse { public int err_no; public string err_msg; public string sn; public string[] result; } IEnumerator Start() { // 拼接请求的URL var uri = $"https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id={APIKey}&client_secret={SecretKey}"; var www = UnityWebRequest.Get(uri); yield return www.SendWebRequest(); if (www.isHttpError || www.isNetworkError) { Debug.Log("[BaiduAip]" + www.downloadHandler.text); var result = JsonUtility.FromJson<TokenResponse>(www.downloadHandler.text); Token = result.access_token; Debug.Log("[WitBaiduAip]Token has been fetched successfully"); } else { Debug.LogError("[BaiduAip]" + www.error); Debug.LogError("[BaiduAip]Token was fetched failed. Please check your APIKey and SecretKey"); } } void Update() { if (Input.GetKeyDown(KeyCode.A)) { _clipRecord = Microphone.Start(null, false, 30, 16000); } if (Input.GetKeyUp(KeyCode.A)) { Microphone.End(null); Debug.Log("[WitBaiduAip demo]end record"); var data = ConvertAudioClipToPCM16(_clipRecord); StartCoroutine(Recognize(data, s => { var text = s.result != null && s.result.Length > 0 ? s.result[0] : "未识别到声音"; Debug.Log(text); })); } } public IEnumerator Recognize(byte[] data, Action<AsrResponse> callback) { var uri = $"https://vop.baidu.com/server_api?lan=zh&cuid={SystemInfo.deviceUniqueIdentifier}&token={Token}"; var form = new WWWForm(); form.AddBinaryData("audio", data); var www = UnityWebRequest.Post(uri, form); www.SetRequestHeader("Content-Type", "audio/pcm;rate=16000"); yield return www.SendWebRequest(); if (string.IsNullOrEmpty(www.error)) { Debug.Log("[WitBaiduAip]" + www.downloadHandler.text); callback(JsonUtility.FromJson<AsrResponse>(www.downloadHandler.text)); } else Debug.LogError(www.error); } /// <summary> /// 将Unity的AudioClip数据转化为PCM格式16bit数据 /// </summary> /// <param name="clip"></param> /// <returns></returns> public static byte[] ConvertAudioClipToPCM16(AudioClip clip) { var samples = new float[clip.samples * clip.channels]; clip.GetData(samples, 0); var samples_int16 = new short[samples.Length]; for (var index = 0; index < samples.Length; index++) { var f = samples[index]; samples_int16[index] = (short)(f * short.MaxValue); } var byteArray = new byte[samples_int16.Length * 2]; Buffer.BlockCopy(samples_int16, 0, byteArray, 0, byteArray.Length); return byteArray; } }
上述代码中有一个AudioClip的数据转化为PCM16数据的方法。
具体操作时,按住键盘A键开始录制语音,松开开始识别并Log结果。
大智:“学会HTTP请求以后,你就掌握了向外拓展的能力,现在很多云服务都是以HTTP请求的方式提供的,要好好掌握哦。”
洪流学堂公众号回复语音识别
获取源码工程。
大智:“最后我们使用了Raw方式来请求,另外还有一种json的请求方式,你来试试吧。”
小新:“好嘞!”
大智:“收获别忘了分享出来!也别忘了分享给你学Unity的朋友,也许能够帮到他。”
洪流学堂公众号回复专栏
,查看更多专栏文章。
《大话Unity2019》,大智带小新学Unity2019的有趣经历,让你学Unity更简单。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。