You need to enable JavaScript to run this app.
导航

HTTP API

最近更新时间2023.05.19 16:19:35

首次发布时间2021.08.23 16:15:12

接入必读

请先查看接入必读了解具体接入方式,再参考此文档完成接入。

接口说明

  • 当前支持通过 HTTP 协议在线调用。
  • 请求内容包括:payload字段为将请求参数序列化后的json文本

公共参数

参考详细说明功能调用-通用协议

配置参数

payload配置参数为json字符串格式

字段描述类型是否必传默认值
text输入文本string否。text与ssml字段至少一个非空,若二者都非空则按照ssml字段-
ssml输入文本(SSML格式),与text字段至少一个非空string否。text与ssml字段至少一个非空,若二者都非空则按照ssml字段-
speaker发音人,具体见附录:发音人列表string-
audio_config补充参数object
audio_config.format输出音频编码格式,wav/mp3/aacstringmp3
audio_config.sample_rate输出音频采样率,可选值 [8000,16000,22050,24000,32000,44100,48000]number24000
audio_config.speech_rate语速,取值范围[-50,100],100代表2.0倍速,-50代表0.5倍数number0
audio_config.pitch_rate音调,取值范围[-12,12]number0
audio_config.enable_timestamp是否选择同时返回字与音素时间戳boolfalse

示例:

{
    "text": "欢迎使用文本转语音服务。",
    "speaker": "zh_female_qingxin",
    "audio_config":
    {
        "format": "wav",
        "sample_rate": 16000
    }
}

响应格式

HTTP响应Content-Type: application/json

字段描述类型
task_id请求任务id,用于链路追踪、问题排查string
namespace服务接口命名空间,比如TTSstring
data请求响应二进制数据,标准base64编码string
payload请求响应文本信息,json字符串格式string
status_code状态码number
status_text状态信息string
  • 响应结果payload为json字符串格式,json内容格式如下:

    字段描述类型
    duration音频时长,单位秒number
    words字的时间戳,单位秒。需要请求参数audio_config.enable_timestamp=truearray
    words.word字内容string
    words.start_time当前字开始时间number
    words.end_time当前字结束时间number
    phonemes音素的时间戳,单位秒。需要请求参数audio_config.enable_timestamp=truearray
    phonemes.phone音素内容string
    phonemes.start_time当前音素开始时间number
    phonemes.end_time当前音素结束时间number

    payload示例:

    {
        "duration": 3.0,
        "words":
        [
            {
                "word": "你",
                "start_time": "0",
                "end_time": "0.05"
            },
    	    ...
        ],
        "phonemes":
        [
            {
                "phone": "C0n",
                "start_time": "0",
                "end_time": "0.025"
            },
    	    ...
        ]
    }
    

参考示例

非流式调用方式为:POST /api/v1/invoke

Golang

// Code sample:
// use http client to invoke SAMI HTTP Service
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

type InvokeResponse struct {
	StatusCode int32   `form:"status_code,required" json:"status_code,required" query:"status_code,required"`
	StatusText string  `form:"status_text,required" json:"status_text,required" query:"status_text,required"`
	TaskId     string  `form:"task_id,required" json:"task_id,required" query:"task_id,required"`
	Namespace  string  `form:"namespace,required" json:"namespace,required" query:"namespace,required"`
	Payload    *string `form:"payload,omitempty" json:"payload,omitempty" query:"payload,omitempty"`
	Data       []byte  `form:"data,omitempty" json:"data,omitempty" query:"data,omitempty"`
	State      *string `form:"state,omitempty" json:"state,omitempty" query:"state,omitempty"`
}

const (
	domain = "https://sami.bytedance.com"

	// auth token
	appkey    = "your_appKey"

	// SAMI method
	version   = "v4"
	namespace = "TTS"

	// dump output
	dataOutputFile    = "output.wav"
	payloadOutputFile = "output.json"
	isDump            = true
)

func main() {
	// Get token
	token := "your_token"

	// Construct HTTP request
	//   1. Read local audio file and construct request payload
	//   2. Set HTTP json body
	//   3. Do HTTP POST request
	speaker := "zh_female_qingxin"
	text := "欢迎使用文本转语音服务。"
	body := fmt.Sprintf(
		`{"payload":"{\"speaker\":\"%v\",\"text\":\"%v\",\"audio_config\": {\"format\":\"wav\"}}"}`, speaker, text,
	)
	urlPath := fmt.Sprintf(
		"%v/api/v1/invoke?version=%v&token=%v&appkey=%v&namespace=%v",
		domain, version, token, appkey, namespace,
	)
	log.Printf("invoke request: %v", urlPath)

	// HTTP POST request
	start := time.Now()
	resp, err := http.Post(urlPath, "application/json", bytes.NewBuffer([]byte(body)))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	// Parse HTTP response
	ret, err := ioutil.ReadAll(resp.Body)
	if err != nil || resp.StatusCode != http.StatusOK {
		panic(string(ret))
	}
	log.Printf("http invoke: cost=%vms", time.Since(start).Milliseconds())

	// parse SAMI response
	samiResp := InvokeResponse{}
	payloadStr := ""
	if err = json.Unmarshal(ret, &samiResp); err != nil {
		log.Println("parse response failed", string(ret), err)
		panic(err)
	}
	if samiResp.Payload != nil {
		payloadStr = *samiResp.Payload
	}
	log.Printf("response task_id=%v, payload=%v, data=[%d]byte", samiResp.TaskId, payloadStr, len(samiResp.Data))
	if isDump && samiResp.Payload != nil {
		_ = ioutil.WriteFile(payloadOutputFile, []byte(*samiResp.Payload), 0644)
	}
	if isDump && len(samiResp.Data) > 0 {
		_ = ioutil.WriteFile(dataOutputFile, samiResp.Data, 0644)
	}
}

