unity接入百度Unit理解与交互机器人和语音合成

using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using LitJson;
using UnityEngine;
using UnityEngine.Networking;
using System.Net;
using System.Text;
using System.IO;
using System.Reflection;
using Newtonsoft.Json;
using UnityEngine.Rendering.PostProcessing;
using Debug = UnityEngine.Debug;

public class QueryAIManager : MonoBehaviour
{
    #region delegate

    /// <summary>
    /// 机器人回复委托
    /// </summary>
    /// <param name="res"></param>
    public delegate void QueryAICallResult(JsonData res);

    public event QueryAICallResult QueryCallRes;
    public AIChatCallType ChatType;
    /// <summary>
    /// 回复用户时的委托
    /// </summary>
    /// <param name="result"></param>
    public delegate void DialogResult(string result);

    public event DialogResult DialogCallRes;
    /// <summary>
    /// 不满足条件的结果
    /// </summary>
    public Action<string> DialogNoSatisfyResoult;
    /// <summary>
    /// 语音合成出现问题
    /// </summary>
    public Action<string> VoiceError;
    /// <summary>
    /// 机器人回复的执行函数
    /// </summary>
    /// <param name="enent"></param>
    public delegate void QueryEvent(string enent);

    public event QueryEvent DialogResEvent;
    public delegate void VoiceSuccess(string timeStemp);

    public event VoiceSuccess voiceSuccess;
    #endregion
    /// <summary>
    /// 设置当前环境,默认是测试版
    /// </summary>
    private bool IsRelease = false;

    private string API_KEY;
    private string SECRET_KEY;
    private string APP_ID;
    private string GetAccessTokenUrl = "https://aip.baidubce.com/oauth/2.0/token";
    private string UnitUrl;

    private string SynthesisUrl = "http://tsn.baidu.com/text2audio";//语音合成url
    [HideInInspector]
    public string accessToken = "";
    private JsonData jsonDataSend;
    private string logId = "";
    public string query = "";
    [HideInInspector]
    public string userId = string.Empty;

    private HttpWebRequest request;
    private string sessionId = "";
    [HideInInspector]
    public Action<string> dialogCallBack;
    public string WriteLocalUrl;
    public Action<int> AudioIndexCall;
    /// <summary>
    /// 存储播放过的音效的字典(时间是key,路径为Vlaue)
    /// </summary>
    [HideInInspector]
    public Dictionary<string, string> DicAudio;
    [HideInInspector]
    public int AudioIndex = 0;
    int index = 0;
    private string FuncStr = "";
    /// <summary>
    /// 是否存在录音设备
    /// </summary>
    public bool isHasDevice = false;
    /// <summary>
    /// 语音合成的当前时间
    /// </summary>
    private string CurAudioTimestemp = "";

