续《是时候开始用C#快速开发移动应用了》刷屏之后,把C#开发移动应用的技术 => Xamarin,在这里和大家做一个分享!
语音合成:也被称为文本转换技术(TTS),它是将计算机自己产生的、或外部输入的文字信息转变为可以听得懂的、流利的口语输出的技术。
技术选型:语音合成初步选择有两个,一是讯飞、二是百度。
因为使用的是Xamarin开发在对接讯飞的时候android绑定上有些问题,攻克不了,讯飞对于Xamarin的态度也是观望,可能是因为国内使用Xamarin的比较少。先来说说讯飞和百度语音各自的优缺点:
1.讯飞支持的字节数更多8xxx字节,具体的值忘记了,反正4k的汉字不成问题;百度支持的字节数是1024个字节。
2.讯飞sdk比较小,对接百度的sdk比较大,因为百度语音的离线在线sdk在一个里面,大概有10几兆所以,为了避免安装包过大,所有只能使用百度的REST方式了。
3.讯飞语音sdk在Xamarin.Android绑定上有问题,暂时没有攻破,在Xamarin.Ios上打调试版也有问题,设置成Release上勉强可以使用。
综合上面的原因,所以选择了百度的REST作为对接语音合成的技术实现。
调用流程:1.获取语音合成密码access_token;2.带上秘钥和文本请求api返回数据流文件;
核心流程方案
步骤一:获取access_token
请求地址:
参数说明:
- grant_type:必须参数,固定为“client_credentials”;
- client_id:必须参数,应用的 API Key;
- client_secret:必须参数,应用的 Secret Key;
返回结果:
{
"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天。
步骤二:合成音频
请求地址:
注意:参数都需要经过两次 URLENCODE 操作。如果是直接在浏览器地址栏输入则不需要。
返回结果:
如果合成成功,下行数据为二进制语音文件,具体header信息 Content-Type:audio/mp3;如果合成出现错误,则会返回json结果,具体header信息为:Content-Type:application/json。其中sn数据主要用于DEBUG追查问题,如果出现问题,可以提供sn帮助确认问题。
错误实例为:
{"err_no":500,"err_msg":"notsupport.","sn":"abcdefgh","idx":1}
错误码解释
错误码 |
含义 |
500 |
不支持输入 |
501 |
输入参数不正确 |
502 |
token验证失败 |
503 |
合成后端错误 |
注意:合成文本长度必须小于1024字节,如果本文长度较长,可以采用多次请求的方式。切忌不可文本长度超过限制。
更多官方文档请访问:http://yuyin.baidu.com/docs
Xamarin调用核心代码如下:
string url = "http://tsn.baidu.com/text2audio"; //百度tts请求地址 HttpClient client = new HttpClient(); client.Timeout = new TimeSpan(0, 1, 0); //超时时间设置 Dictionary<string, string> param = new Dictionary<string, string>() { { "lan", "zh" },{ "ctp", "1" } //不需要修改的参数 }; param.Add("tex", "需要合成的文本内容"); //需要转换的文本内容 param.Add("cuid", "userid"); //用户唯一标识 param.Add("tok", "24.6a0d0ee7cc62446cf0a5fbc9d6204321.2592000.1498802594.282335-9044454");//access_token,在发送之前先调用一次获取到这个值 FormUrlEncodedContent content = new FormUrlEncodedContent(param); //post请求参数设置对象 try { HttpResponseMessage x = await client.PostAsync(url, content); if (x.StatusCode == HttpStatusCode.OK) { Stream st = await x.Content.ReadAsStreamAsync(); //路径保存地址,ios和android各不相同,分别实现,传递文件名 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:请求失败处理逻辑(警告) } } catch { //todo:异常处理逻辑(警告) }
Xamarin系列其他推荐