当前位置: 首页 > news >正文

uni-app 微信小程序 WebSocket 接入讯飞语音合成(流式版)WebAPI 示例

文章目录

  • 语音合成(流式版)WebAPI 文档
  • 安装库
  • JS 完整代码

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

  • https://www.xfyun.cn/doc/tts/online_tts/API.html

安装库

yarn add crypto-js

JS 完整代码

import CryptoJS from 'crypto-js';

const config = {
  // 请求地址
  hostUrl: "wss://tts-api.xfyun.cn/v2/tts",
  host: "tts-api.xfyun.cn",
  //在控制台-我的应用-在线语音合成(流式版)获取
  appid: "xxxxx",
  //在控制台-我的应用-在线语音合成(流式版)获取
  apiSecret: "xxxxx",
  //在控制台-我的应用-在线语音合成(流式版)获取
  apiKey: "xxxxx",
  uri: "/v2/tts",
}

const getWebSocketUrl = () => {
  let url = "wss://tts-api.xfyun.cn/v2/tts";
  let date = new Date().toGMTString();
  let algorithm = "hmac-sha256";
  let headers = "host date request-line";
  let signatureOrigin = `host: ${config.host}\ndate: ${date}\nGET /v2/tts HTTP/1.1`;
  let signatureSha = CryptoJS.HmacSHA256(signatureOrigin, config.apiSecret);
  let signature = CryptoJS.enc.Base64.stringify(signatureSha);
  let authorizationOrigin = `api_key="${config.apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
  let authorization = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(authorizationOrigin))
  return `${url}?authorization=${authorization}&date=${date}&host=${config.host}`;
}

const encodeText = (text, type) => {
  if (type === "unicode") {
    // 使用CryptoJS处理UTF-16BE编码
    const utf16BE = CryptoJS.enc.Utf16BE.parse(text);
    return CryptoJS.enc.Base64.stringify(utf16BE);
  } else {
    // 使用CryptoJS的Base64直接编码
    const utf8WordArray = CryptoJS.enc.Utf8.parse(text);
    return CryptoJS.enc.Base64.stringify(utf8WordArray);
  }
}

const writeFile = (path, data) => {
  const fs = uni.getFileSystemManager()
  return new Promise((resolve, reject) => {
    fs.writeFile({
      filePath: path,
      data,
      encoding: 'utf8',
      success: resolve,
      fail: reject
    });
  });
}

const play = (target) => {
  const innerAudioContext = uni.createInnerAudioContext();
  innerAudioContext.autoplay = true;
  innerAudioContext.src = target;
  innerAudioContext.onPlay(() => {
    console.log('播放事件');
  })

  innerAudioContext.onError((err) => {
    console.log('错误事件', err);
  })
}

export const ttsTest = async (msg) => {
  const wssUrl = getWebSocketUrl()

  const msgData = {
    "common": {
      "app_id": config.appid
    },
    "business": {
      "aue": "lame",
      "auf": "audio/L16;rate=16000",
      "vcn": "xiaoyan",
      "tte": "UTF8"
    },
    "data": {
      "text": encodeText(msg, 'UTF8'),
      "status": 2
    }
  }

  const socketTask = await uni.connectSocket({
    url: wssUrl,
    header: {
      'content-type': 'application/json'
    },
    method: 'GET',
    success: (res) => {
      console.log('connectSocket success', res)
    },
    fail: (err) => {
      console.log('connectSocket fail', err)
    },
    complete: (res) => {
      console.log('connectSocket complete', res)
    }
  });

  socketTask.onMessage(res => {
    console.log('onMessage', JSON.parse(res.data))
    const { code, message, sid, data } = JSON.parse(res.data);
    if (code === 0 && data.status === 2) {
      // 注意:将base64转化成ArrayBuffer
      const dataBuffer = uni.base64ToArrayBuffer(data.audio);
      const target = `${wx.env.USER_DATA_PATH}/${new Date().getTime()}.mp3`;
      console.log('target', target)
      try {
        writeFile(target, dataBuffer)
        // 播放
        play(target)
        socketTask.close(res => {
          console.log('close', res)
        })
      } catch (e) {
        console.error(e);
        socketTask.close(res => {
          console.log('close', res)
        })
      }
    }
  })

  socketTask.onClose(res => {
    console.log('onClose', res)
  })

  socketTask.onError(err => {
    console.log('onError', err)
  })

  socketTask.onOpen(data => {
    console.log('onOpen', data)
	  
    socketTask.send({
      data: JSON.stringify(msgData),
      success: (res) => {
        console.log('send', res)
      }
    })
	  
  })

}

http://www.dtcms.com/a/108495.html

相关文章:

  • 【Redis】如何处理缓存穿透、击穿、雪崩
  • 在 Blazor 中使用 Chart.js 快速创建数据可视化图表
  • 大模型生成浏览器端的初级俄罗斯方块
  • 美团民宿 mtgsig 小程序 mtgsig1.2 分析
  • Unity中的C#脚本中文字符无法正常显示问题
  • mysql-创建和删除索引的两种方式
  • 针对 MySQL 数据库中 主键/唯一约束的更新方法 和 ON DUPLICATE KEY UPDATE 语法的详细说明及示例,并以表格总结
  • YOLOv11区域检测
  • Element Plus 常用组件
  • 超越人工智能驱动的网络攻击:现代防御者的策略
  • 电子电气架构 --- 智能座舱域控设计
  • Flutter 音视频播放器与弹幕系统开发实践
  • RK3588使用笔记:USB转232、485、422模块驱动适配
  • [蓝桥杯 2024 省 A] 训练士兵
  • 虚拟试衣间-云尚衣橱小程序-衣橱管理实现
  • 算法:二进制求和
  • 从零构建大语言模型全栈开发指南:第四部分:工程实践与部署-4.3.3低代码开发:快速构建行业应用(电商推荐与金融风控案例)
  • Python 驱动周立功200U收发报文
  • 国产系统服务器识别不到SATA盘
  • STM32学习笔记之RCC模块(实操篇)
  • 横扫SQL面试——中位数问题
  • git tag
  • Linux 中CIFS和NFS使用说明
  • MCP学习总结
  • 基于RapidIO接口的DSP+GPU工业AI实时计算解决方案
  • ‘conda‘ 不是内部或外部命令,也不是可运行的程序或批处理文件
  • 【YOLOv8】YOLOv8改进系列(12)----替换主干网络之StarNet
  • 系统安全——文件监控-FileMonitor
  • 数据在内存中存储(C语言)
  • 杂篇-行业分类一二-2(通、专用设备制造,汽车制造)