当前位置:   article > 正文

微信小程序实现讯飞语音合成_讯飞 小程序端 语音流

讯飞 小程序端 语音流

参考文档:语音合成(流式版)WebAPI 文档

微信小程序背景音频播报可参考:uniapp实现微信小程序websocket+背景音频语音播报

实现步骤

  1. 注册讯飞账号,完成实名认证,获取应用appid
  2. 连接讯飞websocket,在握手阶段,请求方需要对请求进行签名
  3. 发送请求文本,讯飞服务器返回合成后的音频片段,采用base64编码
  4. 将返回的音频片段组合,并转成可播放的MP3文件

1.注册账号,并获取应用appid

打开官网网址:讯飞开放平台-语音合成 点击免费试用,按步骤完成实名认证后得到appid

 2.连接讯飞websocket,在握手阶段,请求方需要对请求进行签名

  1. async getWebsocketUrl() {
  2. // 合成讯飞语音请求地址
  3. const that = this;
  4. return await new Promise((resolve, reject) => {
  5. var apiKey = API_KEY; // 讯飞控制台查看
  6. var apiSecret = API_SECRET; // 讯飞控制台查看
  7. var url = 'wss://tts-api.xfyun.cn/v2/tts';
  8. var host = BASEURL; // 请求的主机地址
  9. var date = new Date().toGMTString();
  10. var algorithm = 'hmac-sha256';
  11. var headers = 'host date request-line';
  12. var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/tts HTTP/1.1`;
  13. var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret);
  14. var signature = CryptoJS.enc.Base64.stringify(signatureSha);
  15. var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
  16. var authorization = that.base64_encode(authorizationOrigin);
  17. url = `${url}?authorization=${authorization}&date=${date}&host=${host}`;
  18. resolve(url);
  19. });
  20. }
  21. async linkXunfeiSocket() {
  22. // 连接讯飞Socket服务器
  23. let url = await this.getWebsocketUrl();
  24. let XunfeiSocketTask;
  25. await new Promise((resolve, reject) => {
  26. XunfeiSocketTask = uni.connectSocket({
  27. url: encodeURI(url),
  28. header: {
  29. 'content-type': 'application/json'
  30. },
  31. success: () => {
  32. console.log(`讯飞 connect成功`);
  33. resolve();
  34. },
  35. fail: () => {
  36. console.log('讯飞 connect失败');
  37. reject();
  38. }
  39. });
  40. });
  41. this.xunfeiSocketTask = XunfeiSocketTask;
  42. this.initXunFei(this.xunfeiSocketTask);
  43. }
  44. initXunFei(xunfeiSocketTask) {
  45. // 监听消息
  46. xunfeiSocketTask.onMessage(res => {
  47. // console.log('接收讯飞消息');
  48. this.result(res.data);
  49. });
  50. xunfeiSocketTask.onOpen(() => {
  51. // console.log('讯飞websocket打开');
  52. this.webSocketSend();
  53. });
  54. xunfeiSocketTask.onClose(res => {
  55. clearTimeout(this.playTimeout);
  56. // console.error('讯飞断开');
  57. });
  58. xunfeiSocketTask.onError(err => {
  59. // console.error('讯飞连接错误', err);
  60. });
  61. }

注意:

(1)signature_sha:hmac-sha256算法结合apiSecret对signature_origin签名,使用crypto-js实现

  1. // 安装
  2. npm install crypto-js
  3. yarn add crypto-js
  4. // 引用
  5. import CryptoJS from 'crypto-js';

(2)signature:需要使用CryptoJS.enc.Base64.stringify()方式编码后使用

(3)authorization:需要base64编码后使用,编码方式如下(等同于Window.btoa())

  1. base64_encode(str) {
  2. // 编码,配合encodeURIComponent使用
  3. var c1, c2, c3;
  4. var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  5. var i = 0,
  6. len = str.length,
  7. strin = '';
  8. while (i < len) {
  9. c1 = str.charCodeAt(i++) & 0xff;
  10. if (i == len) {
  11. strin += base64EncodeChars.charAt(c1 >> 2);
  12. strin += base64EncodeChars.charAt((c1 & 0x3) << 4);
  13. strin += '==';
  14. break;
  15. }
  16. c2 = str.charCodeAt(i++);
  17. if (i == len) {
  18. strin += base64EncodeChars.charAt(c1 >> 2);
  19. strin += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
  20. strin += base64EncodeChars.charAt((c2 & 0xf) << 2);
  21. strin += '=';
  22. break;
  23. }
  24. c3 = str.charCodeAt(i++);
  25. strin += base64EncodeChars.charAt(c1 >> 2);
  26. strin += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
  27. strin += base64EncodeChars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
  28. strin += base64EncodeChars.charAt(c3 & 0x3f);
  29. }
  30. return strin;
  31. }

3.发送和接收数据

发送文本消息

  1. webSocketSend() {
  2. let params = {
  3. common: {
  4. app_id: APPID // 讯飞控制台查看
  5. },
  6. business: {
  7. aue: 'lame', // 音频编码表示mp3格式,当aue=lame时需传参sfl=1
  8. sfl: 1,
  9. vcn: 'xiaoyan', // 发音人选择
  10. tte: 'UTF8'
  11. },
  12. data: {
  13. status: 2,
  14. text: CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(this.toAudioText))
  15. }
  16. };
  17. this.xunfeiSocketTask.send({
  18. data: JSON.stringify(params),
  19. success: res => {
  20. // console.log('发出讯飞消息');
  21. },
  22. fail: err => {
  23. // console.log('发出讯飞消息失败', err);
  24. }
  25. });
  26. }

注意:

(1)发送的文本数据data的text需要使用base64编码

(2)send方法发送的数据需要转成json字符串

(3)返回的数据为合成后的音频片段,采用base64编码

 4. 将返回的音频片段组合,并转成可播放的MP3文件

当code为0,data.status为1时,表示合并中,将base64字符串合并

当code为0,data.status为2时,表示一句话合并完成,在此处将合并的base64转成音频文件

  1. result(resultData) {
  2. let jsonData = JSON.parse(resultData);
  3. //陆续合并接收的base64音频流
  4. this.audioBase64 += jsonData.data.audio;
  5. if (jsonData.code !== 0) {
  6. // 合成失败
  7. console.log(`${jsonData.code}:${jsonData.message}`);
  8. return;
  9. }
  10. if (jsonData.code === 0 && jsonData.data.status === 2) {
  11. // 分段发送完成,转成语音文件关闭连接
  12. // 注意:将base64转化成ArrayBuffer
  13. const data = uni.base64ToArrayBuffer(this.audioBase64);
  14. const target = `${wx.env.USER_DATA_PATH}/${new Date().getTime()}.mp3`;
  15. try {
  16. // 使用fs.writeFileSync完成音频文件的转化
  17. const res = fs.writeFileSync(target, data, 'binary');
  18. this.playAudio.push(target);
  19. this.xunfeiSocketTask.close();
  20. this.audioBase64 = '';
  21. } catch (e) {
  22. console.error(e);
  23. }
  24. }
  25. }

注意:使用fs.writeFileSync转文件时,传入的data为ArrayBuffer格式

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/77569
推荐阅读
相关标签
  

闽ICP备14008679号