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

发布于:2025-02-27 ⋅ 阅读:(18) ⋅ 点赞:(0)

界面部分

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

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

播放语音方法 playText

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

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

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

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

页面隐藏和卸载时的处理

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

onHide() {
    this.stopText()
},
onUnload() {
    this.stopText()
}

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


网站公告

今日签到

点亮在社区的每一天
去签到