mux.js的使用

//<script src="https://cdn.bootcdn.net/ajax/libs/mux.js/6.2.0/mux-mp4.min.js"></script>
const AUDIO_MIME = 'audio/mp4; codecs="mp4a.40.2"';
class LivePlayer {
    constructor() {
        this._player = new Audio();
        this._player.autoplay = true;

        this._isPaused = false;
        this._isFirst = true;
        this._url = '';
        this._uri = '';

        this._tmr = null;
    }

    play(url) {
        if (url) {
            this._url = url;
        }
        if (!this._url) return;

        this._uri = '';
        this._isFirst = true;
        this._isPaused = false;

        this._mediaSource?.endOfStream();
        this._transmuxer?.dispose();

        this._mediaSource = new window.MediaSource();
        this._player.src = window.URL.createObjectURL(this._mediaSource);
        this._mediaSource.onsourceopen = () => {
            window.URL.revokeObjectURL(this._player.src);
            this._mediaSource.addSourceBuffer(AUDIO_MIME);
            this._reqRealUrl();
        };

        this._transmuxer = new muxjs.Transmuxer();
        this._transmuxer.on('data', segment => {
            let buffer;
            if (this._isFirst) {
                this._isFirst = false;
                buffer = new Uint8Array(segment.initSegment.byteLength + segment.data.byteLength);
                buffer.set(segment.initSegment, 0);
                buffer.set(segment.data, segment.initSegment.byteLength);
            } else {
                buffer = new Uint8Array(segment.data);
            }
            this._mediaSource.sourceBuffers[0].appendBuffer(buffer);
        });
    }

    pause() {
        this._isPaused = true;
        this._player.pause();
    }

    d(...args) {
        window.console.log(new Date().toLocaleTimeString(), ...args);
    }

    _reqStream() {
        this.d('reqStream', this._uri);
        window.fetch(this._uri)
            .then(res => res.arrayBuffer())
            .then(buffer => {
                this._transmuxer?.push(new Uint8Array(buffer));
                this._transmuxer?.flush();
            });
    }

    _reqRealUrl() {
        if (!this._isPaused) {
            window.fetch(this._url)
                .then(res => res.text())
                .then(m3u8 => {
                    const latest = m3u8.trim().split(/\r\n|\n/).filter(it => it !== '').at(-1);
                    if (this._uri !== latest) {
                        this._uri = latest;
                        this._reqStream();
                    }
                });
        }
        window.clearTimeout(this._tmr);
        this._tmr = window.setTimeout(() => this._reqRealUrl(), 2E3);
    }
}

(function () {
    const player = window.player = new LivePlayer();
    window.expose = new class {
        get volume() { return player._player.volume; }
        set volume(vol) { player._player.volume = vol; }

        get muted() { return player._player.muted; }
        set muted(muted) { player._player.muted = muted; }

        get playingId() { return this._playingId; }

        get paused() { return player._isPaused; }

        constructor() {
            this._playingId = '';
        }

        play(channelId) {
            if (channelId) {
                this._playingId = channelId;
                player.play(`http://live.ximalaya.com/radio-first-page-app/live/${channelId}/64.m3u8?transcode=ts`);
            } else {
                this._playingId && player.play();
            }
        }

        pause() {
            player.pause();
        }
    }
})();
posted @ 2023-02-28 12:03  风的线条昵称已被使用  阅读(537)  评论(0编辑  收藏  举报