本站响应部分朋友建议,现开放微软TTS文本转语音API接口,方便有编程能力更高自定义需求的朋友使用,接口套餐价格如下:

所有套餐字符数为30天时间内TTS合成文本总字符数量,汉字数量计算同英文(每个汉字和每个英文一样长度计为1)


接口文档

1、gettoken

接口地址:http://ttsapi.ztjun.fun/gettoken

用途:

获取token,token将用于其它接口计算 headers Authorization

参数详解:

data:={"user":username,"psw":password,"type":0,"key":key,"ts":Timestamp,"sign":sign}
user:网站用户名
password:网站密码
type:0表示获取token,1表示更新token
key:16位自定义key
ts:时间戳
sign:签名验证 md5(username+ts)

返回数据:

{"code":0,"maxChar":20000000,"date":"2024-12-31",charNum:3015,token:"xxxxx","msg":"success"}

maxChar:API接口套餐额度

date:到期时间

charNum:已用字符数

token:headers Authorization 参数

2、queryorde

接口地址:http://ttsapi.ztjun.fun/queryorder

用途:

查询套餐信息

参数详解:

data:={"user":username,"ts":ts,"sign":sign}
user:网站用户名
ts:时间戳
sign:签名验证 md5(username+ts)

Headers Authorization: 
data={"user":username,"token":token,"ts":ts} 
token:gettoken返回
AES加密:ECB/PKCS7 
key:16位自定义Key
auth=AES.Encrypt(data,key)  
headers={  
 Authorization:auth 
}

返回数据:

{"code":0,"maxChar":20000000,"date":"2024-12-31",charNum:3015,"msg":"success"}

maxChar:API接口套餐额度

date:到期时间

charNum:已用字符数

3、mstts

接口地址:http://ttsapi.ztjun.fun/mstts

用途:

微软TTS文本转语音

参数详解:

PostData(JSON格式):
{"user":username,"ssml":enBase64(ssml),"ts":Timestamp,"sign":sign}
user:网站用户名
ssml:enBase64(SSML),经base64编码的SSML(SSML格式参照微软文本转语音官方文档,附后)
ts:时间戳

Headers Authorization: 
token:gettoken返回
data={"user":username,"token":token,"ts":ts} 
AES加密:ECB/PKCS7 
key:16位自定义Key
auth=AES.Encrypt(data,key)
 ​ 
headers={  
 Authorization:auth 
}

SSML官方文档教程

返回数据:

{"code":0,"msg":"success","base64audio":respbase64data,"charNum":charNum,"maxChar":maxChar}

base64audio:经过base64编码的mp3音频数据,自行转换为mp3音频保存即可。

charNum:已用字符数

maxChar:API接口套餐额度

 


API测试工具

右侧顶部免费下载

1、获取token:/gettoken

2、套餐查询: /queryOrder

3、微软TTS语音合成:/mstts

Python 接口调用示例

import base64
import hashlib
import json
import os
import requests
from Crypto.Cipher import AES
import time
from Crypto.Util.Padding import pad, unpad

# AES加密,ECB模式
class AESCipher:
    def __init__(self, key):
        self.key = key.encode('utf-8')
        self.block_size = AES.block_size
    def encrypt(self, plain_text):
        cipher = AES.new(self.key, AES.MODE_ECB)
        padded_text = pad(plain_text.encode('utf-8'), self.block_size)
        return base64.b64encode(cipher.encrypt(padded_text)).decode('utf-8')
    def decrypt(self, encrypted_text):
        cipher = AES.new(self.key, AES.MODE_ECB)
        decrypted_text = unpad(cipher.decrypt(base64.b64decode(encrypted_text)), self.block_size)
        return decrypted_text.decode('utf-8')

# 获取13位时间戳
def getts():
    return str(int(time.time() * 1000))

# MD5加密
def get_md5(data):
    return hashlib.md5(data.encode('utf-8')).hexdigest()

# Base64解码到文件
def base64_to_file(base64_string, file_path):
    with open(file_path, 'wb') as file:
        file.write(base64.b64decode(base64_string))

# Base64编码
def enbase64(original_string):
    return base64.b64encode(original_string.encode('utf-8')).decode('utf-8')

# 获取sign
def getsign(user,ts):
    return get_md5(user+ ts)

# 获取token
def get_token(user, psw, stype,key):
    ts = getts()
    sign = getsign(user , ts)
    data = json.dumps({"user": user, "psw": psw, "type": stype,"key": key,"ts": ts,"sign": sign})
    headers = {'Content-Type': 'application/json'}
    response = requests.post('http://ttsapi.ztjun.fun/gettoken', data=data, headers=headers)
    return response.text

