續(xù)《是時(shí)候開(kāi)始用C#快速開(kāi)發(fā)移動(dòng)應(yīng)用了》刷屏之后,把C#開(kāi)發(fā)移動(dòng)應(yīng)用的技術(shù) => Xamarin,在這里和大家做一個(gè)分享!
語(yǔ)音合成:也被稱(chēng)為文本轉(zhuǎn)換技術(shù)(TTS),它是將計(jì)算機(jī)自己產(chǎn)生的、或外部輸入的文字信息轉(zhuǎn)變?yōu)榭梢月?tīng)得懂的、流利的口語(yǔ)輸出的技術(shù)。
技術(shù)選型:語(yǔ)音合成初步選擇有兩個(gè),一是訊飛、二是百度。
因?yàn)槭褂玫氖荴amarin開(kāi)發(fā)在對(duì)接訊飛的時(shí)候android綁定上有些問(wèn)題,攻克不了,訊飛對(duì)于Xamarin的態(tài)度也是觀(guān)望,可能是因?yàn)閲?guó)內(nèi)使用Xamarin的比較少。先來(lái)說(shuō)說(shuō)訊飛和百度語(yǔ)音各自的優(yōu)缺點(diǎn):
1.訊飛支持的字節(jié)數(shù)更多8xxx字節(jié),具體的值忘記了,反正4k的漢字不成問(wèn)題;百度支持的字節(jié)數(shù)是1024個(gè)字節(jié)。
2.訊飛sdk比較小,對(duì)接百度的sdk比較大,因?yàn)榘俣日Z(yǔ)音的離線(xiàn)在線(xiàn)sdk在一個(gè)里面,大概有10幾兆所以,為了避免安裝包過(guò)大,所有只能使用百度的REST方式了。
3.訊飛語(yǔ)音sdk在Xamarin.Android綁定上有問(wèn)題,暫時(shí)沒(méi)有攻破,在Xamarin.Ios上打調(diào)試版也有問(wèn)題,設(shè)置成Release上勉強(qiáng)可以使用。
綜合上面的原因,所以選擇了百度的REST作為對(duì)接語(yǔ)音合成的技術(shù)實(shí)現(xiàn)。
調(diào)用流程:1.獲取語(yǔ)音合成密碼access_token;2.帶上秘鑰和文本請(qǐng)求api返回?cái)?shù)據(jù)流文件;
核心流程方案
步驟一:獲取access_token
請(qǐng)求地址:
參數(shù)說(shuō)明:
grant_type:必須參數(shù),固定為“client_credentials”;
client_id:必須參數(shù),應(yīng)用的 API Key;
client_secret:必須參數(shù),應(yīng)用的 Secret Key;
返回結(jié)果:
{
"access_token": "24.6a0d0ee7cc62446cf0a5fbc9d6204321.2592000.1498802594.282335-9044454",
"session_key": "9mzdDZfH3RYNxaNq9Kb6RP5JqsthOmat9g4guVLvbm2YymOWPxDiq3vQvdjZrByadZp4qou9F4wYH2dfptIjxdPwzmKH",
"scope": "public audio_tts_post wise_adapt lebo_resource_base lightservice_public hetu_basic lightcms_map_poi kaidian_kaidian wangrantest_test wangrantest_test1 bnstest_test1 bnstest_test2 vis-classify_flower",
"refresh_token": "25.df4ee25f807fe4fc8d0e025dc7b8549e.315360000.1811570594.282335-9044454",
"session_secret": "237af35e4de40ce40e74951d5e187a18",
"expires_in": 2592000
}
注意:access_token有效期30天。
步驟二:合成音頻
請(qǐng)求地址:
注意:參數(shù)都需要經(jīng)過(guò)兩次 URLENCODE 操作。如果是直接在瀏覽器地址欄輸入則不需要。
返回結(jié)果:
如果合成成功,下行數(shù)據(jù)為二進(jìn)制語(yǔ)音文件,具體header信息 Content-Type:audio/mp3;如果合成出現(xiàn)錯(cuò)誤,則會(huì)返回json結(jié)果,具體header信息為:Content-Type:application/json。其中sn數(shù)據(jù)主要用于DEBUG追查問(wèn)題,如果出現(xiàn)問(wèn)題,可以提供sn幫助確認(rèn)問(wèn)題。
錯(cuò)誤實(shí)例為:
{"err_no":500,"err_msg":"notsupport.","sn":"abcdefgh","idx":1}
錯(cuò)誤碼解釋
錯(cuò)誤碼 | 含義 |
500 | 不支持輸入 |
501 | 輸入?yún)?shù)不正確 |
502 | token驗(yàn)證失敗 |
503 | 合成后端錯(cuò)誤 |
注意:合成文本長(zhǎng)度必須小于1024字節(jié),如果本文長(zhǎng)度較長(zhǎng),可以采用多次請(qǐng)求的方式。切忌不可文本長(zhǎng)度超過(guò)限制。
更多官方文檔請(qǐng)?jiān)L問(wèn):http://yuyin.baidu.com/docs
Xamarin調(diào)用核心代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | string url = "http://tsn.baidu.com/text2audio" ; //百度tts請(qǐng)求地址 HttpClient client = new HttpClient(); client.Timeout = new TimeSpan(0, 1, 0); //超時(shí)時(shí)間設(shè)置 Dictionary< string , string > param = new Dictionary< string , string >() { { "lan" , "zh" },{ "ctp" , "1" } //不需要修改的參數(shù) }; param.Add( "tex" , "需要合成的文本內(nèi)容" ); //需要轉(zhuǎn)換的文本內(nèi)容 param.Add( "cuid" , "userid" ); //用戶(hù)唯一標(biāo)識(shí) param.Add( "tok" , "24.6a0d0ee7cc62446cf0a5fbc9d6204321.2592000.1498802594.282335-9044454" ); //access_token,在發(fā)送之前先調(diào)用一次獲取到這個(gè)值 FormUrlEncodedContent content = new FormUrlEncodedContent(param); //post請(qǐng)求參數(shù)設(shè)置對(duì)象 try { HttpResponseMessage x = await client.PostAsync(url, content); if (x.StatusCode == HttpStatusCode.OK) { Stream st = await x.Content.ReadAsStreamAsync(); //路徑保存地址,ios和android各不相同,分別實(shí)現(xiàn),傳遞文件名 string filePath = DependencyService.Get<IResourcesHelper>().GetImageDownLoadPath( "bd_" + DateTime.Now.Ticks + ".mp3" ); using ( var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { st.CopyTo(fileStream); //保存文件 } } else { //todo:請(qǐng)求失敗處理邏輯(警告) } } catch { //todo:異常處理邏輯(警告) } |
相關(guān)技術(shù)文章:
《Xamarin開(kāi)發(fā)筆記—WebView雙項(xiàng)事件調(diào)用》
作者:西安.王磊
出處:http://vipstone.cnblogs.com/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
http://www.cnblogs.com/vipstone/p/6963763.html