博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
腾讯云语音合成TTS
阅读量:6116 次
发布时间:2019-06-21

本文共 9950 字,大约阅读时间需要 33 分钟。

腾讯云语音合成 C# 示例

按着官方文档的顺序开始写吧。

一、请求 url 拼接

首先的坑点就是url必须是按升序排列进行拼接,不然接下来的鉴权肯定失败

基础链接:

https://aai.qcloud.com/tts/v1/
?

参数:

{    "projectid": "0",    "sub_service_type": "0",    "speech_format": "mp3",    "volume": "3",    "person": "0",    "speed": "0",    "secretid": "AKIDlfdHxN0ntSVt4KPH0xXWnGl21UUFNoO5",    "timestamp": "1484109983",    "expired": "1484113583",    "nonce": "1675199141"}

这里以<appid> = 20170111, <SecretKey>=oaYWFO70LGDmcpfwo8uF1IInayysGtgZ 为例拼接签名原文,则拼接的签名原文为:

https://aai.qcloud.com/tts/v1/20170111?expired=1484113583&nonce=1675199141&person=0&projectid=0&secretid=AKIDlfdHxN0ntSVt4KPH0xXWnGl21UUFNoO5&speech_format=mp3&speed=0&sub_service_type=0&timestamp=1484109983&volume=3

记得 url 一定要排序,不然鉴权肯定会失败的

二、加密

接上一步的结果,我们要去掉协议名 https:// 加上POST(必须是大写)

POSTaai.qcloud.com/tts/v1/20170111?expired=1484113583&nonce=1675199141&person=0&projectid=0&secretid=AKIDlfdHxN0ntSVt4KPH0xXWnGl21UUFNoO5&speech_format=mp3&speed=0&sub_service_type=0&timestamp=1484109983&volume=3

对原文进行加密处理:

Base64Encode(HmacSha1(签名原文, SecretKey))

C#方法示例:

public static string HmacSha1AndBase64(string mk, string secretkey)    {        HMACSHA1 hmacsha1 = new HMACSHA1();        hmacsha1.Key = Encoding.UTF8.GetBytes(secretkey);        byte[] dataBuffer = Encoding.UTF8.GetBytes(mk);        byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer);        return Convert.ToBase64String(hashBytes);    }

最终得到签名串为:

HRCKlbwPhWtVvfGn914qE5O1rwc=

三:Body拼接(需要转换成语音的文本设置)

如果返回 111 错误,那么百分之百是这里拼接出错

multipart/form-data;的格式就不介绍了,网上一大堆

-------------------123456abcdefgContent-Disposition: form-data; name="text"; filename="file1.txt"这里是你需要转换的内容-------------------123456abcdefg--

这里的 -----------------123456abcdefg 是边界符,以 --自定义字符串 开头,以 --自定义字符串-- 结尾。

name="text" 和 filename="file1.txt" 都是任意取名

Demo代码:

