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

使用TTS(语音合成)将文本转换成语音

最近更新时间2022.04.12 09:57:37

首次发布时间2022.04.12 09:57:37

前言

语音合成(TTS, Text to Speech),能将文本转换成人类声音。它运用了语音合成领域突破性的端到端合成方案,能提供高保真、个性化的音频。

本实验实现将文本转换成语音。

关于实验

  • 预计部署时间:20分钟
  • 级别:初级
  • 相关产品:TTS
  • 受众: 通用

实验说明

  • 点击此链接登录控制台。

  • 如果您还没有账户,请点击此链接注册账户。

  • 开通语音合成服务。

实验步骤

第一步-创建应用

进入语音技术控制台,创建应用,如下:

alt

第二步-获取APP ID、Access Token、ClusterID

到语音合成界面,选择第一步创建的应用,获取相关信息,如下:

alt

第三步-示例代码

使用TTS HTTP 接口进行接入。

package main

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/satori/go.uuid"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"time"
)

//TTSServResponse response from backend srvs
type TTSServResponse struct {
	ReqID    string        `json:"reqid"`
	Code      int          `json:"code"`
	Message   string       `json:"Message"`
	Operation string       `json:"operation"`
	Sequence  int          `json:"sequence"`
	Data      string       `json:"data"`
}

func httpPost(url string, headers map[string]string, body []byte,
	timeout time.Duration) ([]byte, error) {
	client := &http.Client{
		Timeout: timeout,
	}
	req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(body))
	if err != nil {
		return nil, err
	}
	for key, value := range headers {
		req.Header.Set(key, value)
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	retBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return retBody, err
}

func synthesis(text string) ([]byte, error) {
	//var e1 error
	reqID := uuid.Must(uuid.NewV4()).String()
	//r1 := uuid.Must(uuid.NewV4(),e1)
	params := make(map[string]map[string]interface{})
	params["app"] = make(map[string]interface{})
	params["app"]["appid"] = "123456"
	//这部分的token不生效,填写下方的默认值就好
	params["app"]["token"] = "access_token"
	params["app"]["cluster"] = "volc_xxxx"
	params["user"] = make(map[string]interface{})
	params["user"]["uid"] = "uid"
	params["audio"] = make(map[string]interface{})
	params["audio"]["voice"] = "other"
	params["audio"]["voice_type"] = "BV001"
	params["audio"]["encoding"] = "mp3"
	params["audio"]["speed"] = 10
	params["audio"]["volume"] = 10
	params["audio"]["pitch"] = 10
	params["request"] = make(map[string]interface{})
	params["request"]["reqid"] = reqID
	params["request"]["text"] = text
	params["request"]["text_type"] = "plain"
	params["request"]["operation"] = "query"

	headers := make(map[string]string)
	headers["Content-Type"] = "application/json"
	//bearerToken为平台对应的接入认证中的Access Token
	headers["Authorization"] = fmt.Sprintf("Bearer;%s", "xxxxxxxxxxxxxxxxxxx")

	// URL查看上方第四点: 4.并发合成接口(POST)
	url := "https://openspeech.bytedance.com/tts_middle_layer/tts"
	timeo := 30*time.Second
	bodyStr, _ := json.Marshal(params)
	synResp, err := httpPost(url, headers,
		[]byte(bodyStr), timeo)
	if err != nil {
		fmt.Printf("http post fail [err:%s]\n", err.Error())
		return nil, err
	}
  
	fmt.Println(params["request"]["text"])
	var respJSON TTSServResponse
	err = json.Unmarshal(synResp, &respJSON)
	if err != nil {
		fmt.Printf("unmarshal response fail [err:%s]\n", err.Error())
		return nil, err
	}
	code := respJSON.Code
	if code != 3000 {
		fmt.Printf("code fail [code:%d]\n", code)
		return nil, errors.New("resp code fail")
	}

	audio, _ := base64.StdEncoding.DecodeString(respJSON.Data)
	return audio, nil
}

func main() {

	filepath := "/Users/Documents/xxxx.txt"

	file,err := os.Open(filepath)
	if err != nil{
		fmt.Println(err)
	}
	defer file.Close()

	reader := bufio.NewReader(file)
	buf := make([]byte,300)
	fmt.Println(string(buf))

	f, err := os.OpenFile("test10.mp3", os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)

	if err != nil{
		fmt.Println(err)
	}
	defer func() {
		f.Close()
		fmt.Println("文件关闭")
	}()

	for{
		read,err := reader.Read(buf)

		if err !=nil && err != io.EOF{
			fmt.Println(err)
		}

		if read == 0{
			break
		}

		audio,err := synthesis(string(buf))

		f.Write(audio)
	}
}

参考文档:
[1] http接口

如果您有其他问题,欢迎您联系火山引擎技术支持服务