Python

import base64
import json
import sys

import requests

# Construct HTTP request
tts_payload = json.dumps({
    "text": "欢迎使用文本转语音服务。",
    "speaker": "zh_female_qingxin",
    "audio_config": {
        "format": "wav",
        "sample_rate": 24000,
        "speech_rate": 0,
    },
})
req = {
    "appkey": "your_appkey",
    "token": "your_token",
    "namespace": "TTS",
    "payload": tts_payload,
}

if __name__ == "__main__":
    # HTTP POST request
    resp = requests.post("https://sami.bytedance.com/api/v1/invoke", json=req)

    # Parse HTTP SAMI response
    try:
        sami_resp = resp.json()
        if resp.status_code != 200:
            print(sami_resp)
            sys.exit(1)
    except:
        print(resp)
        sys.exit(1)

    print("response task_id=%s, status_code=%d, status_text=%s, payload=%s" % (
        sami_resp["task_id"], sami_resp["status_code"], sami_resp["status_text"], sami_resp["payload"]))

    # Save audio data into file
    if sami_resp["status_code"] == 20000000 and len(sami_resp["data"]) > 0:
        audio_data = base64.b64decode(sami_resp["data"])
        print("audio_data_len: ", len(audio_data))
        with open("audio.wav", "wb") as f:
            f.write(audio_data)

PHP

<?php

/***********************
 * 
 * tts demo
 * 
 */

$url = "https://sami.bytedance.com/api/v1/invoke";


// 设置appkey、token信息
$appkey = "your-appkey";
$token = "your-token";
// 设置TTS请求参数
$speaker = "zh_female_qingxin";
$text = "欢迎使用智能语音服务。";
$format = "wav";
$sampleRate = 24000;


$audioConfig = array(
    "format" => $format,
    "sample_rate" => $sampleRate
);
$payload = array(
    "speaker" => $speaker,
    "text" => $text,
    "audio_config" =>$audioConfig
);

$payloadObj = json_encode($payload, JSON_UNESCAPED_UNICODE);
print "payload obj " . $payloadObj . "\n";

$body = array(
    "appkey" => $appkey,
    "token" => $token,
    "namespace" => "TTS",
    "payload" => $payloadObj
);

$bodyObj = json_encode($body, JSON_UNESCAPED_UNICODE);
print "body obj: " . $bodyObj . "\n";


// 发送http请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, TRUE);

$contentType = "application/json; charset=utf-8";
$httpHeaders = array(
    "Content-type:" . $contentType
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);

curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyObj);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

$response = curl_exec($ch);
if ($response == FALSE) {
    print "curl_exec failed!\n";
    print curl_error($ch);
    curl_close($ch);
    return ;
}

$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$responseHeaders = substr($response, 0, $headerSize);
$responseBody = substr($response, $headerSize);
curl_close($ch);

print $responseHeaders . "\n";

if ($httpCode != 200) {
    print $responseBody . "\n";
    return ;
}

$resultObj = json_decode($responseBody, TRUE);
$statusCode = $resultObj["status_code"];
if ($statusCode == 20000000) {
    $bodyPayload = $resultObj["payload"];
    $bodyPayloadObj = json_decode($bodyPayload, TRUE);
    $duration = $bodyPayloadObj["duration"];
    print $duration . "\n";
    $data = $resultObj["data"];
    $dataDecode = base64_decode($data);
    file_put_contents("tts_result.wav", $dataDecode);
}

?>

常见问题

HTTP状态码
业务状态码错误信息错误说明解决办法
40040402004TTSInvalidSpeaker
TTS发音人设置无效
检查TTS发音人是否正确设置
40040402001TTSEmptyTextTTS未设置文本检查TTS文本是否设置
40040402002TTSInvalidTextTTS设置文本非法检查TTS文本与发音人可能不匹配、无可读内容
40040402003
TTSExceededTextLimit
TTS文本长度超限检查TTS文本是否超限。非流式接口上限为 1000 个utf-8字符;流式接口上限为 2000 个utf-8字符(包括空格、标点、汉字、字母等)