# 长文本语音合成 API 文档

# 接口说明

  • 长文本语音合成提供了支持单次超大文本(万字级别)进行快速语音合成的功能。
    支持单次合成上限约10万字符;
    语音合成速度快,支持设置语速、语调和音量等特性;
    支持中、英文,男、女声发音人;
    支持输出pcm、mp3、speex、opus等编码格式音频;
    支持通过主动查询和服务回调方式获取语音合成结果;
    支持拼音标注功能;
    注:接口返回的音频在云端保存7天,请及时下载音频

  • 部分开发语言demo如下,其他开发语言请参照文档进行开发,也欢迎热心的开发者到 讯飞开放平台社区 (opens new window) 分享你们的demo。
    长文本语音合成 demo java语言 (opens new window)
    长文本语音合成 demo python语言 (opens new window)

  • 集成长文本语音合成时,需按照以下要求:

内容 说明
传输方式 http[s] (为提高安全性,强烈推荐https)
请求地址 1、创建任务:http(s): //api-dx.xf-yun.com/v1/private/dts_create
2、查询任务:http(s): //api-dx.xf-yun.com/v1/private/dts_query
注:服务器IP不固定,为保证您的接口稳定,请勿通过指定IP的方式调用接口,使用域名方式调用
请求行 1、创建任务:POST /v1/private/dts_create HTTP/1.1
2、查询任务:POST /v1/private/dts_query HTTP/1.1
接口鉴权 签名机制,详情请参照下方鉴权认证
字符编码 UTF-8
响应格式 统一采用JSON格式
开发语言 任意,只要可以向讯飞云服务发起HTTP请求的均可
适用范围 任意操作系统,但因不支持跨域不适用于浏览器
文本长度 单次合成上限约10万字符
音频格式 pcm、mp3、speex、opus

注意:测试或正式使用前,请去对应产品页面获取免费额度或下单购买正式套餐;同时需要去控制台服务页面,获取API有效密钥(AppID、APIKey、APISecret)后再调用。
长文本语音合成产品页 (opens new window)
长文本语音合成服务页 (opens new window)

# 鉴权说明

在调用业务接口时,请求方需要对请求进行签名,服务端通过签名来校验请求的合法性。

# 鉴权方法

通过在请求地址后面加上鉴权相关参数的方式,请注意影响鉴权结果的值有url、apiSecret、apiKey、date,如果调试鉴权,请务必按照示例中给的值进行调试,具体参数如下:

http示例url:

http://api-dx.xf-yun.com/v1/private/dts_create?host=api-dx.xf-yun.com&date=Thu%2C+09+Feb+2023+03%3A37%3A55+GMT&authorization=YXBpX2tleT0iYXBpa2V5WFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFgiLCBhbGdvcml0aG09ImhtYWMtc2hhMjU2IiwgaGVhZGVycz0iaG9zdCBkYXRlIHJlcXVlc3QtbGluZSIsIHNpZ25hdHVyZT0idWpwWVFINGVCUHYwMm42dndQUDZ3cGJjeEV0ZGJ5WVJrQm9hbjlZQm1PWT0i

鉴权参数:

参数 类型 必须 说明 示例
host string 是 请求主机 api-dx.xf-yun.com
date string 是 当前时间戳,RFC1123格式("EEE, dd MMM yyyy HH:mm:ss z") Thu, 09 Feb 2023 03:37:55 GMT
authorization string 是 使用base64编码的签名相关信息(签名基于hamc-sha256计算) 参考下方详细生成规则

• date参数生成规则:

date必须是UTC+0或GMT时区,RFC1123格式(Thu, 09 Feb 2023 03:37:55 GMT)。
服务端会对date进行时钟偏移检查,最大允许300秒的偏差,超出偏差的请求都将被拒绝。

• authorization参数生成格式:

1)获取接口密钥APIKey 和 APISecret。
在讯飞开放平台控制台,创建一个应用后打开长文本合成页面可以获取,均为32位字符串。
2)参数authorization base64编码前(authorization_origin)的格式如下。

