动态

详情 返回 返回

封裝uniapp微信小程序流式語音播放類 - 动态 详情

uniapp微信小程序端的websocket返回的base64音頻數據自動緩存播放,你可以修改緩衝隊列數,可以播放和暫停

class AudioPlay {
    constructor() {
        // createInnerAudioContext
        this.audioContext = uni.createInnerAudioContext();
        // 自動播放
        this.audioContext.autoplay = true;
        // 緩衝數組
        this.queue = [];
        // 至少n個片段才開始播放
        this.MIN_BUFFER = 4
        // 是否正在播放
        this.isPlaying = false;
        // 是否已傳入最後一段音頻
        this.isFinish = false;
    }
 
    /**
     * 添加播放隊列和播放音頻
     * @param base64 音頻數據
     * @param isFinish 是否已傳入最後一段音頻
     */
    async addQueuePlay(base64, isFinish) {
        this.isFinish = isFinish;
        this.queue.push(base64)
        // 未播放,且隊列數大於指定長度
        if (!this.isPlaying && this.queue.length >= this.MIN_BUFFER) {
            this.playNext();
        } else if (!this.isPlaying && this.isFinish) {
            // 沒有播放但音頻數據已完全傳入,兼容時長不足n秒的短音頻
            this.playNext();
        }
    }

    /**
     * 播放下一個音頻
     */
    async playNext() {
        // 隊列長度為0, 暫停播放
        if (this.queue.length === 0) {
            return (this.isPlaying = false);
        }
        // 獲取隊列第一個音頻
        let base64 = this.queue.shift();
        // mp3的base64格式數據頭
        let mp3Head = 'data:audio/mp3;base64,';
        // 微信小程序環境播放mp3必須要完整的base64格式
        // 拼接完整base64,移除Base64字符串中可能存在的換行符
        this.audioContext.src = mp3Head + base64.replace(/[\r\n]/g, '');
        // 播放
        this.audioContext.onPlay(() => {
            this.isPlaying = true;
        });
        // 自然播放結束
        this.audioContext.onEnded(() => {
            // 已傳入最後一個音頻數據,且隊列為0
            if (this.isFinish && this.queue.length == 0) {
                this.stopConnection();
            } else {
                this.playNext();
            }
        });
    }

    /**
     * 停止播放
     */
    async stopConnection() {
        try {
            if (this.audioContext) {
                // 停止播放
                this.audioContext.stop();
                // 取消播放監聽和結束監聽
                this.audioContext.offPlay();
                this.audioContext.offEnded();
            }
            // 重置隊列、播放狀態、isFinish狀態
            this.queue.length = 0;
            this.isPlaying = false;
            this.isFinish = false;
        } catch (err) {
            console.log(`手動斷開失敗: ${err}`);
        }
    };
}

export default AudioPlay;

頁面使用

<script setup>
import AudioPlay from "@/utils/AudioPlay.js"

const audioPlay = new AudioPlay();
// websocket響應
const onMessage = (e) => {
    // 其它邏輯...
  
        audioPlay.addQueuePlay(data.base64, data.isFinish)
};

// 斷開連接
const stopConnection = async () => {
    try {
        audioPlay.stopConnection();

    // 其它邏輯...
    
    } catch (err) {
        console.log(`手動斷開失敗: ${err}`);
    }
};
</script>

參考資料:
createInnerAudioContext

user avatar everfind 头像 caigaobadoudehuangdou_depjnr 头像
点赞 2 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.