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()
}

总结

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

相关推荐
胡耀超8 分钟前
Web Crawling 网络爬虫全景:技术体系、反爬对抗与全链路成本分析
前端·爬虫·python·网络爬虫·数据采集·逆向工程·反爬虫
阿明的小蝴蝶12 分钟前
记一次Gradle环境的编译问题与解决
android·前端·gradle
Ruihong14 分钟前
【VuReact】轻松实现 Vue 到 React 路由适配
前端·react.js
山_雨15 分钟前
startViewTransition
前端
写代码的【黑咖啡】18 分钟前
Python Web 开发新宠:FastAPI 全面指南
前端·python·fastapi
凉_橙18 分钟前
gitlab CICD
前端
wangfpp20 分钟前
性能优化,请先停手:为什么我劝你别上来就搞优化?
前端·javascript·面试
踩着两条虫22 分钟前
AI 驱动的 Vue3 应用开发平台 深入探究(二十):CLI与工具链之构建配置与Vite集成
前端·vue.js·ai编程
凉_橙23 分钟前
前端项目与node项目部署记录
前端
踩着两条虫27 分钟前
AI 驱动的 Vue3 应用开发平台 深入探究(二十):CLI与工具链之自定义构建插件
前端·vue.js·ai编程