脚本基于aardio编程语言

Azure上的文本转语音云服务,效果更接近真人发音,并有语气和换气音。Azure的demo网页仅能在线试听,想下载二次使用目前网络上有2种方案:

  1. 录音法:缺点比较明显,为全局录音容易受干扰,且必须播放完才能完整获取数据
  2. js注入法:现存的注入法,是利用油猴脚本重写SpeechSDK,获取前端合成后的数据,不需要听完音频,数据传输完毕就可以下载

本例采取的方案与第二种类似,也是注入法,但由于油猴脚本的限制,第二种方法的代码稍显复杂,而使用aardio的webview库,重写websocket,使代码更加简洁,可维护性强。

解决方案概述:

云服务是通过WebSocket将音频分段后传输到前端。我们可以重写WebSocket库,更改监听“message”事件,将数据传递给aardio里处理。

开源地址:xuncv/azure-text-to-speech-saver: 微软Azure文本转语音下载器 (github.com)

import win.ui;
/*DSG{{*/
var winform = win.form(text="WebView2";right=966;bottom=622)
winform.add()
/*}}*/

import web.view;
import crypt.bin;
var wb = web.view(winform);

var buf = ''
wb.external = {
getData = function(data){
if(string.indexOf(data,"start")){
buf = ''
}elseif(string.indexOf(data,"end")){
string.save("\1.mp3",buf )
winform.msgbox("下载完成")
buf = ''
}else {
var src = crypt.bin.decodeHex(data);
//去掉分段的token信息,只保留音频数据
src = string.slice( src,131)
buf = string.concat( buf,src )
}
};
}

wb.preloadScript(`
(function() {
//arraybuffer to hex
function buf2hex(buffer) { // buffer is an ArrayBuffer
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}

function hookWebSocket() {
window.RealWebSocket = window.WebSocket;

window.WebSocket = function() {
var socket = new window.RealWebSocket(...arguments);

socket.addEventListener("message", (e) => {
if (typeof(e.data) == 'string') {
aardio.getData(e.data)
} else {
aardio.getData(buf2hex(e.data))
}
});
return socket;
}
}

hookWebSocket()
})()
`)

wb.go("https://azure.microsoft.com/zh-cn/services/cognitive-services/text-to-speech/")

winform.show();
win.loopMessage();