Hyperpipe/src/components/Player.vue
Shiny Nematoda 98fb69e7d5 remove for offline content
- added translateion for logout
- destroy offline strorage with player
2023-10-08 06:52:25 +00:00

233 lines
6 KiB
Vue

<script setup>
import { ref, watch, onMounted, onBeforeUnmount, onUnmounted } from 'vue';
import muxjs from 'mux.js';
window.muxjs = muxjs;
import { useStore, useRoute, useManifest } from '@/scripts/util.js';
import { useData, usePlayer } from '@/stores/player.js';
import { useAlert } from '@/stores/misc';
const player = usePlayer(),
data = useData(),
store = useStore(),
a = useAlert();
const audio = ref(null);
function audioCanPlay() {
player.state.status = 'pause';
audio.value.play().catch(err => {
console.error(err);
player.state.status = 'play';
});
if (location.pathname != '/playlist') useRoute(data.state.url);
document.title = `Playing: ${data.state.title} by ${data.state.artist}`;
}
async function Stream() {
const res = player.state,
shaka = import('shaka-player/dist/shaka-player.compiled.js');
const { url, mime } = await useManifest(res);
if (!window.audioPlayer) {
shaka
.then(shaka => shaka.default)
.then(shaka => {
shaka.polyfill.installAll();
if (shaka.Player.isBrowserSupported()) {
const audioPlayer = new shaka.Player(audio.value),
codecs = store.getItem('codec');
audioPlayer
.getNetworkingEngine()
.registerRequestFilter((_type, req) => {
const headers = req.headers;
let url = new URL(req.uris[0]);
if (url.pathname.indexOf('/videoplayback') > -1) {
if (headers.Range) {
url.searchParams.set('range', headers.Range.split('=')[1]);
req.headers = {};
req.uris[0] = url.toString();
}
}
});
window.offline = new shaka.offline.Storage(audioPlayer);
window.offline.configure({
offline: {
progressCallback: ({ appMetadata: { title, artist } }, prog) =>
a.add(`${title} by ${artist}: ${Math.floor(prog * 100)}%`),
trackSelectionCallback: tracks => [
tracks
.sort((a, b) => a.bandwidth - b.bandwidth)
.find(i => i.type == 'variant'),
],
},
});
audioPlayer.configure({
preferredAudioCodecs: codecs ? codecs.split(':') : ['opus', 'mp4a'],
manifest: {
disableVideo: true,
},
streaming: {
segmentPrefetchLimit: 2,
},
});
window.audioPlayer = audioPlayer;
}
});
}
const quality = store.getItem('quality');
if (url) {
window.audioPlayer
.load(url, 0, mime)
.then(() => {
window.audioPlayer.configure('abr.enabled', true);
if (quality && quality != 'auto') {
window.audioPlayer.configure('abr.enabled', false);
const tracks = window.audioPlayer.getVariantTracks(),
bandwidths = tracks.map(i => i.bandwidth);
let sel;
if (quality == 'best') sel = Math.max(...bandwidths);
else if (quality == 'worst') sel = Math.min(...bandwidths);
if (sel)
window.audioPlayer.selectVariantTrack(
tracks[bandwidths.indexOf(sel)],
);
}
})
.catch(err => {
console.error(err);
a.add('Error: ' + err.code);
});
}
}
function destroy() {
if (window.audioPlayer) {
window.audioPlayer.destroy();
window.audioPlayer = undefined;
}
if (window.offline) {
window.offline.destroy();
window.offline = undefined;
}
}
const titleState = ['Playing', 'Paused'];
watch(
() => player.state.play,
() => {
if (audio.value.paused) {
player.state.status = 'pause';
audio.value.play().catch(err => {
console.error(err);
player.state.status = 'play';
});
} else {
player.state.status = 'play';
audio.value.pause();
}
if (
document.title.startsWith(titleState[0] + ':') ||
document.title.startsWith(titleState[1] + ':')
)
document.title = audio.value.paused
? document.title.replace(titleState[0], titleState[1])
: document.title.replace(titleState[1], titleState[0]);
},
);
watch(() => player.state.streams, Stream);
watch(
() => player.state.currentTime,
() => {
console.log(player.state.currentTime);
audio.value.currentTime = player.state.currentTime;
},
);
onMounted(() => {
Stream();
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('play', () => {
player.state.status = 'pause';
document.title = document.title.replace(titleState[1], titleState[0]);
audio.value.play().catch(err => {
console.log(err);
player.state.status = 'play';
document.title = document.title.replace(titleState[0], titleState[1]);
});
});
navigator.mediaSession.setActionHandler('pause', () => {
audio.value.pause();
player.state.status = 'play';
document.title = document.title.replace(titleState[0], titleState[1]);
});
navigator.mediaSession.setActionHandler('previoustrack', () => {
if (data.state.urls.length > 2) {
const i = data.state.urls.findIndex(s => s.url == data.state.url);
data.play(data.state.urls[i - 1]);
}
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
if (data.state.urls.length > 2) {
const i = data.state.urls.findIndex(s => s.url == data.state.url);
data.play(data.state.urls[i + 1]);
}
});
navigator.mediaSession.setActionHandler('seekbackward', () => {
audio.value.currentTime -= 10;
});
navigator.mediaSession.setActionHandler('seekforward', () => {
audio.value.currentTime += 10;
});
}
});
onBeforeUnmount(() => {
destroy();
});
onUnmounted(() => {
destroy();
});
</script>
<template>
<audio
id="audio"
ref="audio"
:volume="player.state.vol"
@canplay="audioCanPlay"
@timeupdate="player.setTime($event.target.currentTime)"
@ended="data.playNext"
autoplay></audio>
</template>