业务需求:根据后台返回消息播报语音,要求后台运行可继续播报

实现步骤:

  1. 建立socket连接监听消息,并建立心跳检测机制,防止socket意外断连
  2. 将接收到的文字信息转化为音频文件
  3. 使用uni.getBackgroundAudioManager(),实现后台运行可以持续播报音频
  4. 解决并发问题,同时接收多个文件按顺序播报

1. 建立socket连接

onShow() {const SocketTask = getApp().globalData.SocketTask;if (!SocketTask) {this.linkSocket();}}
async linkSocket() {// 连接Socket服务器let SocketTask;const TOKEN = store.getters['base/_token'];await new Promise((resolve, reject) => {SocketTask = uni.connectSocket({url: wsUrl,header: {'content-type': 'application/json',Authorization: TOKEN },success: () => {console.log(`WebSocket connect成功`);resolve();},fail: () => {console.log('WebSocket connect失败');reject();}});});SocketTask.id = this.randomInt(1000, 9999);// 初始化心跳,心跳用于检测连接是否正常SocketTask.heartCheck = { ...heartCheck };SocketTask.reconnectObj = { ...reconnectObj };// 赋值全局变量,用于判断是否已连接getApp().globalData.SocketTask = this.SocketTask = SocketTask;// 开始监听this.initEventHandle(this.SocketTask);}randomInt(min, max) {return Math.floor(Math.random() * (max - min + 1) + min);}

定义心跳对象

// ws 心跳对象
let heartCheck = {timeout: 5000, // 收到pong后再次发ping的间隔时间;也是ws连接不上的最大等待时间 之后关掉连接并重连timeoutObj: null,serverTimeoutObj: null,reset: function() {clearTimeout(this.timeoutObj);clearTimeout(this.serverTimeoutObj);return this;},start: function(SocketTask) {this.timeoutObj = setTimeout(() => {SocketTask.send({ data: 'ping' });this.serverTimeoutObj = setTimeout(() => {SocketTask.close();}, this.timeout);}, this.timeout);}
};

消息监听

initEventHandle(SocketTask) {// 监听消息SocketTask.onMessage(res => {// 心跳检测,后台返回pong表示连接正常if (res.data === 'pong') {SocketTask.heartCheck.reset().start(SocketTask);} else {this.toAudioText = res.data;// 接收到文字消息转语音this.getMp3();}});SocketTask.onOpen(() => {console.log(`${SocketTask.id} WebSocket onOpen`);SocketTask.heartCheck.reset().start(SocketTask);SocketTask.heartCheck.isAlive = true;});SocketTask.onError(res => {console.log(`${SocketTask.id} WebSocket onError`, res);this.reconnect(SocketTask);});SocketTask.onClose(res => {console.log(`${SocketTask.id} WebSocket onClose`, res);SocketTask.heartCheck.isAlive = false;if (res.code === 4000 || res.code === 4001) {console.log(`${SocketTask.id} WebSocket ${res.code}关闭`);} else {// 非正常关闭 重连this.reconnect(SocketTask);}});}

重连机制

let reconnectObj = {timeout: 5000, // 重连间隔时间timer: null, // 重连计时器lock: false, // 重连锁limit: 0 // 重连最多次数
};...
reconnect(SocketTask) {if (SocketTask.reconnectObj.lock) return;SocketTask.reconnectObj.lock = true;clearTimeout(SocketTask.reconnectObj.timer);if (SocketTask.reconnectObj.limit < 24) {SocketTask.reconnectObj.timer = setTimeout(() => {this.linkSocket();SocketTask.reconnectObj.lock = false;}, SocketTask.reconnectObj.timeout);SocketTask.reconnectObj.limit++;} else {console.log(`${SocketTask.id}WebSocket reach limit 24!!!!!!!`);uni.showToast({title: '很抱歉,您与服务器失去连接,请重启小程序',icon: 'none'});}}

2.使用零七生活API完成文字转语音,api返回二进制音频流,直接在小程序无法播放,需要使用writeFile写入文件后可播放,注意播放完成后使用fs.unlink删除本地文件

const fs = uni.getFileSystemManager(); // 文件管理器API
...
getMp3() {const target = `${wx.env.USER_DATA_PATH}/${new Date().getTime()}.mp3`;return new Promise((resolve, reject) => {uni.request({url: `https://api.oick.cn/txt/apiz.php?text=${this.toAudioText}&spd=5`,method: 'GET',responseType: 'arraybuffer', // 注意此处,否则返回音频格式不可用success: (res: any) => {fs.writeFile({filePath: target,data: res.data,encoding: 'binary',success: res => {// 将接收到的消息推进消息队列this.playAudio.push(target);},fail: err => {console.log(err);}});},fail: (err: any) => {reject(err);}});});}

3. 播放背景音频:注意需要在 app.json 中配置 requiredBackgroundModes 属性

为了实现锁屏也可接收消息,进入页面后开始循环播放空音频,保证音频播放不中断,接收到消息后播放消息队列;

const backgroundAudioManager = uni.getBackgroundAudioManager();
...
onShow() {//循环播放音频this.playInit();}
playInit() {backgroundAudioManager.title = '语音播报';backgroundAudioManager.src = kong;backgroundAudioManager.onEnded(() => {if (this.index < this.playAudio.length) {console.log('播放列表:', this.playAudio);backgroundAudioManager.src = this.playAudio[this.index];// backgroundAudioManager.src = ding;this.index++;} else {backgroundAudioManager.src = kong;// 清空播放列表if (this.index > 0) {this.clearFile();this.playAudio = [];this.index = 0;}}});}

4.解决并发问题,定义playAudio数组用于存放音频队列,当接收多个消息时,将消息推入数组,当播放完一个音频后,检测数组是否为空,如果不为空,播放消息音频,否则继续播放空音频。

uniapp实现微信小程序websocket+背景音频语音播报相关推荐

  1. 微信小程序 设置背景音频

    先实例一个对象 设置它的url 和title(必填) 有了对象之后 就可以调用方法

  2. uniapp实现微信小程序音频播放倒计时的功能,类似微信语音条

    uniapp实现微信小程序音频播放功能 最近需要有个项目需要用到音频播放,第一个想到的是audio标签,但是查阅了uniapp官方文档,发现audio组件已经不维护了. 官网推荐使用uni.creat ...

  3. uniapp开发微信小程序,从构建到上线

    前言: 本文主要介绍 uniapp 的基础使用,以及使用 uniapp 在企业开发的过程中的一个详细流程,比较适合第一次使用uniapp 开发微信小程序的伙伴,或者没有过实战经验的小伙伴参考:使用 H ...

  4. 基于uni-app开发微信小程序__手牵手带你开发【懂你找图】项目

    前戏 某一天的夜里,敲完了代码之后便直接倒在床上睡着了,醒来时只记得梦里的一句话:"想要成为高手,就必须要大量实践,大量做项目,必须要把自己不会的东西全部吃透,不要得过且过.",猛 ...

  5. uniApp 生成微信小程序图片上传提示 fail url not in domain list 的解决方法

    问题表现: uniApp 生成微信小程序,获取内容程序不报错,但是图片上传提示 fail url not in domain list 错误. 问题分析: 微信小程序:服务器域名配置 每个微信小程序需 ...

  6. uniapp实现微信小程序端动态生成海报

    背景: 基于uniapp实现微信小程序中商品详情的海报生成与保存 效果图: 思路: 首先把海报上需要的内容准备好,比如用户头像,商品信息,二维码等.需要注意的是,因为二维码是动态生成的,所以需要后端传 ...

  7. uniapp开发微信小程序保存文件方案总结

    uniapp开发微信小程序保存文件方案总结 1.需求背景 最近正使用uniapp开发微信小程序项目,现需要保存文件. 解决方案 // 方法如下,filePath:文件地址:uni.authorize( ...

  8. uni-app开发微信小程序时u-view自定义样式不生效

    背景: 在使用uni-app开发微信小程序时,设置原生样式后无效 test1.vue文件 <template><view><u-radio-group v-model=& ...

  9. python天气查询小程序加背景图_微信小程序开发背景图显示功能

    这两天开发微信小程序,在设置背景图片时,发现在wxss里面设置background-image:(url) 属性,不管是开发工具还是线上都无法显示.经过查资料发现,background-image只能 ...

最新文章

  1. R语言构建广义相加模型(GAM:Generalized Additive Model)实战
  2. 【剑指offer】Q38:数字在数组中出现的次数
  3. 定时清理日志文件-python实现
  4. Java for 语句简化写法_Java 8 Lambda 写法与简化
  5. PHP判断远程url是否有效的几种方法
  6. Kafka 0.10.1.1 特点
  7. catalina 无法验证macos_拿什么拯救你,我的macOS Catalina——完整版补救措施来啦...
  8. MyCat基于MySQL实现读写分离
  9. Android双清卸载木马,刷机如何清除木马病毒
  10. CCF推荐+SCI二区期刊征收AI方向特刊|确定3个月出录用结果
  11. 关于华三路由器nat映射ftp端口号登录服务器失败问题
  12. java 斜杠常量_Java基础之常量
  13. pH响应UV交联壳聚糖水凝胶/氨基葡聚糖基生物杂化水凝胶NMPA-CS壳聚糖水凝胶的制备
  14. 腾讯视频、爱奇艺、豆果美食等为线下贷款中介导流、个人信息遭倒卖
  15. ELF格式解读 Dynamic节
  16. SmartFoxServer 2X管理工具
  17. RN + Flutter
  18. 简单的股票行情演示(一) - 实时标的数据
  19. android 服务自动运行怎么办,怎么解决安卓软件服务停止后又自启?
  20. java交错数组,C#交错数组用法实例

热门文章

  1. 一篇带你走进Vue+阿里云的uni-app开发(HBuilder X开发版)
  2. jetson xavier nx平台 Gstreamer tcpserverink延迟问题调试记录1
  3. Android应用CPU实时监控工具-全机型适用
  4. Hypergraph Neural Networks HGNN
  5. 用友服务器系统,用友软件 用友云服务器
  6. BOL简单分析(一)
  7. 加解密篇 - 什么是加密加盐 (分析web3j的加盐处理)
  8. 大一学生作品《前端框架开发技术》 期末网页制作 HTML+CSS+JavaScript 个人主页网页设计实例
  9. 最新研究动向:智能制造中可应用的技术【区块链与数字孪生】
  10. HTML设计网页之网页头部