开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:1963

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 2140|回复: 113

[云图] unity制作一个Siri问答软件

  [复制链接]  [移动端链接]
排名
305
昨日变化
1

45

主题

375

帖子

4414

积分

Rank: 9Rank: 9Rank: 9

UID
42814
好友
35
蛮牛币
1582
威望
0
注册时间
2014-8-31
在线时间
1368 小时
最后登录
2017-11-19

专栏作家

QQ
发表于 2017-10-18 15:27:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

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

   现在我们先说一些实现的思路,所谓问答系统,第一步就是用户首先说一句话,然后我们的软件把听到的话转换成文字。那现在问题有了,
第二步我们就需要一个地方,把我们的问题文字转化成我们软件回答的答案内容。
第三步就是把要回答的文字读出来。
   思路有了,开始动手,首先,我们把用户输入的语音,要转成文字,经过我几个挑选,我发现百度语音和讯飞语音都不错,只不过讯飞语音的接入麻烦了点,
所以就采用了百度的语音识别
[C#] 纯文本查看 复制代码
    #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#] 纯文本查看 复制代码
    #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);
            }
        }
    }


到这里我们就获取到我们要回答用户答案的音频了,回答的答案特别骚气。 QQ截图20171018150926.jpg 我相信到这一步很多做类似项目的也有不少人做到了,可就是这里没办法做下去了,为什么呢,
因为要用unity把网络的音频下载下来播放是非常麻烦的事情,我至今都没找到办法,就算用c#的办法解决了,可是安卓和ios呢,根本调用不了,再者就是就算你下载下来了,unity好像没有提供外部播放音频的功能,我不知道是我能力不足还是unity的问题,感觉很基本的事情居然没有解决方案。自我怀疑中。。。。
   你可能要问了,那么有没有一种办法能解决这个多平台播放音频的问题呢? 当然有了,我用了FMOD这个插件,可以直接播放网页的在线音频,