#region 语音合成        ///         /// 语音合成        ///         ///         ///         ///         ///         ///         ///         /// 
public string TextToSpeech(string appid, string secretid, string secretkey, string text, string mp3AbsolutePath = "", string mp3Filename = "") { //边界符 var boundary = "-------------------" + DateTime.Now.Ticks.ToString("x"); var url = GetFullUrl(appid, secretid); //创建请求 var webRequest = (HttpWebRequest)WebRequest.Create(url); //设置请求头 SetHeaders(webRequest, url, secretkey, boundary); //将数据写入Body并获取写入后的数据 var strBody = GetRequestBody(boundary, text); //将Body写入到请求流中 WriteRequestStreamFormBody(webRequest, strBody); //获取结果 string responseResult = GetResponseResult(webRequest); var resJson = JObject.Parse(responseResult); if (resJson.Value
("code").Equals("0")) { //转换为mp3保存 Base64ToAudio(resJson.Value
("speech"), mp3AbsolutePath, mp3Filename); } else { //转换失败,具体查看错误码 } return responseResult; } #endregion #region 使用密钥(secretkey)对url进行加密,得到签名 ///
/// 使用密钥(secretkey)对url进行加密,得到签名 /// ///
排序后的url地址 ///
密钥 ///
private string GetAuthorization(string urlSorted, string secretkey) { return HmacSha1AndBase64("POST" + urlSorted.Substring(8),secretkey); } #endregion #region HMACSHA1 & Base64 加密 ///
/// HMACSHA1 & Base64 加密 /// ///
原文 ///
密钥 ///
public static string HmacSha1AndBase64(string mk, string secretkey) { HMACSHA1 hmacsha1 = new HMACSHA1(); hmacsha1.Key = Encoding.UTF8.GetBytes(secretkey); byte[] dataBuffer = Encoding.UTF8.GetBytes(mk); byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); return Convert.ToBase64String(hashBytes); } #endregion #region 获取排序后的完整路径地址 ///
/// 获取排序后的完整路径地址 /// ///
///
///
private string GetFullUrl(string appid, string secretid) { /* * 返回值示例: * * https://aai.qcloud.com/tts/v1/20170111 * ?expired=1484113583 * &nonce=1675199141 * &person=0 * &projectid=0 * &secretid=AKIDlfdHxN0ntSVt4KPH0xXWnGl21UUFNoO5 * &speech_format=mp3 * &speed=0 * &sub_service_type=0 * &timestamp=1484109983 * &volume=3 * */ StringBuilder url = new StringBuilder("https://aai.qcloud.com/tts/v1/" + appid + "?"); SortedDictionary
dic = new SortedDictionary
(); dic.Add("projectid", 0); //腾讯云项目 ID,不填为默认项目,即0,总长度不超过1024字节 dic.Add("sub_service_type", 0); //子服务类型。0:短文本实时合成。目前只支持短文本实时合成 dic.Add("speech_format", "mp3"); //合成语音格式,目前支持MP3格式 dic.Add("volume", 3); //音量,默认为5,取值范围为0-10 dic.Add("person", 0); //发音人,目前仅支持0,女声 dic.Add("speed", 0); //语速,默认值为0,取值范围为-40到40,1表示加速到原来的1.1倍,-1为相对于正常语速放慢1.1倍 dic.Add("secretid", secretid); //官网云API密钥中获得的SecretId dic.Add("timestamp", DateTime.Now.ToUnixDate()); //当前时间戳,是一个符合 UNIX Epoch 时间戳规范的数值,单位为秒 dic.Add("expired", DateTime.Now.AddMinutes(5).ToUnixDate()); //签名的有效期,是一个符合 UNIX Epoch 时间戳规范的数值,单位为秒;expired 必须大于 timestamp 且 expired - timestamp 小于90天 dic.Add("nonce", new Random().Next(10000000, 99999999)); //随机正整数。用户需自行生成,最长10位 foreach (var item in dic) { url.Append(item.Key); url.Append("="); url.Append(item.Value); url.Append("&"); } return url.Remove(url.Length - 1, 1).ToString(); //移除末尾的 & } #endregion #region 设置Header ///
/// 设置Header /// ///
///
///
///
private void SetHeaders(HttpWebRequest webRequest, string url, string secretkey, string boundary) { //设置属性 webRequest.Host = "aai.qcloud.com"; webRequest.Method = "POST"; webRequest.Timeout = 30000; webRequest.ContentType = "multipart/form-data; boundary=" + boundary; webRequest.Headers.Add("Authorization", GetAuthorization(url, secretkey)); } #endregion #region 获取设置文字内容后的Body ///
/// 获取设置文字内容后的Body /// ///
///
///
private string GetRequestBody(string boundary, string text) { //设置需要转语音的文字内容 string strBody = GetTextBody(boundary, text); //在这里可以添加其他的Body内容 //strBody += GetOtherBody(); //设置结尾 strBody += "--" + boundary + "--\r\n"; return strBody; } #endregion #region 获取设置文字内容后的Body段 ///
/// 设置文字内容 /// ///
///
///
private string GetTextBody(string boundary, string text) { return string.Format("--" + boundary + "\r\nContent-Disposition: form-data; name=\"text\"; filename=\"file1.txt\"" + //"\r\nContent-Type: text/plain" + "\r\n\r\n{0}\r\n", text); } #endregion #region 将body流写入到请求流中 ///
/// 将body流写入到请求流中 /// ///
///
private static void WriteRequestStreamFormBody(HttpWebRequest webRequest, string body) { var strBodyBytes = Encoding.UTF8.GetBytes(body); using (var requestStream = webRequest.GetRequestStream()) { requestStream.Write(strBodyBytes, 0, strBodyBytes.Length); } } #endregion #region 获取响应结果 ///
/// 获取响应内容 /// ///
///
private static string GetResponseResult(HttpWebRequest webRequest) { string responseResult; using (var httpWebResponse = (HttpWebResponse)webRequest.GetResponse()) { using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.GetEncoding("utf-8"))) { responseResult = httpStreamReader.ReadToEnd(); } } webRequest.Abort(); return responseResult; } #endregion #region base64转换mp3 ///
/// base64转换mp3 /// ///
///
///
public void Base64ToAudio(string strBase64, string absolutePath = "", string filename = "") { try { absolutePath = (absolutePath != null && !"".Equals(absolutePath.Trim())) ? absolutePath : Server.MapPath("~/audio/"); filename = (filename != null && !"".Equals(filename.Trim())) ? filename : DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".mp3"; byte[] audioByteArray = Convert.FromBase64String(strBase64); using (var mp3File = System.IO.File.Create(absolutePath + filename, audioByteArray.Length)) { mp3File.Write(audioByteArray, 0, audioByteArray.Length); } } catch (Exception ex) { throw ex; } } #endregion

调用代码:

TextToSpeech(appid, secretid, secretkey, "你好,世界!");

代码有些地方封装的欠妥,懒得弄了,先这样写着了,以后看情况重构吧。


腾讯的文档我已经不想吐槽了,可能是刚好赶上了文档的修改时期吧,我刚去看,发现很多地方已经修改了。

转载地址:http://eevka.baihongyu.com/

你可能感兴趣的文章
kubernetes API 访问控制在阿里云容器服务(ACK)上的实践
查看>>
SharePoint 2010 文档管理(三)过期归档工具
查看>>
linux sendmail
查看>>
我的友情链接
查看>>
CentOS 6配置本地YUM源
查看>>
我的友情链接
查看>>
Linux启动流程图解
查看>>
复合赋值语句妙用(a := c):判断结果为null则指定其它值或变量
查看>>
类初始化过程
查看>>
C语言常用小例子
查看>>
我的友情链接
查看>>
javascipt 中this的学习小节
查看>>
IOS开发之相册拾取器UIImagePickerController
查看>>
物化视图初窥
查看>>
NGUI创建Camera参数为Simple 2D的UI UI对象的结构UI Root(2D)
查看>>
终于解决nginx不支持thinkphp路径2问题(正解!!!)
查看>>
Xamarin XAML语言教程构建ControlTemplate控件模板 (二)
查看>>
WebDAV服务漏洞利用工具DAVTest
查看>>
SAP HANA数据库备份方式与工具
查看>>
玩转EXCEL系列-关于打印那些事
查看>>