Uniapp 小程序:语音播放与暂停功能的实现及优化方案

界面部分

js 复制代码
//开启语音 
<button class="open" v-if="showPlay==false" @click="playText">这是开启播放的图片</button >

//关闭语音 
<button class="close" v-if="showPlay==true" @click="stopText">这是关闭播放的图片</button >

播放语音方法 playText

该方法用于处理语音播放的逻辑,包括内容截断、分割、重试机制等。

javascript 复制代码
playText: function() {
    // 检查是否正在等待响应,如果是则提示用户等待
    // 切换显示为正在播放状态
    this.showPlay = true; 
    // 初始化重试次数
    let retryCount = 0; 
    // 设置最大重试次数
    const maxRetryTimes = 3; 
    // 重试间隔时间(单位:毫秒)
    const retryInterval = 2000; 
    // 假设最大允许的内容长度,可根据实际调整
    const maxContentLength = 100; 

    // 截断内容的函数,如果内容长度超过最大允许长度,则截取前 maxContentLength 个字符
    const truncateContent = (content) => {
        if (content.length > maxContentLength) {
            return content.slice(0, maxContentLength);
        }
        return content;
    };

    // 分割内容的函数,将长内容按合适的分割符号(。!,?)分割成多个部分
    const splitContent = (content) => {
        const parts = [];
        let start = 0;
        while (start < content.length) {
            let end = start + maxContentLength;
            if (end >= content.length) {
                parts.push(content.slice(start));
                break;
            }
            // 从后往前查找合适的分割符号(。!,?)
            let symbolIndices = [content.lastIndexOf('。', end), content.lastIndexOf('!', end), content
               .lastIndexOf('?', end), content.lastIndexOf(',', end)
            ];
            symbolIndices = symbolIndices.filter(index => index > start);
            if (symbolIndices.length > 0) {
                end = Math.max(...symbolIndices);
            }
            parts.push(content.slice(start, end));
            start = end + 1;
        }
        return parts;
    };

    // 播放分割后的内容部分的函数
    const playParts = (parts) => {
        let index = 0;
        const playNextPart = () => {
            if (index < parts.length) {
                const part = parts[index];
                const plugin = requirePlugin('WechatSI');
                // 调用文字转语音插件
                plugin.textToSpeech({
                    lang: 'zh_CN',
                    tts: true,
                    content: part,
                    success: (res) => {
                        // 创建内部音频上下文并播放音频
                        this.innerAudioContext = uni.createInnerAudioContext();
                        this.innerAudioContext.src = res.filename;
                        this.innerAudioContext.play();
                        // 监听音频播放结束事件,播放下一部分
                        this.innerAudioContext.onEnded(() => {
                            index++;
                            playNextPart();
                        });
                    },
                    fail: (res) => {
                        console.log('文字转语音失败', res);
                        if (retryCount < maxRetryTimes) {
                            retryCount++;
                            console.log(`正在进行第${retryCount}次重试...`);
                            // 重试播放
                            setTimeout(() => playNextPart(), retryInterval);
                        } else {
                            console.log('已达到最大重试次数,文字转语音仍失败');
                        }
                    }
                });
            } else {
                // 所有部分播放完毕,切换显示为可播放状态
                this.showPlay = false; 
            }
        };
        playNextPart();
    };

    // 截断内容
    const truncatedContent = truncateContent(this.readContent);
    // 分割内容
    const splitContents = splitContent(this.readContent);
    if (splitContents.length > 1) {
        // 如果分割后的内容部分大于 1,则按部分播放
        playParts(splitContents);
    } else {
        // 内容较短,直接播放
        const retryFn = () => {
            if (retryCount < maxRetryTimes) {
                retryCount++;
                console.log(`正在进行第${retryCount}次重试...`);
                const plugin = requirePlugin('WechatSI');
                // 调用文字转语音插件
                plugin.textToSpeech({
                    lang: 'zh_CN',
                    tts: true,
                    content: truncatedContent,
                    success: (res) => {
                        // 创建内部音频上下文并播放音频
                        this.innerAudioContext = uni.createInnerAudioContext();
                        this.innerAudioContext.src = res.filename;
                        this.innerAudioContext.play();
                    },
                    fail: (res) => {
                        console.log('文字转语音失败', res);
                        // 重试播放
                        setTimeout(retryFn, retryInterval);
                    }
                });
            } else {
                console.log('已达到最大重试次数,文字转语音仍失败');
            }
        };
        const plugin = requirePlugin('WechatSI');
        // 调用文字转语音插件
        plugin.textToSpeech({
            lang: 'zh_CN',
            tts: true,
            content: truncatedContent,
            success: (res) => {
                // 创建内部音频上下文并播放音频
                this.innerAudioContext = uni.createInnerAudioContext();
                this.innerAudioContext.src = res.filename;
                this.innerAudioContext.play();
            },
            fail: (res) => {
                console.log('文字转语音失败', res);
                // 重试播放
                setTimeout(retryFn, retryInterval);
            }
        });
    }
}

暂停语音方法 stopText

该方法用于停止语音播放并释放资源。

javascript 复制代码
stopText() {
    // 切换显示为可播放状态
    this.showPlay = false;
    if (this.innerAudioContext) {
        // 停止播放
        this.innerAudioContext.stop(); 
        // 释放资源
        this.innerAudioContext = null; 
    }
}

页面隐藏和卸载时的处理

在页面隐藏和卸载时,调用 stopText 方法停止语音播放。

javascript 复制代码
onHide() {
    this.stopText()
},
onUnload() {
    this.stopText()
}

总结

这段代码实现了语音播放和暂停的功能,通过界面上的按钮触发相应的操作。在播放语音时,会对内容进行截断和分割处理,以适应文字转语音插件的要求。同时,为了提高稳定性,添加了重试机制。在页面隐藏和卸载时,会自动停止语音播放并释放资源。

相关推荐
郭邯10 小时前
从零到一:我用 AI 写了个复利计算器,顺便治好了我的"公式恐惧症"
前端
Pointer Pursuit10 小时前
C++11特性(二)
前端·c++·算法
天道kabuto10 小时前
Vue3 升级踩坑:子组件 click 事件为什么会触发两次?
前端
Nayana10 小时前
《Web 到 HarmonyOS》-- Ability、Stage、模块化与路由导航
前端
Quor10 小时前
小程序工作室:AI 生成即运行的可视化工作台
人工智能·小程序
ShineWinsu11 小时前
对于 Vue 3:从为什么学 Vue,到声明式渲染与数据响应式的解析
前端·javascript·vue.js
粥里有勺糖11 小时前
视野修炼-技术周刊第132期 | 一些有趣的组件
前端·github·aigc
এ慕ོ冬℘゜11 小时前
样式控制 .css ()
前端·css
天府云创11 小时前
uni-app X 蒸汽模式发布!性能比肩原生~
前端框架·uni-app·移动开发·原生应用·蒸汽模式·app研发·多端适配
leoZ23112 小时前
第 6 篇:SchemaForm 渲染器核心实现
前端·javascript·vue.js·人工智能·神经网络·机器学习·自然语言处理