文/云圖

大家好,我是云圖。 之前項目有個需求要做一個簡單的siri類似的問答系統(tǒng),經(jīng)過一番周折,終于還是實現(xiàn)出來了,軟件不單可以在pc上面運行,也可以打包到安卓,ios平臺,真正實現(xiàn)一鍵跨平臺打包。

現(xiàn)在我們先說一些實現(xiàn)的思路,所謂問答系統(tǒng),第一步就是用戶首先說一句話,然后我們的軟件把聽到的話轉換成文字。那現(xiàn)在問題有了,第二步我們就需要一個地方,把我們的問題文字轉化成我們軟件回答的答案內(nèi)容。第三步就是把要回答的文字讀出來。

思路有了,開始動手,首先,我們把用戶輸入的語音,要轉成文字,經(jīng)過我?guī)讉€挑選,我發(fā)現(xiàn)百度語音和訊飛語音都不錯,只不過訊飛語音的接入麻煩了點,所以就采用了百度的語音識別
?

  1. private string token; //access_token
  2. private string cuid = 隨便寫的d; //用戶標識
  3. private string format = pcm; //語音格式
  4. private int rate = 8000; //采樣率
  5. private int channel = 1; //聲道數(shù)
  6. private string speech; //語音數(shù)據(jù),進行base64編碼
  7. private int len; //原始語音長度
  8. private string lan = zh; //語種
  9. private string grant_Type = client_credentials;
  10. private string client_ID = 9152186; //百度appkey
  11. private string client_Secret = 14c703ce0f900eae40e95b2cdd564472; //百度Secret Key
  12. private string baiduAPI = http://vop.baidu.com/server_api;
  13. private string getTokenAPIPath =
  14. https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentialsclient_id=ekGb1G5XHY4BIVSA8nLzX5cAclient_secret=14c703ce0f900eae40e95b2cdd564472;
  15. private Byte[] clipByte;
  16. /// <summary>
  17. /// 轉換出來的TEXT
  18. /// </summary>
  19. public static string audioToString;
  20. private AudioSource aud;
  21. private int audioLength;//錄音的長度
  22. public void StartRecord()
  23. {
  24. Debug.Log(開始說話);
  25. if (Microphone.devices.Length == 0) return;
  26. Microphone.End(null);
  27. aud.clip = Microphone.Start(null, false, 10, rate);
  28. }
  29. public void EndRecord()
  30. {
  31. Debug.Log(結束說話);
  32. int lastPos = Microphone.GetPosition(null);
  33. if (Microphone.IsRecording(null))
  34. audioLength = lastPos / rate;//錄音時長
  35. else
  36. audioLength = 10;
  37. Microphone.End(null);
  38. clipByte = GetClipData();
  39. len = clipByte.Length;
  40. speech = Convert.ToBase64String(clipByte);
  41. StartCoroutine(GetToken(getTokenAPIPath));
  42. StartCoroutine(GetAudioString(baiduAPI));
  43. }
  44. /// <summary>
  45. /// 把錄音轉換為Byte[]
  46. /// </summary>
  47. /// <returns></returns>
  48. public Byte[] GetClipData()
  49. {
  50. if (aud.clip == null)
  51. {
  52. Debug.LogError(錄音數(shù)據(jù)為空);
  53. return null;
  54. }
  55. float[] samples = new float[aud.clip.samples];
  56. aud.clip.GetData(samples, 0);
  57. Byte[] outData = new byte[samples.Length * 2];
  58. int rescaleFactor = 32767; //to convert float to Int16
  59. for (int i = 0; i < samples.Length; i)
  60. {
  61. short temshort = (short)(samples[i] * rescaleFactor);
  62. Byte[] temdata = System.BitConverter.GetBytes(temshort);
  63. outData[i * 2] = temdata[0];
  64. outData[i * 2 1] = temdata[1];
  65. }
  66. if (outData == null outData.Length <= 0)
  67. {
  68. Debug.LogError(錄音數(shù)據(jù)為空);
  69. return null;
  70. }
  71. return outData;
  72. }
  73. /// <summary>
  74. /// 獲取百度用戶令牌
  75. /// </summary>
  76. /// <param name=url>獲取的url</param>
  77. /// <returns></returns>
  78. private IEnumerator GetToken(string url)
  79. {
  80. WWW getTW = new WWW(url);
  81. yield return getTW;
  82. if (getTW.isDone)
  83. {
  84. if (getTW.error == null)
  85. {
  86. token = getTW.text;
  87. StartCoroutine(GetAudioString(baiduAPI));
  88. }
  89. else
  90. {
  91. Debug.LogError(獲取令牌出錯 getTW.error);
  92. }
  93. }
  94. else
  95. {
  96. Debug.LogError(下載出錯 getTW.error);
  97. }
  98. }
  99. /// <summary>
  100. /// 把語音轉換為文字
  101. /// </summary>
  102. /// <param name=url></param>
  103. /// <returns></returns>
  104. private IEnumerator GetAudioString(string url)
  105. {
  106. JsonWriter jw = new JsonWriter();
  107. jw.WriteObjectStart();
  108. jw.WritePropertyName(format);
  109. jw.Write(format);
  110. jw.WritePropertyName(rate);
  111. jw.Write(rate);
  112. jw.WritePropertyName(channel);
  113. jw.Write(channel);
  114. jw.WritePropertyName(token);
  115. jw.Write(token);
  116. jw.WritePropertyName(cuid);
  117. jw.Write(cuid);
  118. jw.WritePropertyName(len);
  119. jw.Write(len);
  120. jw.WritePropertyName(speech);
  121. jw.Write(speech);
  122. jw.WriteObjectEnd();
  123. WWW getASW = new WWW(url, Encoding.Default.GetBytes(jw.ToString()));
  124. yield return getASW;
  125. if (getASW.isDone)
  126. {
  127. if (getASW.error == null)
  128. {
  129. JsonData getASWJson = JsonMapper.ToObject(getASW.text);
  130. if (getASWJson[err_msg].ToString() == success.)
  131. {
  132. audioToString = getASWJson[result][0].ToString();
  133. if (audioToString.Substring(audioToString.Length - 1) == ,)
  134. audioToString = audioToString.Substring(0, audioToString.Length - 1);
  135. Debug.Log(說話的問題是: audioToString);
  136. GetAnswer(audioToString);
  137. }
  138. else
  139. {
  140. Debug.LogWarning(沒有成功: getASWJson[err_msg].ToString());
  141. }
  142. }
  143. else
  144. {
  145. Debug.LogError(getASW.error);
  146. }
  147. }
  148. }


