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