用了一个插件集成进来,最后一步就把网页音频地址传进去,就解决了播放的问题,而且是跨平台的,ios ,安卓,pc都能用。
[C#] 纯文本查看 复制代码
    #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系统的机器人,展厅的一些全息 投影之类的项目,都可以接入这个功能,
让项目更有可玩性。基本就是这些,
   和往常一样,底下提供源码,这次收费贵一些,筛选出帮助用到这个项目的朋友


AudioAllPlatform.rar

24 MB, 下载次数: 911

售价: 30 蛮牛币  [记录]

评分

参与人数 7鲜花 +17 收起 理由
mrsix + 2 很给力!
longlongSMU + 2 亲测可用 厉害了我的哥
skdy哭着笑 + 5 很给力!
Masquerader + 2 吊炸天
lixiaobai + 2 很给力!
狼之独步 + 2 很给力!
清风 + 2

查看全部评分


回复

使用道具 举报

排名
3
昨日变化

5625

主题

6093

帖子

2万

积分

Rank: 16

UID
1231
好友
185
蛮牛币
13551
威望
30
注册时间
2013-7-29
在线时间
2785 小时
最后登录
2017-11-17

社区QQ达人活力之星原创精华达人突出贡献奖财富之证游戏蛮牛QQ群会员蛮牛妹VIP

发表于 2017-10-18 16:27:02 | 显示全部楼层
厉害了

跟我念“站长妹纸萌萌哒!”我说站长,你说YO!爱你们么么哒~
回复

使用道具 举报

7日久生情
1666/5000
排名
1893
昨日变化

11

主题

370

帖子

1666

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
148830
好友
3
蛮牛币
2555
威望
0
注册时间
2016-5-17
在线时间
689 小时
最后登录
2017-11-10
发表于 2017-10-18 17:58:09 | 显示全部楼层
为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗为什么楼上的妹子可以三个字回复 性别歧视吗

评分

参与人数 1鲜花 +5 收起 理由
XXHH + 5

查看全部评分


我一个人走走停停冷暖自知自始自终自给
回复 支持 2 反对 0

使用道具 举报

5熟悉之中
587/1000
排名
5774
昨日变化
1

6

主题

269

帖子

587

积分

Rank: 5Rank: 5

UID
214924
好友
1
蛮牛币
1146
威望
0
注册时间
2017-3-28
在线时间
126 小时
最后登录
2017-11-18
发表于 2017-10-18 17:59:30 | 显示全部楼层
66666666666666666666666666

回复 支持 反对

使用道具 举报

2初来乍到
115/150
排名
11201
昨日变化
3

0

主题

36

帖子

115

积分

Rank: 2Rank: 2

UID
58148
好友
1
蛮牛币
68
威望
0
注册时间
2014-11-28
在线时间
17 小时
最后登录
2017-11-15
发表于 2017-10-18 18:25:56 | 显示全部楼层
默默的点个赞,只为楼主的风骚走位和极限操作,黄天不负苦心人,终于收到两个蛮牛币~~

回复 支持 反对

使用道具 举报

5熟悉之中
923/1000
排名
2330
昨日变化

4

主题

146

帖子

923

积分

Rank: 5Rank: 5

UID
86759
好友
5
蛮牛币
3226
威望
0
注册时间
2015-3-29
在线时间
287 小时
最后登录
2017-11-18
发表于 2017-10-18 18:32:31 | 显示全部楼层
讲解很细致,值得学习,多谢分享

回复 支持 反对

使用道具 举报

5熟悉之中
769/1000
排名
6146
昨日变化
1

1

主题

247

帖子

769

积分

Rank: 5Rank: 5

UID
24956
好友
1
蛮牛币
1798
威望
0
注册时间
2014-5-14
在线时间
355 小时
最后登录
2017-11-19

VIP

发表于 2017-10-18 20:09:02 | 显示全部楼层
舅服你!谢谢分享!!!!!
[发帖际遇]: 狼之独步 乐于助人,奖励 2 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

排名
53168
昨日变化
21

0

主题

13

帖子

21

积分

Rank: 1

UID
116813
好友
0
蛮牛币
5
威望
0
注册时间
2015-8-5
在线时间
6 小时
最后登录
2017-10-19
发表于 2017-10-18 23:20:22 | 显示全部楼层
有水準 厲害
[发帖际遇]: 一个袋子砸在了 dpdp3445 头上,dpdp3445 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

6蛮牛粉丝
1174/1500
排名
6764
昨日变化
72

2

主题

858

帖子

1174

积分

Rank: 6Rank: 6Rank: 6

UID
241666
好友
0
蛮牛币
4574
威望
0
注册时间
2017-9-6
在线时间
164 小时
最后登录
2017-11-20
发表于 2017-10-19 08:22:05 来自Mobile--- | 显示全部楼层
感谢分享

回复

使用道具 举报

4四处流浪
397/500
排名
5411
昨日变化
1

0

主题

86

帖子

397

积分

Rank: 4

UID
226471
好友
0
蛮牛币
604
威望
0
注册时间
2017-6-12
在线时间
111 小时
最后登录
2017-11-18
发表于 2017-10-19 08:58:48 | 显示全部楼层
感谢楼主的分享,大赞!

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1183/1500
排名
2175
昨日变化

15

主题

185

帖子

1183

积分

Rank: 6Rank: 6Rank: 6

UID
131349
好友
2
蛮牛币
325
威望
0
注册时间
2015-12-9
在线时间
465 小时
最后登录
2017-11-14
发表于 2017-10-19 08:59:05 | 显示全部楼层
厉害  厉害  感谢分享

回复 支持 反对

使用道具 举报

4四处流浪
487/500
排名
4141
昨日变化
1

0

主题

73

帖子

487

积分

Rank: 4

UID
193740
好友
0
蛮牛币
577
威望
0
注册时间
2016-12-18
在线时间
140 小时
最后登录
2017-11-17
发表于 2017-10-19 09:02:17 | 显示全部楼层
真真的厉害
[发帖际遇]: unity_l老猫 捡了钱没交公 蛮牛币 降了 1 . 幸运榜 / 衰神榜

回复

使用道具 举报

5熟悉之中
570/1000
排名
5195
昨日变化
2

6

主题

236

帖子

570

积分

Rank: 5Rank: 5

UID
176358
好友
0
蛮牛币
182
威望
0
注册时间
2016-11-4
在线时间
118 小时
最后登录
2017-11-16
发表于 2017-10-19 09:08:54 | 显示全部楼层
66666666666

回复

使用道具 举报

6蛮牛粉丝
1262/1500
排名
998
昨日变化

0

主题

107

帖子

1262

积分

Rank: 6Rank: 6Rank: 6

UID
20073
好友
0
蛮牛币
2168
威望
0
注册时间
2014-4-3
在线时间
267 小时
最后登录
2017-10-31
发表于 2017-10-19 09:16:05 | 显示全部楼层
赞一个赞一个赞一个赞一个赞一个赞一个赞一个赞一个赞一个赞一个赞一个

回复 支持 反对

使用道具 举报

4四处流浪
351/500
排名
8444
昨日变化
2

4

主题

56

帖子

351

积分

Rank: 4

UID
174269
好友
0
蛮牛币
180
威望
0
注册时间
2016-10-9
在线时间
185 小时
最后登录
2017-11-10
发表于 2017-10-19 09:17:38 | 显示全部楼层
厉害了,学习学习

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表