Z-TTS API接口文档

欢迎使用我们的微软TTS API服务。本文档旨在帮助开发者快速理解和集成我们的文本转语音接口。请在开始前仔细阅读,特别是关于认证授权的部分。

准备工作 (Prerequisites)

在调用任何接口之前,您需要准备好您在本站的用户名密码。请注意,请勿使用注册邮箱作为user参数,应使用您的用户名。

核心概念:认证与授权

为了保障接口安全,我们所有的请求都需要进行签名和加密验证。

  1. 时间戳 (Timestamp):所有接口都需要一个13位的毫秒级时间戳,参数名为 ts。

  2. 签名 (Sign):部分接口需要对请求进行签名,签名算法为 md5(username + ts)。

  3. 授权头 (Authorization Header):queryorder 和 mstts 接口需要在HTTP请求头中加入 Authorization 字段。该字段的值是通过 AES 加密生成

    • 模式ECB

    • 填充:PKCS7

    • 密钥 (Key):一个16位的自定义字符串,在首次获取token时生成或指定。

    • 待加密数据:一个包含user, token, ts的JSON字符串。


API 接口详解

基础URL (Base URL): http://47.96.88.233:2048

1. 获取Token (/gettoken)

此接口用于获取后续接口调用所需的 token 和 key。

接口地址:/gettoken

请求方法:POST

请求参数 (data)

  • user (string): 您的网站用户名。
  • psw (string): 您的网站密码。
  • type (integer): 操作类型。0表示获取token,1表示更新key和token。
  • key (string, optional): 16位自定义密钥。如果留空,系统将为您随机生成一个(建议自动生成,更安全)。
  • ts (string): 13位时间戳。
  • sign (string): 签名,计算方式为 md5(user + ts)。

返回数据示例

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

2. 查询套餐信息 (/queryorder)

查询您当前账户的字符套餐余量和到期时间。

  • 接口地址:/queryorder

  • 请求方法:POST

  • 请求头 (Headers):Authorization: 经过AES加密后的授权字符串。

  • 请求参数 (data):user (string): 您的网站用户名。ts (string): 13位时间戳。sign (string): 签名,计算方式为 md5(user + ts)。

  • 返回数据示例

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

3. 微软TTS语音合成 (/mstts)

核心接口,用于将SSML文本合成为语音。

  • 接口地址:/mstts

  • 请求方法:POST

  • 请求头 (Headers):Authorization: 经过AES加密后的授权字符串。

  • 请求参数 (PostData, JSON格式)

    • user (string): 您的网站用户名。
    • ssml (string): 经过 Base64编码 的SSML文本。注意:单次请求的原文长度不能超过2000字符。
    • ts (string): 13位时间戳。
    • sign (string): 签名,计算方式为 md5(user + ts)。
  • 返回数据示例

{
    "code": 0,
    "msg": "success",
    "base64audio": "UklGRiQ... (base64编码的mp3音频数据)",
    "charNum": 3515,
    "maxChar": 20000000
}

您只需将 base64audio 字段的内容进行Base64解码,即可得到mp3音频文件。

重要注意事项

  1. 启用重定向:所有接口请求都必须启用HTTP重定向(allow_redirects=True)。

  2. 并发限制:接口限制最高并发为 4次/秒。超过此限制服务器将返回 429 状态码。

  3. SSML文档:关于如何编写SSML以控制语音情感、停顿、多角色发音等高级功能,请参考 微软官方SSML文档教程


API 快速测试工具

为了方便您在编码前快速验证接口的有效性,我们提供了API测试工具。您可以在页面顶部免费下载。

  • 获取token:/gettoken

 

  • 套餐查询: /queryOrder

 

  • 微软TTS语音合成:/mstts


Python API 调用完整示例代码

以下是一个完整的Python示例,演示了从获取Token到最终合成语音的全过程。您需要安装 requests 和 pycryptodome 库。

pip install requests pycryptodome

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

base_url="http://47.96.88.233:2048"

# 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))

#  获取sign
def get_sign(user,ts):
    data=f'{user}{ts}'
    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')
    

# 获取token
def get_token(user, psw, stype,key):
    ts = getts()
    sign = get_sign(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(base_url+'/gettoken',data=data,headers=headers,allow_redirects=True)
    return response.text

# 查询订单
def query_order(user, key,token):
    ts = getts()
    sign = get_sign(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(base_url+'/queryorder',data=data,headers=headers,allow_redirects=True)
    response = requests.post(response.url, data=data, headers=headers)
    return response.text
    
# 文本转语音
def mstts(user,ssml,key,token):
    ssml = ssml.replace('\r\n', '')
    ts = getts()
    sign = get_sign(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(base_url+'/mstts',data=data,headers=headers, allow_redirects=True)
    response = requests.post(response.url, 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 = ""

    #0表示获取token,1表示更新key、token
    stype = "0"

    #自定义密钥,16位字符串,留空则随机生成(推荐随机生成)
    key = "" 

    token =""

    gtoken =json.loads(get_token(user, psw, stype,key))
    if(gtoken['code'] == 0):
        token=gtoken['token']
        key=gtoken['key']
        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)
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。