api_key="$api_key",algorithm="hmac-sha256",headers="host date request-line",signature="$signature"

其中 api_key 是在控制台获取的APIKey,algorithm 是加密算法(仅支持hmac-sha256),headers 是参与签名的参数(见下方注释)。
signature 是使用加密算法对参与签名的参数签名后并使用base64编码的字符串,详见下方。

注: headers是参与签名的参数,请注意是固定的参数名("host date request-line"),而非这些参数的值。

3)signature的原始字段(signature_origin)规则如下。

signature原始字段由 host,date,request-line三个参数按照格式拼接成,
拼接的格式为(\n为换行符,’:’后面有一个空格):

host: $host\ndate: $date\n$request-line

假设

请求url = "http(s): //api-dx.xf-yun.com/v1/private/dts_create"
date = "Thu, 09 Feb 2023 03:37:55 GMT"

那么 signature原始字段(signature_origin)则为:

host: api-dx.xf-yun.com
date: Thu, 09 Feb 2023 03:37:55 GMT
POST /v1/private/dts_create HTTP/1.1

4)使用hmac-sha256算法结合apiSecret对signature_origin签名,获得签名后的摘要signature_sha。

signature_sha=hmac-sha256(signature_origin,$apiSecret)

其中 apiSecret 是在控制台获取的APISecret

5)使用base64编码对signature_sha进行编码获得最终的signature。

signature=base64(signature_sha)

假设

APISecret = "apisecretXXXXXXXXXXXXXXXXXXXXXXX"	
date = "Thu, 09 Feb 2023 03:37:55 GMT"

则signature为

signature="ujpYQH4eBPv02n6vwPP6wpbcxEtdbyYRkBoan9YBmOY="

6)根据以上信息拼接authorization base64编码前(authorization_origin)的字符串,示例如下。

api_key="apikeyXXXXXXXXXXXXXXXXXXXXXXXXXX", algorithm="hmac-sha256", headers="host date request-line", signature="ujpYQH4eBPv02n6vwPP6wpbcxEtdbyYRkBoan9YBmOY="

注: headers是参与签名的参数,请注意是固定的参数名("host date request-line"),而非这些参数的值。

7)最后再对authorization_origin进行base64编码获得最终的authorization参数。

authorization = base64(authorization_origin)
示例结果为:
authorization=YXBpX2tleT0iYXBpa2V5WFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFgiLCBhbGdvcml0aG09ImhtYWMtc2hhMjU2IiwgaGVhZGVycz0iaG9zdCBkYXRlIHJlcXVlc3QtbGluZSIsIHNpZ25hdHVyZT0idWpwWVFINGVCUHYwMm42dndQUDZ3cGJjeEV0ZGJ5WVJrQm9hbjlZQm1PWT0i

# 鉴权结果

如果鉴权失败,则根据不同错误类型返回不同HTTP Code状态码,同时携带错误描述信息,详细错误说明如下:

HTTP Code 说明 错误描述信息 解决方法
401 缺少authorization参数 {"message":"Unauthorized"} 检查是否有authorization参数,详情见authorization参数详细生成规则
401 签名参数解析失败 {“message”:”HMAC signature cannot be verified”} 检查签名的各个参数是否有缺失是否正确,特别确认下复制的api_key是否正确
401 签名校验失败 {“message”:”HMAC signature does not match”} 签名验证失败,可能原因有很多。
1. 检查api_key,api_secret 是否正确。
2.检查计算签名的参数host,date,request-line是否按照协议要求拼接。
3. 检查signature签名的base64长度是否正常(正常44个字节)。
403 时钟偏移校验失败 {“message”:”HMAC signature cannot be verified, a valid date or x-date header is required for HMAC Authentication”} 检查服务器时间是否标准,相差5分钟以上会报此错误

时钟偏移校验失败示例:

HTTP/1.1 403 Forbidden
Date: Mon, 30 Nov 2020 02:34:33 GMT
Content-Length: 116
Content-Type: text/plain; charset=utf-8
{
    "message": "HMAC signature does not match, a valid date or x-date header is required for HMAC Authentication"
}

