5分钟

任务 2 创建云函数调用TTS接口

任务目的

小程序调用TTS接口,可以使用云函数来实现。云函数是一段运行在云端的代码,无需管理服务器,在开发工具内编写、一键上传部署即可运行后端代码。本实验先完成TTS接口的调用。

任务步骤

1.开通TTS接口

在腾讯云官网搜索“TTS”,搜索结果会出现【语音合成】,点击【立即使用】按钮。

腾讯云官网搜索TTS

在语音合成界面勾选“我已阅读并同意《用户协议》”,点击【免费试用】按钮,即可开通TTS接口。

免费使用TTS接口

在后面会使用小程序调用各种接口,这里需要先记录腾讯云账号的APPID,SecretId,SecretKey。

在官网点击右上角账号图标进入【账号中心】

账号中心

在【账号信息】界面记录下APPID,然后点击【访问管理】

账号信息页面

在【访问管理】界面点击【访问密钥】下的【API密钥管理】,可以看到账号的SecretId和SecretKey,SecretKey需要扫码验证身份后才可以显示。记录下SecretId和SecretKey,后续小程序调用TTS接口会使用。

API密钥管理

2.创建云函数

在创建云开发项目时,微信开发者工具会在 cloudfunctions 文件夹下自动生成四个本地的云函数,这四个云函数与本项目无关,因此先将这四个云函数所在的文件夹删除。分别在四个文件夹上右击,选择删除。注意:在微信开发者工具内只能分多次删除,不能一次性删除。

删除自动创建的函数

然后右键点击cloudfunctions文件夹,选择【新建 Node.js 云函数】

新建云函数

填写云函数名字,这里命名为“invokeTTS”。

云函数命名

函数创建完成后包含 index.js 和 package.json 两个文件。

创建云函数完成

3.编写云函数

首先添加云函数所需依赖,这里需要添加腾讯云sdk的依赖。点击 package.json,在“dependencies”下,添加语句

"tencentcloud-sdk-nodejs": "latest"
修改package.json

注意:dependencies中每个依赖间用“,”隔开,最后一个依赖后,不能有“,”,如果缺少或者多添加“,”,微信开发者工具会报错。

点击 index.js ,将 index.js 改写成以下代码。

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()

//引入腾讯云sdk的依赖
const tencentcloud = require("tencentcloud-sdk-nodejs");

//设置成自己的secretId,secreteKey
const secretId = "yourSecretId"    # 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
const secretKey = "yourSecretKey"  # 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140

//调用TTS接口
function invokeTTS(transObj) {
  const TtsClient = tencentcloud.tts.v20190823.Client;
  const models = tencentcloud.tts.v20190823.Models;
  const Credential = tencentcloud.common.Credential;
  const ClientProfile = tencentcloud.common.ClientProfile;
  const HttpProfile = tencentcloud.common.HttpProfile;
  let cred = new Credential(secretId, secretKey); # 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
                                                  # 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140 
  let httpProfile = new HttpProfile();
  httpProfile.endpoint = "tts.tencentcloudapi.com";
  let clientProfile = new ClientProfile();
  clientProfile.httpProfile = httpProfile;
  let client = new TtsClient(cred, "ap-guangzhou", clientProfile);
  let req = new models.TextToVoiceRequest();
  let params = `{"Text":"${transObj.content}","SessionId":"session-1","ModelType":1,"VoiceType":"${transObj.voiceType}","Codec":"mp3"}`
  req.from_json_string(params);
  return new Promise((resolve, reject) => {
    client.TextToVoice(req, function (errMsg, response) {
      if (errMsg) {
        console.log(errMsg);
        reject(errMsg)
      }
      resolve(response)
    })
  }).then((res) => {
    return res.Audio
  })
}

// 云函数入口函数
exports.main = async (event, context) => {
  return invokeTTS(event.transObj)
}

改写后的 index.js 引入了腾讯云sdk的依赖,并设置自己账号的secretId与secretKey。

//引入腾讯云sdk的依赖
const tencentcloud = require("tencentcloud-sdk-nodejs");

//设置成自己的secretId,secreteKey
const secretId = "yourSecretId"  # 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
const secretKey = "yourSecretKey"# 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140

编写一个invokeTTS的函数调用TTS接口。这里 invokeTTS 函数接受一个 transObj 对象作为参数,这个参数中需要包含 content 属性和 voiceType 属性,content 属性代表合成语音的内容,voiceType 属性代表合成语音的类型。完整版本如下。

