【技术教程】如何写个小程序,白嫖微软语音合成

大家都知道,我前几个月写了一款极客配音小程序,这里面我对接了5个大厂的语音合成接口,具体也不说了,里边最让我头疼的就是微软,因为一开始考虑到它是花美金的,与其他接口对比,比较贵,所以我就研究了一下,通过抓官网接口,确实能实现白嫖。当然现在我的极客配音小程序也接入了官方正版接口,为什么接正版后面再说,这里主要分享一下我写过的白嫖技术。

图片[1]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

注意:

1、本篇文章适合有技术基础的朋友阅读,如果你不懂技术,就不用往下看了,省的头疼。

2、本篇文章示例代码并非一直可用,因为官方的接口也会有变化,所以主要分享的是方法。

一、抓包

首先要使用官方的接口,当然就是抓官方的数据包了,然后通过模拟官网发包,来调用接口。

网址:https://azure.microsoft.com/zh-cn/products/cognitive-services/text-to-speech/#features

图片[2]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

这个位置,就是官方试用的语音合成,我们右键网页,打开控制台,通过网络功能,抓一下他的合成过程。

图片[3]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

这条websocket链接,就是了,点开查看请求的链接和消息。

图片[4]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

这个是请求的链接,注意,后面有一段是变量,下面再说

图片[5]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

在这条链接的消息里,绿色的,就是我们发出的消息,红色的,前两条字符串没啥用,后面持续发送的二进制消息,就是我们需要的语音信息流。

二、分析消息

既然要模拟,我们就要分析一下消息中的内容,确定那些是固定内容,那些是变量,以便能在实际调用时不踩坑。

图片[6]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

具体的变量我也直接标出来了,三条消息基本都有共同的两个变量,X-RequestId是一个uuidv4字符串,需要自己生成,X-Timestamp是一个ISO 标准的时间戳,格式为2022-12-22T17:47:28.049Z

最后一条消息下面几个就是我们自己控制的变量,name是发音人,可选,具体可选值自己去官网看吧,mstts的style是语气,rate是语速,pitch是语调,后面就是我们要配音的文字了。

注意:上面的请求url中后面有一个X-ConnectionId值也是uuidv4

下面是示例代码:

//生成uuidv4函数
uuidv4() {
	return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
	var r = Math.random() * 16 | 0,
		v = c == 'x' ? r : (r & 0x3 | 0x8);
	return v.toString(16);
	});
}
//获取IOS标准时间
getXTime() {
	return new Date().toISOString();
}

三、模拟请求

利用小程序建立websocket链接还是非常容易的,我们先将请求的地址写好, 将要发送的消息写成三个字符串,放到一个数组中

图片[7]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

截图写法仅供参考,具体写法以你为主

图片[8]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

创建socket链接,并循环将数组中的三条消息发出去!

注意,这里我是在uniapp中写的,你在小程序开发者工具里,将uni换成wx就可以,其他语音自行适配

图片[9]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

这里就厉害了,我们开始接收微软发来的消息,这里判断收到的消息类型,如果是字符串,就像刚刚我们官网抓到的消息,有字符串,先忽略,如果是个对象,那它就是数据流,这里我们需要将它转为字符串,函数代码如下:

//ArrayBuffer转字符串
ab2str(buf) {
	return String.fromCharCode.apply(null, new Uint8Array(buf));
},

转成字符串后,截取掉Path:audio之前的部分,剩下的就是纯语音数据了,记得将这些语音数据存到一个数组中去,因为它会接收到多条数据流,合在一起才是完整的文件,并且要记录一下所有数据流合在一起的byte长度,后面会用到。

//记录所有数据流最终的长度
offset += audioData.byteLength;

最后它结束时,还会发送一个字符串,这个字符串中带有Path:turn.end字段,判断到这条字符串后,关掉socket链接就可以了。

四、合成语音

图片[10]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享

前两行是创建一个文件管理器,创建一个本地文件路径

ArrayBuffer是创建一个字节数组,但注意,这里创建时它便会在内存生成一块区域,并且这个区域的空间大小必须一开始就固定好,否则后期不可更改,所以就用到了上面的记录数据流总长度,来划出一个足够可存放音频流的区域。

Uint8Array将上面的字节数组转为一个可操作的整型数组,下面开始循环的是刚才存入数据流的数组。

还记得上面将数据流转为字符串了吗,这里通过var s = new Uint8Array(arrBuffer[i])将它转回来,并通过result.set(s, n);写入到整型数组中。

set接收的第一个参数是数据流,第二个是它从哪个位置开始写,这样我们又要每次循环记录下写到了哪个位置,再继续写入。

最后的fs.writeFile就是把数据写入mp3文件,最后将得到的文件路径,返回给回调函数。

五、结语

这么一讲实在复杂,已经忘记自己当时踩了多少坑才写下来的,因为小程序并非普通软件一样,对所有系统API有如此好的支持,所以只能一步一步测试,当然还有更好的优化写法,那些就留给各位大佬发挥吧。

最后说下我为啥又接入了官方API,因为官网这个wss口,好像最多支持到一次500多个字左右吧,具体我也忘了,这导致很多用户生成长文本时,就需要分割字符,并循环创建socket链接,就经常出现断链情况,所以我的程序就是白嫖与官方API方式做了选项,让客户自行选择了。

如果你不想这么麻烦,现在就有机会一步拥有这么完善的小程序,独立部署,完美后台,不管是自己用省成本,还是通过会员充值赚差价,都是不二之选啊~

【极客配音】极客分享独家开发,极客配音小程序系统,文案提取,200+人工智能配音员

图片[11]-【技术教程】如何写个小程序,白嫖微软语音合成-极客分享
------本页内容已结束,喜欢请分享------

感谢您的来访,获取更多精彩文章请收藏本站。

© 版权声明
THE END
喜欢就支持一下吧
点赞9赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容