针对上一篇微信同声传译语音播报部分坑的解决和优化

2024-05-25 14:20

本文主要是介绍针对上一篇微信同声传译语音播报部分坑的解决和优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 上一篇语音播报其实是不完美的,就是如何停止上一个音频开始下一个音频的问题,我在此做一下修改

在这里插入图片描述
比如说:现在正在播放1,我点击2让2开始播放,1停止播放,我上面的写法是有问题的:

  • 通过 innerAudioContext.pause() 是可以停止播放音频的;
  • wx.createInnerAudioContext()的实例,我是在readStart方法里面创建的
  • 再次执行readStart方法,会重新创建wx.createInnerAudioContext()实例
  • 我们如果在点击播放图标的时候执行pause() 方法,执行的不是正在播放的音频的实例

因此:我们需要创建一个全局的实例,这样我们执行pause() 方法时,在同一个实例下,就是停止正在播放的音频
代码如下:

	data:{dialogue:'您好,我是您的健康管家"向我提问。您好,我是您的健康管家"质迹"!您有什么疑问都可以在此向我提问。',type:'play'}// 在onLoad中创建一个全局的实例onLoad(){this.innerAudioContext = wx.createInnerAudioContext();}// 阅读文字readText: async function () {const that = this;// ------------------------------在点击播放图标之前,我们先执行一个pause()方法,停止上一段音频--------------------that.innerAudioContext.pause()that.setData({type :'pause'})// 将文字按照每200个长度截取成一段,组成一个数组// 切片处理,将超过1000个字符的文字,截取成几段let list =this.splitStringByLength(dialogue, 200)// 循环遍历数组,将文字转化成音频let radioList = list.map(el => {return new Promise(resolve => {plugin.textToSpeech({lang: "zh_CN",tts: true,content: el,success: function (res) {resolve(res.filename)},fail: function (res) {wx.showToast({title: '语音转换失败',})}})})})// 将promise执行结果放在一起执行(解决for循环中有异步操作的方法之一,经典面试题)// 有个弊端: 如果前面的promise有一个执行错误,Promise.all就不会执行,因此:可以用map/filter将radioList过滤一遍(本项目中有一个Promise执行失败,就应该失败)Promise.all(radioList).then(res => {that.readStart(res)})},// 将字符串每隔length个就截取一段splitStringByLength :function (str, length)  {let result = [];for (let i = 0; i < str.length; i += length) {result.push(str.substring(i, i + length));}return result;}// 开始阅读readStart: async function (radioList) {const that = thisfor (let text of radioList) {// --------------------------在此就不需要再次创建实例了---------------------------// const innerAudioContext = wx.createInnerAudioContext();that.innerAudioContext.src = text;that.innerAudioContext.onPlay(() => {console.log('开始播放当前片段', 'onPlay');});that.innerAudioContext.onError((err) => {console.error('音频播放出错', err);});that.innerAudioContext.onEnded(async () => {// 如果是最后一个片段,这里可以结束,否则不需要awaitif (text === radioList[radioList.length - 1]) {that.setData({type: 'play',})}});// 确保前一个音频播放结束后再播放下一个await new Promise(resolve => {that.innerAudioContext.onEnded(resolve);that.innerAudioContext.play();});}},// 暂停阅读readPause: function () {this.innerAudioContext.pause()const that = this;that.setData({type: 'play',})}

2. 对于splitStringByLength方法,我也进行了一些优化 (wx.createInnerAudioContext()只支持1000个字符以内的文字转为音频)

下面一段代码是无脑按照长度切割,在进行语音播报的时候,第一段语音和第二段语音之前的衔接会有1-2秒的停顿,语音播报不流畅
比如:您好,我是您的健康管家"向我提问。您好,我是您的健康 | 管家"质迹"!您有什么疑问都可以在此向我提问。
在 | 处切成两段,语音在播放到‘康’的时候,会停顿1-2秒,在开始播放‘管家…’

splitStringByLength :function (str, length)  {let result = [];for (let i = 0; i < str.length; i += length) {result.push(str.substring(i, i + length));}return result;}

在此,我对切割方法进行了一下优化

  • 不超过length的长度,不进行切割
  • 超过length的长度,首先找中文句号,在中文句号处切割
  • 如果整个文本都没有中文句号,则在中文逗号处切割
  • 语音在逗号和句号处本来就是会停顿的,在此处切割,这样用户的体验更好一些
const splitStringByLength = (text, length) => {const MAX_LENGTH = length;  // 最大长度const CHINESE_PERIOD = '。'; // 首个切割条件const CHINESE_COMMA = ',';  // 当首个切割条件不存在时的次要切割条件let result = [];let startIndex = 0;// 文本长度不超过最大长度,就不切割,直接返回if (text.length < MAX_LENGTH) {return [text]}while (startIndex < text.length) {// 查找下一个中文句号的位置,若找不到则返回-1let periodIndex = text.indexOf(CHINESE_PERIOD, startIndex);if (periodIndex === -1 || periodIndex - startIndex > MAX_LENGTH) {// 如果没有找到句号,或者句号距离起始点超过了300个字符// 则查找中文逗号的位置,同样,若找不到则返回-1let commaIndex = text.lastIndexOf(CHINESE_COMMA, startIndex + MAX_LENGTH);if (commaIndex === -1 || commaIndex <= startIndex) {// 如果也没有找到逗号,或者逗号位置不满足条件,则直接在MAX_LENGTH处截断result.push(text.substring(startIndex, startIndex + MAX_LENGTH));startIndex += MAX_LENGTH;} else {// 找到了逗号并且位置合适,就在逗号后分割result.push(text.substring(startIndex, commaIndex + 1));startIndex = commaIndex + 1;}} else {// 找到了句号并且位置合适,就在句号后分割result.push(text.substring(startIndex, periodIndex + 1));startIndex = periodIndex + 1;}}return result;
}

这篇关于针对上一篇微信同声传译语音播报部分坑的解决和优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1001754

相关文章

504 Gateway Timeout网关超时的根源及完美解决方法

《504GatewayTimeout网关超时的根源及完美解决方法》在日常开发和运维过程中,504GatewayTimeout错误是常见的网络问题之一,尤其是在使用反向代理(如Nginx)或... 目录引言为什么会出现 504 错误?1. 探索 504 Gateway Timeout 错误的根源 1.1 后端

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

Java实现复杂查询优化的7个技巧小结

《Java实现复杂查询优化的7个技巧小结》在Java项目中,复杂查询是开发者面临的“硬骨头”,本文将通过7个实战技巧,结合代码示例和性能对比,手把手教你如何让复杂查询变得优雅,大家可以根据需求进行选择... 目录一、复杂查询的痛点:为何你的代码“又臭又长”1.1冗余变量与中间状态1.2重复查询与性能陷阱1.

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