# 1、创建任务

# 请求参数

在调用业务接口时,都需要在 Http Request Body 中配置以下参数,请求数据均为json字符串。
请求参数示例:

{
	"header": {
		"app_id": "your_appid"
	},
	"parameter": {
		"dts": {
			"vcn": "x3_mingge",
			"language": "zh",
			"speed": 50,
			"volume": 50,
			"pitch": 50,
			"rhy": 1,
			"audio": {
				"encoding": "lame",
				"sample_rate": 16000,
			},
			"pybuf": {
				"encoding": "utf8",
				"compress": "raw",
				"format": "plain"
			}
		}
	},
	"payload": {
		"text": {
			"encoding": "utf8",
			"compress": "raw",
			"format": "plain",
			"text": "6L+Z5piv5LiA5q615rWL6K+V5paH5pys\n"
		}
	}
}

请求参数说明:

参数名 类型 必传 描述
header Object 是 协议头部,用于描述平台特性的参数
parameter Object 是 AI 特性参数,用于控制 AI 引擎特性的开关
dts Object 是 服务别名
audio Object 是 数据格式预期,用于描述返回结果的编码等相关约束,不同的数据类型,约束维度亦不相同,此 object 与响应结果存在对应关系
pybuf Object 是 数据格式预期,用于描述返回结果的编码等相关约束,不同的数据类型,约束维度亦不相同,此 object 与响应结果存在对应关系
payload Object 是 数据段,携带请求的数据
text Object 是 输入数据

header段参数

参数名 类型 必传 描述
app_id string 是 应⽤唯⼀标识
callback_url string 否 任务结果回调服务地址
request_id string 否 客户端⽤于标记任务的唯⼀id,最⼤⻓度64字符,由客户端保证唯⼀性,服务回调结果时会包含此参数

parameter.dts段参数

参数名 类型 必传 描述
vcn string 是 详见发音人列表
language string 否 合成文本语言
zh:中文(默认)
en:英文
speed int 否 取值范围[0-100],默认50
volume int 否 取值范围[0-100],默认50
pitch int 否 取值范围[0-100],默认50
ram string 否 是否读出标点
0:不读出所有的标点符号(默认)
1:读出所有的标点符号
rhy string 否 控制是否返回拼音标注
0: 不返回拼音(默认)
1: 返回拼音 (支持的引擎: xtts1.0-cpu, xtts1.0-gpu, xtts2.0-gpu, xtts2-gpu中是每句话一次性返回) 拼音标注的时间xtts2.0要乘以5ms

parameter.dts.pybuf段参数

参数名 类型 必传 描述
encoding string 否 文本编码,可选值:utf8(默认)、gb2312
compress string 否 文本压缩格式,可选值:raw
format string 否 文本格式,可选值:plain

parameter.dts.audio段参数

参数名 类型 必传 描述
encoding string 是 音频编码
raw:原始pcm音频
lame:mp3编码格式
opus:opus 8K
opus-wb:opus 16K
speex-org-nb;8:speex 8K
speex-org-wb;8:speex 16K
注:分号后面数字为压缩等级,取值1-10,缺省8
speex;7:讯飞定制8K speex
speex-wb;7:讯飞定制16K speex
注:分号后面数字为压缩等级,取值1-10,缺省7
sample_rate int 否 采样率,可选值:16000(默认)、8000、24000

payload.text段参数

参数名 类型 必传 描述
encoding string 是 文本编码,可选值:utf8(默认)、gb2312
compress string 否 文本压缩格式,可选值:raw(默认)、gzip
format string 否 文本格式,可选值:plain、json、xml
text string 是 文本数据,最大支持10w 字文本字数,文本大小:0-1M

# 返回结果

返回参数示例:
成功

{
	"header": {
		"code": 0,
		"message": "success",
		"sid": "dts000e81e2@dx184a8c91edf738d882",
		"task_id": "221124163743668851981200"
	},
	"payload": null
}

失败