//调用TTS接口
function invokeTTS(transObj) {
  const TtsClient = tencentcloud.tts.v20190823.Client;
  const models = tencentcloud.tts.v20190823.Models;
  const Credential = tencentcloud.common.Credential;
  const ClientProfile = tencentcloud.common.ClientProfile;
  const HttpProfile = tencentcloud.common.HttpProfile;
  let cred = new Credential(secretId, secretKey);  # 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
                                                   # 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
  let httpProfile = new HttpProfile();
  let httpProfile = new HttpProfile();
  httpProfile.endpoint = "tts.tencentcloudapi.com";
  let clientProfile = new ClientProfile();
  clientProfile.httpProfile = httpProfile;
  let client = new TtsClient(cred, "ap-guangzhou", clientProfile);
  let req = new models.TextToVoiceRequest();
  let params = `{"Text":"${transObj.content}","SessionId":"session-1","ModelType":1,"VoiceType":"${transObj.voiceType}","Codec":"mp3"}`
  req.from_json_string(params);
  return new Promise((resolve, reject) => {
    client.TextToVoice(req, function (errMsg, response) {
      if (errMsg) {
        console.log(errMsg);
        reject(errMsg)
      }
      resolve(response)
    })
  }).then((res) => {
    return res.Audio
  })
}

在函数中首先引入腾讯云sdk的相关类

const TtsClient = tencentcloud.tts.v20190823.Client;
const models = tencentcloud.tts.v20190823.Models;
const Credential = tencentcloud.common.Credential;
const ClientProfile = tencentcloud.common.ClientProfile;
const HttpProfile = tencentcloud.common.HttpProfile;

然后创建相关类的对象,这里注意创建 Credential 类的对象需要 secretId 与 secretKey 作为参数。

本实验调用TTS接口所需参数如下表所示。

参数名称

必选

类型

描述

Region

String

公共参数,详见产品支持的
腾讯云官网搜索TTS

Text

String

合成语音的源文本,按UTF-8编码统一计算

SessionId

String

一次请求对应一个SessionId,会原样返回,建议传入类似于uuid的字符串防止重复。

ModelType

Integer

模型类型,1-默认模型。

VoiceType

Integer

音色

Codec

String

返回音频格式,可取值:wav(默认),mp3

调用接口的返回值如下表所示

参数名称

类型

描述

Audio

String

base64编码的wav/mp3音频数据

SessionId

String

一次请求对应一个SessionId

RequestId

String

唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。

更多关于TTS接口的详细描述,可进入腾讯云API中心的语音合成页面做进一步的了解。

let cred = new Credential(secretId, secretKey);  # 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
                                                 # 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
let httpProfile = new HttpProfile();
httpProfile.endpoint = "tts.tencentcloudapi.com";
let clientProfile = new ClientProfile();
clientProfile.httpProfile = httpProfile;
let client = new TtsClient(cred, "ap-guangzhou", clientProfile);
let req = new models.TextToVoiceRequest();
let params = `{"Text":"${transObj.content}","SessionId":"session-1","ModelType":1,"VoiceType":"${transObj.voiceType}","Codec":"mp3"}`
req.from_json_string(params);

最后调用 client 对象的 TextToVoice 方法,传入 req 对象和回调函数即可。

new Promise((resolve, reject) => {
  client.TextToVoice(req, function (errMsg, response) {
    if (errMsg) {
      console.log(errMsg);
      reject(errMsg)
    }
    resolve(response)
  })
}).then((res) => {
  return res.Audio
})

注意:这里使用Promise语法异步返回调用结果,可以采用其他异步调用的写法,但不能使用同步调用。

最后在云函数的入口函数直接调用invokeTTS,传入相应参数即可。

// 云函数入口函数
exports.main = async (event, context) => {
  return invokeTTS(event.transObj)
}

4.测试云函数

先将写好的云函数上传云端,在编写的云函数上点击右键选择【上传并部署:云端安装依赖(不上传 node_modules)】的按钮

上传云函数

开始上传时,微信开发者工具会显示

开始上传云函数

此时云函数上传至云端,但并没有完成,等待一段时间后显示

上传云函数完成

此时说明上传云函数完成,可以开始测试。点击【云开发】按钮,进入云开发控制台,点击【云函数】按钮,会在云函数列表中看到刚才编写的云函数,点击后面的【云端测试】按钮,进入云端测试页面。

进入云端测试页面

测试云函数时已经内置了一些常用的测试模板,可以改写测试模板,也可以直接新建一个模板,为了方便后续的调用,这里选择新建模板。

新建模板

将模板命名为testTTS,参数写法如下。

{
  "transObj":{
    "content":"测试TTS接口",
    "voiceType":1
  }
}

测试使用的实参相当于云函数中的 event 形参,在云函数调用invokeTTS 时,传入 event.transObj 就可传入到符合要求的参数

exports.main = async (event, context) => {
  return invokeTTS(event.transObj)
}

点击【确定】,然后点击【测试运行】

运行测试

运行测试后,可以看到【调用状态】为成功,【返回结果】是一个很长的字符串。这里的返回结果代表被Base64编码的mp3音频数据,使用Base64编码是为了方便音频在网络上传输。返回结果不能直接使用,需要使用Base64解码才能使用。解码过程会在后面讲到,现阶段只要看到返回Base64编码的字符串即可说明调用成功。

调用成功