# 查询订单
def query_order(user, key,token):
    ts = getts()
    sign = getsign(user , ts)
    data = json.dumps({"user": user, "ts": ts, "sign": sign})
    aes = AESCipher(key)
    auth = aes.encrypt('{"user":"'+user+'","token":"'+token+'","ts":"'+ts+'"}')
    headers = {'Content-Type': 'application/json', 'Authorization': auth}
    response = requests.post('http://ttsapi.ztjun.fun/queryorder', data=data, headers=headers)
    return response.text

# 文本转语音
def mstts(user,ssml,key,token):
    ssml = ssml.replace('\r\n', '')
    ts = getts()
    sign = getsign(user , ts)
    data = json.dumps({"user": user, "ssml":base64.b64encode(ssml.encode('utf-8')).decode('utf-8'),"ts": ts, "sign": sign})
    aes = AESCipher(key)
    auth = aes.encrypt('{"user":"'+user+'","token":"'+token+'","ts":"'+ts+'"}')
    headers = {'Content-Type': 'application/json', 'Authorization': auth}
    response = requests.post('http://ttsapi.ztjun.fun/mstts', data=data, headers=headers)
    if response.status_code == 200:
        jo = response.json()
        if jo['code'] == 0:
            audiostr = jo['base64audio']
            base64_to_file(audiostr, os.path.join(os.path.dirname(__file__), 'test.mp3'))
            return response.text
        else:
            return response.text
    return response.text

# 示例使用
if __name__ == "__main__":
    #网站用户名
    user = ""
    #网站密码
    psw = ""
    #自定义密钥,16位字符串
    key = "1234567890123456"

    stype = "0"
    token = ''

    gtoken = json.loads(get_token(user, psw, stype,key))
    if(gtoken['code'] == 0):
        token=gtoken['token']
        print("get token",gtoken)

    if(token != ''):    
        order_info = query_order(user, key,token)
        print("Order Info:", order_info)

        ssml = '''<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="en-US-AriaNeural"><mstts:express-as style="Cheerful">"That’s remarkable! You’re a genius!"</mstts:express-as>Mom said to her son.</voice><voice name="en-US-JennyNeural">Customize output by <prosody rate="-40.00%"> slowing-down the speed rate.</prosody></voice><voice name="en-US-GuyNeural">Add a break <break time="600ms" /> between words.</voice><voice name="en-GB-SoniaNeural">You can pronounce it <say-as interpret-as="spell">ASAP </say-as>or <sub alias="as soon as possible">ASAP</sub>.</voice><voice name="zh-CN-XiaoxiaoNeural"><s /><mstts:express-as style="chat">可以通过停顿里的高级功能“No break”,解决<phoneme alphabet="sapi" ph="fen 1 ci 2">分词</phoneme>引起的多余停顿问题。</mstts:express-as><s /><mstts:express-as style="chat">也可以合成多角色多情感的有声<prosody contour="(49%, -40%)">书</prosody>,例如:</mstts:express-as></voice><voice name="zh-CN-YunyeNeural">黛玉冷笑道:</voice><voice name="zh-CN-XiaoxiaoNeural"><s /><mstts:express-as style="disgruntled">“我说呢,亏了绊住,不然,早就飞了来了。”</mstts:express-as><s /> </voice><voice name="zh-CN-YunyeNeural">宝玉道:</voice><voice name="zh-CN-YunxiNeural">“只许和你玩,替你解闷。不过偶然到他那里,就说这些闲话。”</voice><voice name="zh-CN-XiaoxiaoNeural"><mstts:express-as style="angry">”好没意思的话!去不去,关我什么事儿?又没叫你替我解闷儿,还许你<mstts:ttsbreak strength="none" />从此<prosody contour="(24%, +49%) (59%, -2%)">不</prosody><prosody rate="-15.00%" contour="(24%, +49%) (59%, -2%)">理</prosody><prosody contour="(24%, +49%) (59%, -2%)">我呢</prosody>!”</mstts:express-as></voice><voice name="zh-CN-YunyeNeural"><s />说着,便赌气回房去了。</voice></speak>'''
        tts_result = mstts(user, ssml, key,token)
        print("TTS Result:", tts_result)

NodeJS 接口调用示例

const crypto = require('crypto');
const axios = require('axios');
const fs = require('fs');

// AES加密,ECB模式
function encryptAES(data, key) {
    const cipher = crypto.createCipheriv('aes-128-ecb', key, '');
    let encrypted = cipher.update(data, 'utf8', 'base64');
    encrypted += cipher.final('base64');
    return encrypted;
}

// 获取13位时间戳
function getts() {
    return String(Date.now());
}

// MD5加密
function getMd5(data) {
    return crypto.createHash('md5').update(data).digest('hex');
}

// Base64解码到文件
function base64ToFile(base64String, filePath) {
    fs.writeFileSync(filePath, base64String, 'base64');
}

// Base64编码
function enbase64(originalString) {
    return Buffer.from(originalString, 'utf-8').toString('base64');
}

// 获取sign
function getsign(user,ts) {
    return getMd5(user+ts);
}