{
	"header": {
		"code": 10313,
		"message": "appid cannot be empty",
		"sid": "dts000e61dd@dx184a8fe7c55738d882"
	}
}

返回参数说明:

参数名 类型 描述
header object ⽤于传递平台框架使⽤的相关公共参数
header.code int 0:任务创建成功
非0:任务创建失败
header.message string 错误描述,针对任务创建错误码的描述
header.sid string 本次会话的id,⽤于链路及问题跟踪
header.task_id string 本次创建的任务id,⽤于唯⼀标识本次任务

# 2、查询任务

# 请求参数

在调用业务接口时,都需要在 Http Request Body 中配置以下参数,请求数据均为json字符串。
请求参数示例:

{
	"header": {
		"app_id": "3e79d91c",
		"task_id": "221124174214587600971201"
	}
}

请求参数说明:

参数名 类型 必传 描述
header object 是 平台公共协议段,⽤于传递平台框架使⽤的相关公共参数
header.app_id string 是 在平台申请的app id信息
header.task_id string 是 任务唯⼀标识,由任务创建接⼝返回

# 返回结果

返回参数示例:
成功

{
	"header": {
		"code": 0,
		"message": "success",
		"sid": "dts000fa2e7@dx184a90433d96f19882",
		"task_id": "221124174214587600971201",
		"task_status": "5"
	},
	"payload": {
		"audio": {
			"audio": "aHR0cD······",
			"bit_depth": "16",
			"channels": "1",
			"encoding": "lame",
			"sample_rate": "16000"
		},
		"pybuf": {
			"encoding": "utf8",
			"text": "aHR0cDovL······"
		}
	}
}

失败

{
	"header": {
		"code": 10163,
		"message": "parameter schema validate error: '$.header.task_id' length must be larger or equal than 1; ",
		"sid": "dts000ef953@dx184ac8e8ce4738d882"
	}
}

返回参数说明:

参数名 类型 描述
header Object 协议头部,用于描述平台特性的参数
header.code int 返回码,0表示成功,其它表示异常
header.message string 错误描述
header.sid string 本次会话的id
header.task_id string 任务唯⼀标识
header.task_status string 任务状态: 1:任务创建成功
2:任务派发失败
3:任务处理中
4:任务处理失败
5:任务处理成功
payload Object 数据段,携带响应的数据
payload.audio Object 输出数据
payload.audio.encoding string 音频编码,可选值:lame, speex, opus, opus-wb, speex-wb
payload.audio.sample_rate int 音频采样率,可选值:16000, 8000, 24000
payload.audio.channels int 声道数,可选值:1, 2
payload.audio.bit_depth int 单位bit,可选值:16, 8
payload.audio.audio string 音频链接,采用base64编码
payload.pybuf Object 输出数据
payload.pybuf.encoding string 文本编码,可选值:utf8, gb2312
payload.pybuf.text string 文本地址,音素链接,采用base64编码

# 附录

发音人

中文名称 参数名称(vcn=) 音色 语种/方言 风格
希涵 x4_yeting 女 中文/普通话 游戏影视解说
关山-专题 x4_guanshan 男 中文/普通话 专题片纪录片
小鹏 x4_pengfei 男 中文/普通话 新闻播报
千雪 x4_qianxue 女 中文/普通话 阅读听书
聆伯松-老年男声 x4_lingbosong 男 中文/普通话 阅读听书
秀英-老年女声 x4_xiuying 女 中文/普通话 阅读听书
明哥 x4_mingge 男 中文/普通话 阅读听书
豆豆 x4_doudou 男 中文/男童 阅读听书
聆小珊 x4_lingxiaoshan_profnews 女 中文/普通话 新闻播报
小果 x4_xiaoguo 女 中文/普通话 新闻播报
小忠 x4_xiaozhong 男 中文/普通话 新闻播报
小露 x4_yezi 女 中文/普通话 通用场景
超哥 x4_chaoge 男 中文/普通话 新闻播报
飞碟哥 x4_feidie 男 中文/普通话 游戏影视解说
聆飞皓-广告 x4_lingfeihao_upbeatads 男 中文/普通话 直播广告
嘉欣 x4_wangqianqian 女 中文/普通话 直播广告
聆小臻 x4_lingxiaozhen_eclives 女 中文/普通话 直播广告
# python完整示例代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author : iflytek