我相信到這一步很多做類似項目的也有不少人做到了,可就是這里沒辦法做下去了,為什么呢,因為要用unity把網(wǎng)絡的音頻下載下來播放是非常麻煩的事情,我至今都沒找到辦法,就算用c#的辦法解決了,可是安卓和ios呢,根本調(diào)用不了,再者就是就算你下載下來了,unity好像沒有提供外部播放音頻的功能,我不知道是我能力不足還是unity的問題,感覺很基本的事情居然沒有解決方案。自我懷疑中。。。。

你可能要問了,那么有沒有一種辦法能解決這個多平臺播放音頻的問題呢? 當然有了,我用了FMOD這個插件,可以直接播放網(wǎng)頁的在線音頻,用了一個插件集成進來,最后一步就把網(wǎng)頁音頻地址傳進去,就解決了播放的問題,而且是跨平臺的,ios ,安卓,pc都能用。

?

?

  1. //要播放的語音文字
    • 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=zhcuid=隨便寫的ctp=1tok= token;//
                    • string[] arrPunc = { ,, 。, ”, ;, “, };
                      • for (int i = 0; i < arrPunc.Length; i)
                        • {
                          • //用空白字符來替換指定的標點符號,也就相當于刪除掉了標點符號
                            • AudioUrl = AudioUrl.Replace(arrPunc[i], );
                              • }
                                • asDemo.SetUrlContext(AudioUrl);
                                  • asDemo.OnPlay();
                                    • }
復制代碼
就這么點代碼,當初找不到方案的時候頭疼了2個星期。 好在在不放棄的堅持下還是搞定了,中間走了不少彎路,好在有 MemoryC 大神的幫助下, 也一個個解決了,為 MemoryC大神打call 我把這三步驟已經(jīng)縮減到一個類里面,方便大家查閱,提一下目前這個功能的一點短處,就是說完話以后要盡快點結束,讓語音不浪費那么多空間, 增快識別速度,最快的時候可以在2秒內(nèi)讀出答案,網(wǎng)速好的話比較好。我測試在安卓讀的最快,然后是pc,最慢是ios,測試的機器是iphone5,不知道和這個有沒有關系。再說點這個東西的拓展,比如一些項目有一些運行了windows系統(tǒng)的機器人,展廳的一些全息 投影之類的項目,都可以接入這個功能,讓項目更有可玩性。

via:GAD

聲明:游資網(wǎng)登載此文出于傳遞信息之目的,絕不意味著游資網(wǎng)贊同其觀點或證實其描述。

銳亞教育

銳亞教育,游戲開發(fā)論壇|游戲制作人|游戲策劃|游戲開發(fā)|獨立游戲|游戲產(chǎn)業(yè)|游戲研發(fā)|游戲運營| unity|unity3d|unity3d官網(wǎng)|unity3d 教程|金融帝國3|8k8k8k|mcafee8.5i|游戲蠻牛|蠻牛 unity|蠻牛