function getauth(user,token,ts,key){
    return encryptAES(`{"user":"${user}","token":"${token}","ts":"${ts}"}`,key)
}
// 获取token
async function getToken(user, psw, type,key) {
    const ts = getts();
    const sign = getsign(user, ts);
    const data = JSON.stringify({
        user,
        psw,
        type,
        key,
        ts,
        sign
    });
    const url = 'http://ttsapi.ztjun.fun/gettoken';
    const response = await axios.post(url, data, {
        headers: {
            'Content-Type': 'application/json',
        }
    });
    return response.data;
}

// 查询订单
async function queryOrder(user,key,token) {
    const ts = getts();
    const sign = getsign(user, ts);
    const auth = getauth(user, token, ts,key);
    const data = JSON.stringify({
        user,
        ts,
        sign
    });
    const headers = {
        'Content-Type': 'application/json',
        'Authorization': auth
    };
    const response = await axios.post('http://ttsapi.ztjun.fun/queryorder', data, { headers });
    return response.data;
}

// 文本转语音
async function mstts(user,ssml,key,token) {
    ssml = ssml.replace(/\r\n/g, '');
    const ts = getts();
    const sign = getsign(user, ts);
    const auth = getauth(user, token, ts,key);
    const endata = JSON.stringify({
        user,
        ssml: enbase64(ssml),
        ts,
        sign
    });
    const headers = {
        'Content-Type': 'application/json',
        'Authorization': auth
    };
    const response = await axios.post('http://ttsapi.ztjun.fun/mstts', endata, { headers });
    if (response.status === 200) {
        const jo = response.data;
        if (jo.code === 0) {
            const audiostr = jo.base64audio;
            base64ToFile(audiostr, 'test.mp3');
            return response.data;
        } else {
            return response.data;
        }
    }
    return response.data;
}

// 示例使用
(async () => {
    //网站用户名
    const user = "";
    //网站密码
    const psw = "";
    //自定义16位key
    const key = "1234567890123456"
    
    const stype = "0";
    let token = '';

    const gtoken = await getToken(user, psw, stype,key);
    if (gtoken.code === 0) {
        token = gtoken.token;
        console.log("get token", gtoken);
    }    

    if (token !== '') {
        const orderInfo = await queryOrder(user, key, token);
        console.log("Order Info:", orderInfo);

        const ssml = `<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="en-US-AriaNeural"><mstts:express-as style="Cheerful">"That’s remarkable! You’re a genius!"</mstts:express-as>Mom said to her son.</voice><voice name="en-US-JennyNeural">Customize output by <prosody rate="-40.00%"> slowing-down the speed rate.</prosody></voice><voice name="en-US-GuyNeural">Add a break <break time="600ms" /> between words.</voice><voice name="en-GB-SoniaNeural">You can pronounce it <say-as interpret-as="spell">ASAP </say-as>or <sub alias="as soon as possible">ASAP</sub>.</voice><voice name="zh-CN-XiaoxiaoNeural"><s /><mstts:express-as style="chat">可以通过停顿里的高级功能“No break”,解决<phoneme alphabet="sapi" ph="fen 1 ci 2">分词</phoneme>引起的多余停顿问题。</mstts:express-as><s /><mstts:express-as style="chat">也可以合成多角色多情感的有声<prosody contour="(49%, -40%)">书</prosody>,例如:</mstts:express-as></voice><voice name="zh-CN-YunyeNeural">黛玉冷笑道:</voice><voice name="zh-CN-XiaoxiaoNeural"><s /><mstts:express-as style="disgruntled">“我说呢,亏了绊住,不然,早就飞了来了。”</mstts:express-as><s /> </voice><voice name="zh-CN-YunyeNeural">宝玉道:</voice><voice name="zh-CN-YunxiNeural">“只许和你玩,替你解闷。不过偶然到他那里,就说这些闲话。”</voice><voice name="zh-CN-XiaoxiaoNeural"><mstts:express-as style="angry">”好没意思的话!去不去,关我什么事儿?又没叫你替我解闷儿,还许你<mstts:ttsbreak strength="none" />从此<prosody contour="(24%, +49%) (59%, -2%)">不</prosody><prosody rate="-15.00%" contour="(24%, +49%) (59%, -2%)">理</prosody><prosody contour="(24%, +49%) (59%, -2%)">我呢</prosody>!”</mstts:express-as></voice><voice name="zh-CN-YunyeNeural"><s />说着,便赌气回房去了。</voice></speak>`
        const ttsResult = await mstts(user, ssml, key ,token);
        console.log("TTS Result:", ttsResult);
    }
})();
本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习使用,请在下载后24小时内删除,严禁商用。若由于商用引起版权纠纷,一切责任均由使用者承担。 【注意:本站发布资源来源于网络搜集,均有较强时效性,请在下载前注意查看文章资源发布或更新时间,距离当前时间太久的资源不建议下载,特别是安卓专区相关资源,会有大概率失效无法使用】