import requests
import json
import base64
import hashlib
import time
from urllib.parse import urlencode
import hmac
from datetime import datetime
from wsgiref.handlers import format_date_time
from time import mktime
import sys

class TestTask():

    def __init__(self):
        self.host = HOST
        self.app_id = APP_ID
        self.api_key = API_KEY
        self.api_secret = API_SECRET

    # 生成鉴权的url
    def assemble_auth_url(self, path):
        params = self.assemble_auth_params(path)
        # 请求地址
        request_url = "http://" + self.host + path
        # 拼接请求地址和鉴权参数,生成带鉴权参数的url
        auth_url = request_url + "?" + urlencode(params)
        return auth_url

    # 生成鉴权的参数
    def assemble_auth_params(self, path):
        # 生成RFC1123格式的时间戳
        format_date = format_date_time(mktime(datetime.now().timetuple()))
        # 拼接字符串
        signature_origin = "host: " + self.host + "\n"
        signature_origin += "date: " + format_date + "\n"
        signature_origin += "POST " + path + " HTTP/1.1"
        # 进行hmac-sha256加密
        signature_sha = hmac.new(self.api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
                                 digestmod=hashlib.sha256).digest()
        signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
        # 构建请求参数
        authorization_origin = 'api_key="%s", algorithm="%s", headers="%s", signature="%s"' % (
            self.api_key, "hmac-sha256", "host date request-line", signature_sha)
        # 将请求参数使用base64编码
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
        # 将请求的鉴权参数组合为字典
        params = {
            "host": self.host,
            "date": format_date,
            "authorization": authorization
        }
        return params

    # 创建任务
    def test_create(self, text):
        # 创建任务的路由
        create_path = "/v1/private/dts_create"
        # 拼接鉴权参数后生成的url
        auth_url = self.assemble_auth_url(create_path)
        # 合成文本
        encode_str = base64.encodebytes(text.encode("UTF8"))
        txt = encode_str.decode()
        # 请求头
        headers = {'Content-Type': 'application/json'}
        # 请求参数,字段具体含义见官网文档:https://aidocs.xfyun.cn/docs/dts/%E6%8E%A5%E5%8F%A3%E5%8D%8F%E8%AE%AEv3.html
        data = {
            "header": {
                "app_id": self.app_id,
                # "callback_url": "",
                # "request_id": ""
            },
            "parameter": {
                "dts": {
                    "vcn": "x4_mingge",#请先在控制台开通明哥发音人权限
                    "language": "zh",
                    "speed": 50,
                    "volume": 50,
                    "pitch": 50,
                    "rhy": 1,
                    "bgs": 0,
                    "reg": 0,
                    "rdn": 0,
                    "scn": 0,
                    "audio": {
                        "encoding": "lame", # 下方下载的文件后缀需要保持一致
                        "sample_rate": 16000,
                        "channels": 1,
                        "bit_depth": 16,
                        "frame_size": 0
                    },
                    "pybuf": {
                        "encoding": "utf8",
                        "compress": "raw",
                        "format": "plain"
                    }
                }
            },
            "payload": {
                "text": {
                    "encoding": "utf8",
                    "compress": "raw",
                    "format": "plain",
                    "text": txt
                }
            },
        }
        try:
            print("创建任务请求参数:", json.dumps(data))
            res = requests.post(url=auth_url, headers=headers, data=json.dumps(data))
            res = json.loads(res.text)
            return res
        except Exception as e:
            print("创建任务接口调用异常,错误详情:%s" % e)
            sys.exit(1)

    # 查询任务
    def test_query(self, task_id):
        # 查询任务的路由
        query_path = "/v1/private/dts_query"
        # 拼接鉴权参数后生成的url
        auth_url = self.assemble_auth_url(query_path)
        # 请求头
        headers = {'Content-Type': 'application/json'}
        # 请求参数,字段具体含义见官网文档:https://aidocs.xfyun.cn/docs/dts/%E6%8E%A5%E5%8F%A3%E5%8D%8F%E8%AE%AEv3.html
        data = {
            "header": {
                "app_id": self.app_id,
                "task_id": task_id
            }
        }
        try:
            print("\n查询任务请求参数:",json.dumps(data))
            res = requests.post(url=auth_url, headers=headers, data=json.dumps(data))
            res = json.loads(res.text)
            return res
        except Exception as e:
            print("查询任务接口调用异常,错误详情:%s" % e)
            sys.exit(1)


