//edgetts 微软语音合成
//小肥羊自用tts语音合成
//v1.0.0 2023-6-10
/*
import yang.edgetts;
yang.edgetts.VoiceList();
yang.edgetts.TtsRead(wordstring,voicetype,savepath,autoRead); //直接使用即可
*/
//部分代码摘自https://aardio.com.cn/t/21445,并进行整理
import string.template
import web.rest.client
import web.json;
import fsys;
namespace yang.edgetts;
TRUSTED_CLIENT_TOKEN = "6A5AA1D4EAFF4E9FB37E23D68491D6F4"
//wss://speech.platform.bing.com/consumer/speech/synthesize/readaloud/edge/v1?TrustedClientToken=6A5AA1D4EAFF4E9FB37E23D68491D6F4
VOICE_LIST = "https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list?trustedclienttoken=" + TRUSTED_CLIENT_TOKEN;
VoiceList = function(){
client = ..web.rest.client()
client.addHeaders = {
"Authority"="speech.platform.bing.com",
"Sec-CH-UA"='" Not;A Brand";v="99", "Microsoft Edge";v="91", "Chromium";v="91"',
"Sec-CH-UA-Mobile"="?0",
"User-Agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 Edg/91.0.864.41",
"Accept"="*/*",
"Sec-Fetch-Site"="none",
"Sec-Fetch-Mode"="cors",
"Sec-Fetch-Dest"="empty",
"Accept-Encoding"="gzip, deflate, br",
"Accept-Language"="en-US,en;q=0.9"
}
api = client.api(VOICE_LIST);
list = api.get();
json = ..web.json.tryParse(list);
var res = {};
if(json){
res = ..table.filter(json,function(v,index){
return ..string.indexOf(v[['ShortName']],"zh-CN")
})
}
return res;
}
TtsRead = function(str,voiceType="zh-CN-YunxiNeural",savepath,readIt=false){
var ssmlTemp = ..string.template()
ssmlTemp.template = /***
<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="en-US">
<voice name="${voiceType}">
<mstts:express-as >
<prosody rate="10.000000000000009%" pitch="0%">
${text}
</prosody>
</mstts:express-as>
</voice>
</speak>
***/
var ssml = ssmlTemp.format({
text = str,
voiceType = voiceType
}
)
client = ..web.rest.client()
client.addHeaders = {
"authority": "southeastasia.api.speech.microsoft.com",
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"customvoiceconnectionid": "d8a3a480-dd87-11ed-8758-97b5a7fbfaf6",
"origin": "https://speech.microsoft.com",
"sec-ch-ua":'"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-site",
"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
"content-type": "application/json",
}
api = client.api("https://southeastasia.api.speech.microsoft.com/accfreetrial/texttospeech/acc/v3.0-beta1")
var res,e,c = api.vcg.speak.post(..web.json.stringify(
{
ssml = ssml;
ttsAudioFormat = "audio-24khz-160kbitrate-mono-mp3";
offsetInPlainText = 0;
properties = {
SpeakTriggerSource = "AccTuningPagePlayButton";
};
}))
if(res){
if(!savepath)savepath = ..fsys.getTempDir()+"\"+..string.random(8)+".mp3";
..string.save(savepath,res );
if(readIt){
import fsys.media;
mp3=..fsys.media(savepath);
mp3.play();
}
return true,savepath;
}
return false;
}
/**intellisense(yang.edgetts)
VoiceList()=列出所有的中文语音人物声音种类,注意,仅保留了zh-cn的语音哈
TtsRead(wordstring,voicetype,savepath,autoRead) = 合成语音:\n@1为文本信息\n@2为声音种类,如不提供默认是云溪,种类可以通过VoiceList函数获取,供选择\n@3存储位置,可以为空,为空默认存储到temp目录\n@4自动朗读,默认为false,开启后调用fsys.media进行朗读
end intellisense**/