打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【新提醒】【unity制作一个Siri问答软件】
大家好,我是云图。 之前项目有个需求要做一个简单的siri类似的问答系统,经过一番周折,终于还是实现出来了,软件不单可以在pc上面运行,也可以打包到安卓,ios平台,真正实现一键跨平台打包。

   现在我们先说一些实现的思路,所谓问答系统,第一步就是用户首先说一句话,然后我们的软件把听到的话转换成文字。那现在问题有了,
第二步我们就需要一个地方,把我们的问题文字转化成我们软件回答的答案内容。
第三步就是把要回答的文字读出来。
   思路有了,开始动手,首先,我们把用户输入的语音,要转成文字,经过我几个挑选,我发现百度语音和讯飞语音都不错,只不过讯飞语音的接入麻烦了点,
所以就采用了百度的语音识别
[C#] 纯文本查看 复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#region 录制声音转化为文字
private string token;                           //access_token
private string cuid = "随便写的d";        //用户标识
private string format = "pcm";                  //语音格式
private int rate = 8000;                        //采样率
private int channel = 1;                        //声道数
private string speech;                          //语音数据,进行base64编码
private int len;                                //原始语音长度
private string lan = "zh";                      //语种
private string grant_Type = "client_credentials";
private string client_ID = "9152186";                       //百度appkey
private string client_Secret = "14c703ce0f900eae40e95b2cdd564472";                   //百度Secret Key
private string baiduAPI = "http://vop.baidu.com/server_api";
private string getTokenAPIPath =
    "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=ekGb1G5XHY4BIVSA8nLzX5cA&client_secret=14c703ce0f900eae40e95b2cdd564472";
private Byte[] clipByte;
/// <summary>
/// 转换出来的TEXT
/// </summary>
public static string audioToString;
private AudioSource aud;
private int audioLength;//录音的长度
public void StartRecord()
{
    Debug.Log("开始说话");
       
    if (Microphone.devices.Length == 0) return;
    Microphone.End(null);
    aud.clip = Microphone.Start(null, false, 10, rate);
}
  
public void EndRecord()
{
    Debug.Log("结束说话");
    int lastPos = Microphone.GetPosition(null);
    if (Microphone.IsRecording(null))
        audioLength = lastPos / rate;//录音时长 
    else
        audioLength = 10;
    Microphone.End(null);
    clipByte = GetClipData();
    len = clipByte.Length;
    speech = Convert.ToBase64String(clipByte);
    StartCoroutine(GetToken(getTokenAPIPath));
    StartCoroutine(GetAudioString(baiduAPI));
}
/// <summary>
/// 把录音转换为Byte[]
/// </summary>
/// <returns></returns>
public Byte[] GetClipData()
{
    if (aud.clip == null)
    {
        Debug.LogError("录音数据为空");
        return null;
    }
    float[] samples = new float[aud.clip.samples];
    aud.clip.GetData(samples, 0);
    Byte[] outData = new byte[samples.Length * 2];
    int rescaleFactor = 32767; //to convert float to Int16  
    for (int i = 0; i < samples.Length; i++)
    {
        short temshort = (short)(samples[i] * rescaleFactor);
      [/i]  Byte[] temdata = System.BitConverter.GetBytes(temshort);
        outData[i * 2] = temdata[0];
        outData[i * 2 + 1] = temdata[1];
    }
    if (outData == null || outData.Length <= 0)
    {
        Debug.LogError("录音数据为空");
        return null;
    }
      
    return outData;
}
/// <summary>
/// 获取百度用户令牌
/// </summary>
/// <param name="url">获取的url</param>
/// <returns></returns>
private IEnumerator GetToken(string url)
{
    WWW getTW = new WWW(url);
    yield return getTW;
    if (getTW.isDone)
    {
        if (getTW.error == null)
        {
            token = getTW.text;
            StartCoroutine(GetAudioString(baiduAPI));
        }
        else
        {
            Debug.LogError("获取令牌出错" + getTW.error);
        }
    }
    else
    {
        Debug.LogError("下载出错" + getTW.error);
    }
}
/// <summary>
/// 把语音转换为文字
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private IEnumerator GetAudioString(string url)
{
    JsonWriter jw = new JsonWriter();
    jw.WriteObjectStart();
    jw.WritePropertyName("format");
    jw.Write(format);
    jw.WritePropertyName("rate");
    jw.Write(rate);
    jw.WritePropertyName("channel");
    jw.Write(channel);
    jw.WritePropertyName("token");
    jw.Write(token);
    jw.WritePropertyName("cuid");
    jw.Write(cuid);
    jw.WritePropertyName("len");
    jw.Write(len);
    jw.WritePropertyName("speech");
    jw.Write(speech);
    jw.WriteObjectEnd();
    WWW getASW = new WWW(url, Encoding.Default.GetBytes(jw.ToString()));
    yield return getASW;
    if (getASW.isDone)
    {
        if (getASW.error == null)
        {
            JsonData getASWJson = JsonMapper.ToObject(getASW.text);
            if (getASWJson["err_msg"].ToString() == "success.")
            {
                audioToString = getASWJson["result"][0].ToString();
                if (audioToString.Substring(audioToString.Length - 1) == ",")
                    audioToString = audioToString.Substring(0, audioToString.Length - 1);
                Debug.Log("说话的问题是:" + audioToString);
                GetAnswer(audioToString);
            }
            else
            {
                Debug.LogWarning("没有成功:" + getASWJson["err_msg"].ToString());
            }
        }
        else
        {
            Debug.LogError(getASW.error);
        }
    }
}
#endregion



首先你要去百度语音官网申请一个开发者权限,这些细节在这里就不讨论了,很简单。重要的就是两个参数 client_ID和client_Secret 的内容,
填写到获取token的网页中发上去,获取到token后百度就知道我们是哪个用户哪个软件在调用语音识别了。这里在ios运行的时候有时候会显示获取不到token,
原因是苹果不给我们这样发信息获取内容,说不安全,需要用其他办法。其他办法有很多,最笨的方法就是提前获取到token,然后写死在程序,坏处就是一个月会变一次,比较麻烦。
好了,现在我们的语音已经传上百度然后转成文字下来, 下一步我采用的是图灵的文字问答系统。图灵这个做的也是非常好用的,
直接把我们的问题文字写到url里面打开链接,就可以返回答案了。
[C#] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#region 将文字转出得到回答答案
private string url = "http://www.tuling123.com/openapi/api?key=d91b25b8866fef13f82cd28c0d523c8a&info=";
private string QuestionUrl= "http://www.tuling123.com/openapi/api?key=d91b25b8866fef13f82cd28c0d523c8a&info=";
public string msg = "";
/// <summary>
/// 获取图灵返回的答案
/// </summary>
/// <param name="msg">提问的问题</param>
public void GetAnswer(string msg)
{
    StartCoroutine(GetTuLingtoken(url + msg));
}
private string TuLingtoken = "";
/// <summary>
/// 图灵的问答系统
/// </summary>
/// <param name="Question">要问的问题</param>
/// <returns></returns>
private IEnumerator GetTuLingtoken(string url)
{
    WWW getTW = new WWW(url);
    yield return getTW;
    if (getTW.isDone)
    {
        if (getTW.error == null)
        {
            TuLingtoken = getTW.text;
            TuLingtoken = JsonMapper.ToObject(getTW.text)["text"].ToString();
            PlayAudio(TuLingtoken);
        }
        else
        {
            Debug.LogError(getTW.error);
        }
    }
}


到这里我们就获取到我们要回答用户答案的音频了,回答的答案特别骚气。
我相信到这一步很多做类似项目的也有不少人做到了,可就是这里没办法做下去了,为什么呢,
因为要用unity把网络的音频下载下来播放是非常麻烦的事情,我至今都没找到办法,就算用c#的办法解决了,可是安卓和ios呢,根本调用不了,再者就是就算你下载下来了,unity好像没有提供外部播放音频的功能,我不知道是我能力不足还是unity的问题,感觉很基本的事情居然没有解决方案。自我怀疑中。。。。
   你可能要问了,那么有没有一种办法能解决这个多平台播放音频的问题呢? 当然有了,我用了FMOD这个插件,可以直接播放网页的在线音频,
用了一个插件集成进来,最后一步就把网页音频地址传进去,就解决了播放的问题,而且是跨平台的,ios ,安卓,pc都能用。
[C#] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
    #region 开始播放文字答案
    //要播放的语音文字
    public string AudioMsg = "";
    private string urlForward = @"http://tsn.baidu.com/text2audio?tex=";
    public string AudioUrl = "";
    public AudioStreamDemo asDemo;
    public void PlayAudio(string content)
    {
        Debug.Log(content);
        AudioUrl = @"http://tsn.baidu.com/text2audio?tex=" + content  + "&lan=zh&cuid=随便写的&ctp=1&tok=" + token;//
        string[] arrPunc = { ",", "。", "”", ";", "“", " " };
        for (int i = 0; i < arrPunc.Length; ++i)
        {
            //用空白字符来替换指定的标点符号,也就相当于删除掉了标点符号
[i]            AudioUrl = AudioUrl.Replace(arrPunc, "%20");
        
        asDemo.SetUrlContext(AudioUrl);
        asDemo.OnPlay();
    }
    #endregion




就这么点代码,当初找不到方案的时候头疼了2个星期。 好在在不放弃的坚持下还是搞定了,中间走了不少弯路,好在有 MemoryC 大神的帮助下,
也一个个解决了,为 MemoryC大神打call
     我把这三步骤已经缩减到一个类里面,方便大家查阅,提一下目前这个功能的一点短处,就是说完话以后要尽快点结束,让语音不浪费那么多空间,
增快识别速度,最快的时候可以在2秒内读出答案,网速好的话比较好。我测试在安卓读的最快,然后是pc,最慢是ios,测试的机器是iphone5,
不知道和这个有没有关系。再说点这个东西的拓展,比如一些项目有一些运行了windows系统的机器人,展厅的一些全息 投影之类的项目,都可以接入这个功能,
让项目更有可玩性。基本就是这些,
   和往常一样,底下提供源码,这次收费贵一些,筛选出帮助用到这个项目的朋友


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
实现shiro多方式登录系统
微信开发总结 三
微信公众账号开发教程第3篇-开发模式启用及接口配置
使用ScriptableObject创建.asset文件
Spring MVC防御CSRF、XSS和SQL注入攻击
微信公众平台开发教程(五)自定义菜单(含实例源码)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服