# 创建任务
def do_create(text):
    # 调用创建任务接口
    test_task = TestTask()
    create_result = test_task.test_create(text)
    print("create_response:",json.dumps(create_result))
    # 创建任务接口返回状态码
    code = create_result.get('header', {}).get('code')
    # 状态码为0,创建任务成功,打印task_id, 用于后续查询任务
    if code == 0:
        task_id = create_result.get('header', {}).get('task_id')
        print("创建任务成功,task_id: %s" % task_id)
        return task_id
    # 状态码非0,创建任务失败, 相关错误码参考官网文档:https://aidocs.xfyun.cn/docs/dts/%E6%8E%A5%E5%8F%A3%E5%8D%8F%E8%AE%AEv3.html
    else:
        print("创建任务失败,返回状态码: %s" % code)

# 查询任务
def do_query(task_id):
    test_task = TestTask()
    # 这里循环调用查询结果,当task_status状态为'5'(即大文本合成任务完成)时停止循环,循环次数和sleep时间可酌情定义
    for i in range(9):
        # 等待1秒
        time.sleep(1)
        # 调用查询任务接口
        query_result = test_task.test_query(task_id)
        print("query_response:",json.dumps(query_result))
        # 查询任务接口返回状态码
        code = query_result.get('header', {}).get('code')
        # 状态码为0,查询任务成功
        if code == 0:
            # 任务状态码:1-任务创建成功 2-任务派发失败 4-结果处理中 5-结果处理完成
            task_status = query_result.get('header', {}).get('task_status')
            if task_status == '5':
                audio = query_result.get('payload', {}).get('audio').get('audio')
                # base64解码audio,打印下载链接
                decode_audio = base64.b64decode(audio)
                print("查询任务成功,音频下载链接: %s" % decode_audio.decode())
                return decode_audio
                break
            else:
                print("第%s次查询,处理未完成,任务状态码:%s" % (i + 1, task_status))
        else:
            print("查询任务失败,返回状态码: %s" % code)
            sys.exit(1)



if __name__ == "__main__":
    # 1、用户参数,相关参数注意修改
    HOST = "api-dx.xf-yun.com"
    APP_ID = "XXXX"
    API_KEY = "XXXX"
    API_SECRET = "XXXX"

    # 2、执行创建任务
    file= open("input.txt",encoding='utf-8')
    text = file.read()
    task_id = do_create(text)
    file.close()

    # 3、执行查询任务
    # 创建任务执行成功后,由返回的task_id执行查询任务
    if task_id:
        query_result = do_query(task_id)

    # 4、下载到本地
    Download_addres = query_result
    f = requests.get(Download_addres)
    # 下载文件,根据需要更改文件后缀
    filename = "tts.mp3"
    with open(filename, "wb") as code:
        code.write(f.content)
    if filename:
        print("\n音频保存成功!")

# 常见问题

# 长文本语音合成的主要功能是什么?

答:长文本语音合成提供了支持单次超大文本(万字级别)进行快速语音合成的功能。

# 长文本语音合成支持什么应用平台?

答:目前支持Web API应用平台。

# 长文本语音合成支持合成什么格式的音频,音频在云端保存时间是多久?

答:支持合成pcm、mp3、speex、opus格式的音频。音频在云端保存7天,请及时下载音频。

在线咨询
体验中心