Unity智能语音聊天机器人

在本篇文章中,使用了百度的语音识别、语音合成、智能对话Unit的功能,制作成了一款简易的聊天机器人,在开始做之前呢,需要确定需要实现的核心功能,有以下几点:
(1)实现人机文字聊天
(2)实现人机语音聊天
(3)语音聊天记录播放
(4)文字聊天与语音聊天切换

创建UI界面

核心代码

一、人机文字聊天

chatDialog.onEndEdit.AddListener(delegate{if (chatDialog != null){if (chatDialog.text.Equals("")){return;}chat.AddChatMessage( ChatUI.enumChatMessageType.MessageRight, chatDialog.text);//自己的聊天UI界面Unit_NLP(chatDialog.text);JsonDecode(result);}});
 /// <summary>/// NLP的人工智能对话功能/// </summary>/// <param name="mysay"></param>/// <param name="session_id"></param>/// <param name="action_id"></param>public void Unit_NLP(string mysay, string session_id = "", string action_id = ""){string token = accessToken;string host = "https://aip.baidubce.com/rpc/2.0/unit/service/chat?access_token=" + token;HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);request.Method = "post";request.ContentType = "application/json";request.KeepAlive = true;JsonData send = new JsonData();send["version"] = "2.0";send["service_id"] = "S27034";send["log_id"] = "home";send["session_id"] = "home";send["action_id"] = "1017002";send["request"] = new JsonData();send["request"]["user_id"] = "88888";send["request"]["query"] = mysay;send["request"]["query_info"] = new JsonData();send["request"]["query_info"]["type"] = "TEXT";JsonData bot_session = new JsonData();bot_session["session_id"] = "";send["bot_session"] = JsonMapper.ToJson(bot_session);string sendStr = JsonMapper.ToJson(send);byte[] buffer = Encoding.UTF8.GetBytes(sendStr);request.ContentLength = buffer.Length;request.GetRequestStream().Write(buffer, 0, buffer.Length);HttpWebResponse response = (HttpWebResponse)request.GetResponse();StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);result = reader.ReadToEnd();}
 /// <summary>/// 对NLP的回复进行Json解析/// </summary>/// <param name="js"></param>/// <returns></returns>public List<string> JsonDecode(string js){List<string> Says = new List<string>();var json = SimpleJson.SimpleJson.DeserializeObject<SimpleJson.JsonObject>(js);if (json.ContainsKey("result")){var result = (SimpleJson.JsonObject)json["result"];if (result.ContainsKey("response_list")){var resArray = (SimpleJson.JsonArray)result["response_list"];var res = (SimpleJson.JsonObject)resArray[0];if (res.ContainsKey("action_list")){var actArray = (SimpleJson.JsonArray)res["action_list"];var act = (SimpleJson.JsonObject)actArray[0];if (act.ContainsKey("say")){var say = (string)act["say"];if (!isChooseSpeech){chat.AddChatMessage(ChatUI.enumChatMessageType.MessageLeft,say);}else{StartCoroutine(StratTTS(say, s =>{robotclipDic.Add(robotindex,s.clip);robotindex++;chat.AddChatMessage(ChatUI.enumChatMessageType.MessageLeft);tts_source.clip = s.clip;tts_source.Play();}));}Says.Add(say);}}}}return Says;}

二、人机语音聊天

/// <summary>/// 开始录音/// </summary>public void StartRecord(){saveAudioClip = Microphone.Start(currentDeviceName, false, recordMaxTime, recordFrequency);}/// <summary>/// 结束录音/// </summary>public void EndRecord(){Microphone.End(currentDeviceName);myclipDic.Add(myindex, saveAudioClip);myindex++;//source.PlayOneShot(saveAudioClip);StartCoroutine(RequestASR());//请求语音识别}/// <summary>/// 请求语音识别/// </summary>/// <returns></returns>public IEnumerator RequestASR(){if (string.IsNullOrEmpty(accessToken)){yield return _GetAccessToken();}resulrStr = string.Empty;//处理当前录音数据为PCM16float[] samples = new float[recordFrequency * 10 * saveAudioClip.channels];saveAudioClip.GetData(samples, 0);var samplesShort = new short[samples.Length];for (var index = 0; index < samples.Length; index++){samplesShort[index] = (short)(samples[index] * short.MaxValue);}byte[] datas = new byte[samplesShort.Length * 2];Buffer.BlockCopy(samplesShort, 0, datas, 0, datas.Length);string url = string.Format("{0}?cuid={1}&token={2}", "https://vop.baidu.com/server_api", SystemInfo.deviceUniqueIdentifier, accessToken);WWWForm wwwForm = new WWWForm();wwwForm.AddBinaryData("audio", datas);UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, wwwForm);unityWebRequest.SetRequestHeader("Content-Type", "audio/pcm;rate=" + recordFrequency);yield return unityWebRequest.SendWebRequest();if (string.IsNullOrEmpty(unityWebRequest.error)){resulrStr = unityWebRequest.downloadHandler.text;if (Regex.IsMatch(resulrStr, @"err_msg.:.success")){Match match = Regex.Match(resulrStr, "result.:..(.*?)..]");if (match.Success){resulrStr = match.Groups[1].ToString();//语音识别的结果Unit_NLP(resulrStr);JsonDecode(result);}}else{resulrStr = "识别结果为空";}}}/// <summary>/// 返回的语音合成结果/// </summary>[System.Serializable]public class TtsResponse{public int error_index;public string error_msg;public string sn;public int idx;public bool Success{get { return error_index == 0; }}public AudioClip clip;}/// <summary>/// 请求语音合成/// </summary>/// <param name="text"></param>/// <param name="callback"></param>/// <returns></returns>public IEnumerator StratTTS(string text, Action<TtsResponse> callback){var url = "http://tsn.baidu.com/text2audio";var param = new Dictionary<string, string>();param.Add("tex", text);param.Add("tok", accessToken);param.Add("cuid", SystemInfo.deviceUniqueIdentifier);param.Add("ctp", "1");param.Add("lan", "zh");param.Add("spd", "5");param.Add("pit", "5");param.Add("vol", "10");param.Add("per", "1");
#if UNITY_STANDALONE || UNITY_EDITOR || UNITY_UWPparam.Add("aue", "6"); //Windows设置为wav格式,移动端需要mp3格式
#endifint i = 0;foreach (var p in param){url += i != 0 ? "&" : "?";url += p.Key + "=" + p.Value;i++;}
#if UNITY_STANDALONE || UNITY_EDITOR || UNITY_UWP  //根据不同平台,获取不同类型的音频格式var www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.WAV);
#elsevar www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG);
#endifDebug.Log("[WitBaiduAip]" + www.url);yield return www.SendWebRequest();if (www.isHttpError || www.isNetworkError)Debug.LogError(www.error);else{var type = www.GetResponseHeader("Content-Type");Debug.Log("[WitBaiduAip]response type: " + type);if (type.Contains("audio")){var response = new TtsResponse { clip = DownloadHandlerAudioClip.GetContent(www) };callback(response);}else{var textBytes = www.downloadHandler.data;var errorText = Encoding.UTF8.GetString(textBytes);}}}

三、语音聊天记录播放

//发送录音保存字典public int myindex=0;public Dictionary<int, AudioClip> myclipDic = new Dictionary<int, AudioClip>();//收到录音保存字典public int robotindex = 0;public Dictionary<int, AudioClip> robotclipDic = new Dictionary<int, AudioClip>();
oid Start(){index = UnitManager.instance.myindex;source = GameObject.Find("Canvas/robot").GetComponent<AudioSource>();Litsen_btn = transform.GetComponent<Button>();Litsen_btn.onClick.AddListener(() => {if (MessageType.Equals("myself")){GetValueByKey(UnitManager.instance.myclipDic, index - 1);}else if (MessageType.Equals("robot")){GetValueByKey(UnitManager.instance.robotclipDic, index - 1);}});}public void GetValueByKey(Dictionary<int, AudioClip> dic, int key){AudioClip clip = null;dic.TryGetValue(key, out clip);source.clip = clip;source.Play();}

通篇代码

using LitJson;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class UnitManager : MonoBehaviour
{public static UnitManager instance;private void Awake(){instance = this;}public string api_key;public string secret_key;string accessToken = string.Empty;InputField chatDialog;Button speechToggle; //选择当前发送信息的类型(语音或者文字)public ChatUI chat; //聊天界面public bool isChooseSpeech = false; //判断当前的发送信息类型状态//语音识别模块string resulrStr = string.Empty;int recordFrequency = 8000;AudioClip saveAudioClip; //存储语音string currentDeviceName = string.Empty; //当前录音设备名称AudioSource source;int recordMaxTime=20;public Sprite[] _sp;public GameObject speechButton;//NLPAudioSource tts_source;string result=string.Empty;//发送录音保存字典public int myindex=0;public Dictionary<int, AudioClip> myclipDic = new Dictionary<int, AudioClip>();//收到录音保存字典public int robotindex = 0;public Dictionary<int, AudioClip> robotclipDic = new Dictionary<int, AudioClip>();void Start(){StartCoroutine(_GetAccessToken());chat = GameObject.Find("Canvas/ChatUI").GetComponent<ChatUI>();chatDialog = GameObject.Find("Canvas/ChatUI/InputArea/InputField").GetComponent<InputField>();speechToggle= GameObject.Find("Canvas/ChatUI/speechToggle").GetComponent<Button>();tts_source = GameObject.Find("Canvas/ChatUI/speechToggle").GetComponent<AudioSource>();source = transform.GetComponent<AudioSource>();chatDialog.onEndEdit.AddListener(delegate{if (chatDialog != null){if (chatDialog.text.Equals("")){return;}chat.AddChatMessage( ChatUI.enumChatMessageType.MessageRight, chatDialog.text);//自己的聊天UI界面Unit_NLP(chatDialog.text);JsonDecode(result);}});speechToggle.onClick.AddListener(ToChangeSpeechToggle);}/// <summary>/// 当前处于发语音还是文字,如果是语音则AI回复语音,如果是文字则AI回复文字/// </summary>void ToChangeSpeechToggle(){if (!this.isChooseSpeech){this.isChooseSpeech = true;speechToggle.GetComponent<Image>().sprite = _sp[0];speechButton.SetActive(true);}else{this.isChooseSpeech = false;speechToggle.GetComponent<Image>().sprite = _sp[1];speechButton.SetActive(false);}}/// <summary>/// 开始录音/// </summary>public void StartRecord(){saveAudioClip = Microphone.Start(currentDeviceName, false, recordMaxTime, recordFrequency);}/// <summary>/// 结束录音/// </summary>public void EndRecord(){Microphone.End(currentDeviceName);myclipDic.Add(myindex, saveAudioClip);myindex++;//source.PlayOneShot(saveAudioClip);StartCoroutine(RequestASR());//请求语音识别}/// <summary>/// 请求语音识别/// </summary>/// <returns></returns>public IEnumerator RequestASR(){if (string.IsNullOrEmpty(accessToken)){yield return _GetAccessToken();}resulrStr = string.Empty;//处理当前录音数据为PCM16float[] samples = new float[recordFrequency * 10 * saveAudioClip.channels];saveAudioClip.GetData(samples, 0);var samplesShort = new short[samples.Length];for (var index = 0; index < samples.Length; index++){samplesShort[index] = (short)(samples[index] * short.MaxValue);}byte[] datas = new byte[samplesShort.Length * 2];Buffer.BlockCopy(samplesShort, 0, datas, 0, datas.Length);string url = string.Format("{0}?cuid={1}&token={2}", "https://vop.baidu.com/server_api", SystemInfo.deviceUniqueIdentifier, accessToken);WWWForm wwwForm = new WWWForm();wwwForm.AddBinaryData("audio", datas);UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, wwwForm);unityWebRequest.SetRequestHeader("Content-Type", "audio/pcm;rate=" + recordFrequency);yield return unityWebRequest.SendWebRequest();if (string.IsNullOrEmpty(unityWebRequest.error)){resulrStr = unityWebRequest.downloadHandler.text;if (Regex.IsMatch(resulrStr, @"err_msg.:.success")){Match match = Regex.Match(resulrStr, "result.:..(.*?)..]");if (match.Success){resulrStr = match.Groups[1].ToString();//语音识别的结果Unit_NLP(resulrStr);JsonDecode(result);}}else{resulrStr = "识别结果为空";}}}/// <summary>/// 返回的语音合成结果/// </summary>[System.Serializable]public class TtsResponse{public int error_index;public string error_msg;public string sn;public int idx;public bool Success{get { return error_index == 0; }}public AudioClip clip;}/// <summary>/// 请求语音合成/// </summary>/// <param name="text"></param>/// <param name="callback"></param>/// <returns></returns>public IEnumerator StratTTS(string text, Action<TtsResponse> callback){var url = "http://tsn.baidu.com/text2audio";var param = new Dictionary<string, string>();param.Add("tex", text);param.Add("tok", accessToken);param.Add("cuid", SystemInfo.deviceUniqueIdentifier);param.Add("ctp", "1");param.Add("lan", "zh");param.Add("spd", "5");param.Add("pit", "5");param.Add("vol", "10");param.Add("per", "1");
#if UNITY_STANDALONE || UNITY_EDITOR || UNITY_UWPparam.Add("aue", "6"); //Windows设置为wav格式,移动端需要mp3格式
#endifint i = 0;foreach (var p in param){url += i != 0 ? "&" : "?";url += p.Key + "=" + p.Value;i++;}
#if UNITY_STANDALONE || UNITY_EDITOR || UNITY_UWP  //根据不同平台,获取不同类型的音频格式var www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.WAV);
#elsevar www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG);
#endifDebug.Log("[WitBaiduAip]" + www.url);yield return www.SendWebRequest();if (www.isHttpError || www.isNetworkError)Debug.LogError(www.error);else{var type = www.GetResponseHeader("Content-Type");Debug.Log("[WitBaiduAip]response type: " + type);if (type.Contains("audio")){var response = new TtsResponse { clip = DownloadHandlerAudioClip.GetContent(www) };callback(response);}else{var textBytes = www.downloadHandler.data;var errorText = Encoding.UTF8.GetString(textBytes);}}}/// <summary>/// NLP的人工智能对话功能/// </summary>/// <param name="mysay"></param>/// <param name="session_id"></param>/// <param name="action_id"></param>public void Unit_NLP(string mysay, string session_id = "", string action_id = ""){string token = accessToken;string host = "https://aip.baidubce.com/rpc/2.0/unit/service/chat?access_token=" + token;HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);request.Method = "post";request.ContentType = "application/json";request.KeepAlive = true;JsonData send = new JsonData();send["version"] = "2.0";send["service_id"] = "S27034";send["log_id"] = "home";send["session_id"] = "home";send["action_id"] = "1017002";send["request"] = new JsonData();send["request"]["user_id"] = "88888";send["request"]["query"] = mysay;send["request"]["query_info"] = new JsonData();send["request"]["query_info"]["type"] = "TEXT";JsonData bot_session = new JsonData();bot_session["session_id"] = "";send["bot_session"] = JsonMapper.ToJson(bot_session);string sendStr = JsonMapper.ToJson(send);byte[] buffer = Encoding.UTF8.GetBytes(sendStr);request.ContentLength = buffer.Length;request.GetRequestStream().Write(buffer, 0, buffer.Length);HttpWebResponse response = (HttpWebResponse)request.GetResponse();StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);result = reader.ReadToEnd();}/// <summary>/// 对NLP的回复进行Json解析/// </summary>/// <param name="js"></param>/// <returns></returns>public List<string> JsonDecode(string js){List<string> Says = new List<string>();var json = SimpleJson.SimpleJson.DeserializeObject<SimpleJson.JsonObject>(js);if (json.ContainsKey("result")){var result = (SimpleJson.JsonObject)json["result"];if (result.ContainsKey("response_list")){var resArray = (SimpleJson.JsonArray)result["response_list"];var res = (SimpleJson.JsonObject)resArray[0];if (res.ContainsKey("action_list")){var actArray = (SimpleJson.JsonArray)res["action_list"];var act = (SimpleJson.JsonObject)actArray[0];if (act.ContainsKey("say")){var say = (string)act["say"];if (!isChooseSpeech){chat.AddChatMessage(ChatUI.enumChatMessageType.MessageLeft,say);}else{StartCoroutine(StratTTS(say, s =>{robotclipDic.Add(robotindex,s.clip);robotindex++;chat.AddChatMessage(ChatUI.enumChatMessageType.MessageLeft);tts_source.clip = s.clip;tts_source.Play();}));}Says.Add(say);}}}}return Says;}/// <summary>/// 获取accessToken请求令牌/// </summary>/// <returns></returns>IEnumerator _GetAccessToken(){var uri =string.Format("https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id={0}&client_secret={1}",api_key, secret_key);UnityWebRequest unityWebRequest = UnityWebRequest.Get(uri);yield return unityWebRequest.SendWebRequest();if (unityWebRequest.isDone){Match match = Regex.Match(unityWebRequest.downloadHandler.text, @"access_token.:.(.*?).,");if (match.Success){Debug.Log("Token已经匹配");accessToken = match.Groups[1].ToString();}else{Debug.Log("验证错误,获取AccessToken失败!!!");}}}
}

演示效果

发送文字:

发送语音:
(因为语音播放演示不了,所以就打个样吧)

结尾,希望能与对这方面感兴趣的兄弟姐妹一起探讨,有需要源码做项目的也可以私聊。技术有限,现在是在Windows平台上实现了简易智能语音聊天机器人的基本功能,各方面的细节还有待优化,本篇结束啦,希望明天会更好。

Unity 智能语音助手相关推荐

  1. 标贝科技|智能语音助手+全息形象,会是下一个趋势吗

    现在,智能语音助手已经无处不在,手机.音箱.电视.汽车里都能寻得他们的踪迹.他们都有一些相似的点:能识别语音.说唤醒词就能开始对话.可以完成人们的各种指令,除了内在技能以外,在外表上,他们目前也都没有 ...

  2. 亚马逊智能语音助手Alexa大举招聘 放出400个职位

    今年5月,亚马逊CEO杰夫·贝索斯(Jeff Bezos)宣布,亚马逊将招聘1000多人,开发Echo智能音箱和Alexa智能语音助手.当时他表示:"这只是冰山一角." 根据Ale ...

  3. 百度地图智能语音助手用户量突破3亿:确实方便

    百度地图宣布截至10月1日18:00,百度地图智能语音功能用户量突破3亿.超3亿人喊"小度小度"来解决地图需求问题. 百度地图智能语音助手功能于2017年上线,依托百度大脑语音领先 ...

  4. 如何快速搭建一个像“天猫精灵”的智能语音助手?

    不看这几篇好文,就别说自己了解物联网 天猫精灵相信大家都不陌生了,它是阿里巴巴于2017年7月5日发布的AI智能终端品牌.让用户以自然语言对话的交互方式,实现影音娱乐.购物.信息查询.生活服务等功能操 ...

  5. 智能语音助手调研【简单可行方案及开源代码】

    智能语音助手调研 需求: 方案一:百度智能对话AI产品(3个) 方案二:阿里AI语音助手 方案三:科大讯飞语音助手 部署方式: 不收费版本: 集成方案 简单可行方案及开源代码

  6. 爆肝一周,用Python在物联网设备上写了个智能语音助手

    1. 背景介绍 智能语音助手作为物联网领域的一个重要生态成员,是一种全新的交互方式,它能够解放双手,随时提供服务,无须借助任何按键.想必很多开发者都有玩过天猫精灵.小爱同学或者小度吧,看到这些炫酷的人 ...

  7. 午夜惊魂!频繁失控的亚马逊智能语音助手Alexa到底怎么了?

    [数据猿导读]不久之前,亚马逊Alexa上演了一场午夜惊魂. 记者 | 郭敏 官网 | www.datayuan.cn 微信公众号ID | datayuancn 当基于人工智能的语音助手进入千家万户的 ...

  8. 华为云WeLink智能语音助手专题(上篇:WeLink智能语音助手是什么?)

    华为云WeLink是华为内部打磨多年的远程办公软件.协同办公平台.移动办公平台.协同办公软件,源自华为19万员工的数字化办公实践,融合多屏协同.视频会议.打卡.报销.考勤.审批.企业网盘.IM消息.邮 ...

  9. 通过激光入侵Google智能语音助手

    黑客可利用激光向智能语音助手发送看不见的指令. 近期,有研究人员发现,只需一束激光,就可以控制Alexa和Siri智能扬声器.攻击者不需要对受害者的设备进行物理接触,也不需要与受害者进行交互,只要攻击 ...

  10. 贴近司机,感知生活:智能语音助手在滴滴车主端的设计与实践

    桔妹导读:基于网约车司机的职业特性,帮助与指引司机在各类复杂的场景下更安全.便捷地完成工作,并尽可能疏导与减轻他们因长时间处于封闭环境下的心理压力,一直是滴滴发力的一个方向.但现有的一些途径,如规则展 ...

最新文章

  1. 2021年《环球科学》十大科学新闻:“天宫”空间站、火星探索位列前二
  2. 09、redis哨兵的多个核心底层原理的深入解析(包含slave选举算法)
  3. python sklearn学习笔记大全(常见代码速查)
  4. wince投屏苹果手机_怎么把手机上的导航映射到中控屏
  5. 构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化...
  6. MM32看门狗学习(兼容STM32)
  7. Zabbix实现自动发现端口并监控
  8. 用ping IP的方法测试网卡
  9. Nmap命令参数介绍
  10. C语言乘方,平方根的使用
  11. 苹果企业开发者账号申请时间
  12. bp神经网络实现人脸识别,车牌识别深度神经网络
  13. 微信ios接入-Objc -all_load的坑
  14. 新整理的开源Odoo13发布更新的部分功能模块信息
  15. 题库来源:安全生产模拟考试一点通公众号小程序 安全生产模拟考试一点通:2021年焊工(初级)考试资料为正在备考焊工(初级)操作证的学员准备的理论考试专题,每个月更新的焊工(初级)免费试题祝您顺利通过
  16. 【Vscode】解决报错 An SSH installation couldn‘t be found
  17. 使用无界面方式登录人人网
  18. 其他——调试时chrom崩溃
  19. Elasticsearch(033):es中Document(文档)之删除文档
  20. Spring Cloud Gateway之踩坑日记

热门文章

  1. Parsing error: Decorators cannot be used to decorate object literal properties
  2. 新浪微博since_id值
  3. 易语言 设置屏幕刷新率 源码_下任安卓机皇曝光,领先iPhone 12屏幕一年!
  4. 学习uc/os-ii
  5. 收藏夹整理——程序员笔试面试
  6. Unity Shader 玻璃材质
  7. 使用乘法表计算GF(2^8)中的乘法
  8. Dlang如何禁用垃圾回收(GC)
  9. 虚拟机的安装没有虚拟网卡
  10. LSD_SLAM 编译、安装到运行demo