    #region Sigleton
    private static QueryAIManager m_Instance = null;
    public static QueryAIManager Singleton
    {
        get
        {
            if (m_Instance == null)
                m_Instance = CEMain.queryAiMger;

            return m_Instance;
        }
    }
    #endregion Singleton
    void Awake()
    {
        API_KEY = "nSHVHmSI6wKof6BRdUke1uKZ";
        SECRET_KEY = "6msxcehHFAVdn6UFgzZqy02BAiskj75n";
        APP_ID = "15981168";
        if (IsRelease)
        {
            UnitUrl = "https://unit.bj.baidubce.com/rpc/2.0/unit/bot/chat?access_token=";
        }
        else
        {
            UnitUrl = "https://aip.baidubce.com/rpc/2.0/unit/bot/chat?access_token=";
        }
        GetAccessToken();
    }
    void Start()
    {
        QueryCallRes += QueryCallBackResult;
       
        AudioIndexCall = GetAudioIndex;
        logId = UtilMgr.GUID(12);
        WriteLocalUrl = Util.GetRootPath() + "Audio/";
        DicAudio = new Dictionary<string, string>();
        DeleteVoiceDir();//每次重新登录,都要删除下载的语音文件,以达到节省硬盘空间的目的
        
       
    }
    /// <summary>
    /// 删除语音文件
    /// </summary>
    public void DeleteVoiceDir()
    {
        if (Directory.Exists(WriteLocalUrl))
        {
            DicAudio.Clear();
            DirectoryInfo direction = new DirectoryInfo(WriteLocalUrl);
            FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);
            for (int i = 0; i < files.Length; i++)
            {
                if (files[i].Name.EndsWith(".wav"))
                {
                    File.Delete(WriteLocalUrl + files[i].Name);
                }
            }
        }
    }
    void GetAudioIndex(int index)
    {
        AudioIndex = index;
    }

    public void StopCurServiceAudio()
    {
        CESoundManager.Singleton._StopSound(AudioIndex);
    }
    /// <summary>
    /// 向客服说话
    /// </summary>
    /// <param name="dialog"></param>
    public void SayToAIServices(string dialog)
    {
        string host = UnitUrl + accessToken;
       // Debug.Log("access_token:" + host);
        JsonData send = new JsonData();
        send["version"] = "2.0";
        send["bot_id"] = "35577";
        send["log_id"] = logId;
        send["request"] = new JsonData();
        send["request"]["user_id"] = userId;
        send["request"]["query"] = dialog;
        send["request"]["query_info"] = new JsonData();
        send["request"]["query_info"]["type"] = "TEXT";
        send["request"]["query_info"]["source"] = "ASR";
        //send["request"]["query_info"]["asr_candidates"][0]=;
        send["request"]["bernard_level"] = 1;
        JsonData bot_session = new JsonData();
        bot_session["session_id"] = sessionId;
        send["bot_session"] = JsonMapper.ToJson(bot_session);
        string sendStr = JsonMapper.ToJson(send);
        //Debug.Log("sendstr:" + sendStr);
        StartCoroutine(DiaLogPost(host, sendStr, (res) =>
        {
            if (DialogNoSatisfyResoult != null)
            {
                DialogNoSatisfyResoult("意图识别出错:" + res);
            }
        }));
    }
    /// <summary>
    /// 机器人回复
    /// </summary>
    /// <param name="res"></param>
    public void QueryCallBackResult(JsonData res)
    {
        //Debug.Log("result:" + res["response"].ToJson());
        //return;
        if (res["response"]["status"].ToString().ToInt() != 0)
        {
            if (DialogNoSatisfyResoult != null)
            {
                DialogNoSatisfyResoult("意图识别出错:" + res["response"]["msg"].ToString());
            }
            Debug.LogWarning(res["response"]["msg"].ToString());
            return;
        }
        JsonData bot = JsonMapper.ToObject(res["bot_session"].ToString());
        sessionId = bot["session_id"].ToString();
        foreach (JsonData item in res["response"]["action_list"])
        {
            /*
             *  clarify(澄清)
                satisfy(满足)
                guide(引导到对话意图)
                faqguide(引导到问答意图)
                understood(理解达成,注:内部使用)
                failure(理解失败)
                chat(聊天话术)
                event(触发事件,在答复型对话回应中选择了"执行函数",将返回event类型的action)
             */
            string actionType = item["type"].ToString();

            if (actionType.Equals("failure"))//不满足结果条件时,理解失败
            {
                if (DialogNoSatisfyResoult != null)
                {
                    DialogNoSatisfyResoult(item["say"].ToString());
                }
            }
            else if (actionType.Equals("event"))//满足结果条件时事件
            {
                if (DialogResEvent != null)
                {
                    DialogResEvent(item["custom_reply"].ToString());
                }
            }
            else if (actionType.Equals("guide") || actionType.Equals("faqguide"))//不满足结果条件时引导其他意图
            {
                StringBuilder sb = new StringBuilder();
                JsonData data = item["refine_detail"];
                int index = 0;
                foreach (JsonData var in data["option_list"])
                {
                    index++;
                    sb.AppendFormat("\n{0}.{1}", index, var["option"].ToString());
                }
                if (DialogNoSatisfyResoult != null)
                {
                    DialogNoSatisfyResoult(item["say"] + sb.ToString());
                }
            }
            else if (actionType.Equals("satisfy"))//满足结果条件理解正确
            {
                if (DialogCallRes != null)
                {
                    DialogCallRes(item["say"].ToString());
                }
            }
            else if (actionType.Equals("clarify"))//不满足结果条件时澄清
            {
                if (DialogNoSatisfyResoult != null)
                {
                    DialogNoSatisfyResoult(item["say"].ToString());
                }
            }
            else if (actionType.Equals("chat"))
            {

            }

        }
    }


  
    #region  语音合成

    /// <summary>
    /// 语音合成
    /// </summary>
    /// <param name="txt"></param>
    public void SpeechSynthesis(string txt)
    {
        Debug.Log("语音合成text:"+ txt);
        WWWForm form = new WWWForm();
        form.AddField("per", 0);//发音人选择, 0为普通女声,1为普通男生,3为情感合成-度逍遥,4为情感合成-度丫丫,默认为普通女声
        form.AddField("spd", 6);//语速,取值0-15,默认为5中语速
        form.AddField("pit", 5);//音调,取值0-15,默认为5中语调
        form.AddField("vol", 15);//音量,取值0-15,默认为5中音量
        form.AddField("tex", txt);
        MyFamily fi = GameData.Singleton.getMyFamily();
        form.AddField("cuid", fi.nFamilyID.ToString());
        form.AddField("lan", "zh");
        form.AddField("ctp", 1);
        form.AddField("tok", accessToken);
        form.AddField("aue", 6);

        StartCoroutine(RequestSpeech(SynthesisUrl, form));
    }

    IEnumerator RequestSpeech(string url, WWWForm form)
    {
        using (UnityWebRequest www = UnityWebRequest.Post(url, form))
        {
            www.SetRequestHeader("Content-Type", "application/json;  charset=utf-8");
            yield return www.SendWebRequest();

            if (www.isNetworkError)
            {
                if (VoiceError != null)
                {
                    VoiceError(www.error);
                }
                yield return www.error;
            }
            else
            {
                if (www.responseCode == 200)
                {
                    if (www.GetResponseHeader("Content-Type").ToLower() == "application / json")
                    {
                        JsonData resData = JsonMapper.ToObject(www.downloadHandler.text);
                        if (VoiceError != null)
                        {
                            VoiceError(resData["err_msg"].ToString());
                        }
                    }
                    else
                    {
                        if (www.isDone)
                        {
                            string audioName = UtilMgr.GUID(6);
                            if (!Directory.Exists(WriteLocalUrl))
                            {
                                Directory.CreateDirectory(WriteLocalUrl);
                            }
                            if (!File.Exists(WriteLocalUrl + "audio_" + audioName + ".wav"))
                            {
                                File.Delete(WriteLocalUrl + "audio_" + audioName + ".wav");
                            }
                            File.WriteAllBytes(WriteLocalUrl + "audio_" + audioName + ".wav", www.downloadHandler.data);

                            CurAudioTimestemp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                            if (!DicAudio.ContainsKey(CurAudioTimestemp))
                            {
                                DicAudio.Add(CurAudioTimestemp, WriteLocalUrl + "audio_" + audioName + ".wav");
                            }
                            if (voiceSuccess != null)
                            {
                                voiceSuccess(CurAudioTimestemp);
                            }
                        }
                    }
                }
            }
        }
    }

    #endregion





    #region  对话POST请求
    /// <summary>
    /// 对话POST请求
    /// </summary>
    /// <param name="uri"></param>
    /// <param name="postdata"></param>
    /// <param name="error_code"></param>
    /// <returns></returns>
    IEnumerator DiaLogPost(string uri, string postdata, Action<string> error_code)
    {
        WWWForm form = new WWWForm();
        Dictionary<string, string> header = form.headers;
        header["Content-Type"] = "application/json; charset=utf-8";

        using (WWW www = new WWW(uri, Encoding.UTF8.GetBytes(postdata), header))
        {
            yield return www;
            if (www.error != null)
            {
                yield return www.error;
            }
            else
            {
                Debug.Log(www.text);
                JsonData resData = JsonMapper.ToObject(www.text);
                if (error_code != null)
                {
                    double errCode = resData["error_code"].ToString().ToDouble();
                    if (errCode != 0 && error_code != null)
                    {
                        error_code(resData["error_msg"].ToString());
                        yield break;
                    }
                    if (QueryCallRes != null)
                    {
                        QueryCallRes(resData["result"]);
                    }
                }
            }
        }
    }
    #endregion

    #region  获取和刷新AccessToken  (最终建议在server端获取)

    /// <summary>
    /// 获取accesstoken的POST请求
    /// </summary>
    /// <param name="url"></param>
    /// <param name="form"></param>
    /// <param name="getResult"></param>
    /// <returns></returns>
    private IEnumerator GetTokenPostUrl(string url, WWWForm form, Action<string> getResult)
    {
        using (UnityWebRequest www = UnityWebRequest.Post(url, form))
        {
            yield return www.SendWebRequest();

            if (www.isNetworkError)
            {
                yield return www.error;
            }
            else
            {
                if (www.isDone)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("回调:{0}", www.downloadHandler.text);
                    Debug.Log("sb:" + sb);
                    getResult(www.downloadHandler.text);
                }
            }
        }
    }


    /// <summary>
    /// 获取token
    /// </summary>
    /// <param name="getResult"></param>
    /// <returns></returns>
    IEnumerator GetToken(Action<string> getResult)
    {
        WWWForm form = new WWWForm();
        form.AddField("grant_type", "client_credentials");
        form.AddField("client_id", API_KEY);
        form.AddField("client_secret", SECRET_KEY);
        yield return StartCoroutine(GetTokenPostUrl(GetAccessTokenUrl, form, getResult));
    }

    private bool isGetAccessToken = false;
    /// <summary>
    /// 获取Token
    /// </summary> 
    /// <returns></returns>
    void GetAccessToken()
    {
        if (isGetAccessToken)
        {
            return;
        }
        StartCoroutine(GetToken((str) =>
        {
            LitJson.JsonData data = LitJson.JsonMapper.ToObject(str);
            accessToken = data["access_token"].ToString();
            isGetAccessToken = true;
        }));
    }
  
    #endregion
}

 

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值