improve player

- feat: add option to prefer HLS over DASH
- feat: add skip +/- 10sec to statusbar
- enhancement: tweek shaka config
This commit is contained in:
Shiny Nematoda 2024-07-10 15:29:50 +00:00
parent 4cf71ec22b
commit 071fe0ba86
7 changed files with 60 additions and 22 deletions

View file

@ -293,6 +293,10 @@ input[type='search']::-webkit-search-cancel-button:hover {
text-transform: capitalize; text-transform: capitalize;
} }
.hidden {
visibility: hidden;
}
.textbox { .textbox {
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
color: var(--color-text); color: var(--color-text);

View file

@ -1,3 +1,3 @@
{ {
"date": "2024-07-07" "date": "2024-07-10"
} }

View file

@ -80,10 +80,17 @@ async function Stream() {
preferredAudioCodecs: codecs ? codecs.split(':') : ['opus', 'mp4a'], preferredAudioCodecs: codecs ? codecs.split(':') : ['opus', 'mp4a'],
manifest: { manifest: {
disableVideo: true, disableVideo: true,
disableThumbnails: true,
}, },
streaming: { streaming: {
segmentPrefetchLimit: 2, segmentPrefetchLimit: 2,
bufferBehind: 50,
rebufferingGoal: 1,
stallEnabled: true,
}, },
dash: {
ignoreMinBufferTime: true,
}
}); });
window.audioPlayer = audioPlayer; window.audioPlayer = audioPlayer;

View file

@ -24,6 +24,7 @@ const { t, setupLocale } = useI18n(),
instances = ref([]), instances = ref([]),
hypInstances = ref([]), hypInstances = ref([]),
next = ref(false), next = ref(false),
hls = ref(false),
compact = ref(false), compact = ref(false),
prm = ref(false), prm = ref(false),
cc = ref(false), cc = ref(false),
@ -136,6 +137,7 @@ const verifyApi = computed(() =>
onMounted(() => { onMounted(() => {
getRestoreUrl(); getRestoreUrl();
getStoreBool('next', next, true); getStoreBool('next', next, true);
getStoreBool('hls', hls, false);
getStoreBool('compact', compact, false); getStoreBool('compact', compact, false);
getStoreBool('prm', prm, false); getStoreBool('prm', prm, false);
getStoreBool('cc', cc, false); getStoreBool('cc', cc, false);
@ -248,6 +250,17 @@ onMounted(() => {
</select> </select>
</div> </div>
<div class="left pt">
<input
type="checkbox"
name="pref-chk-hls"
id="pref-chk-hls"
class="input"
@change="setStore('hls', $event.target.checked)"
v-model="hls" />
<label for="pref-chk-next">{{ t('pref.hls') }}</label>
</div>
<div class="left"> <div class="left">
<label for="pref-quality">{{ t('pref.quality') }}</label> <label for="pref-quality">{{ t('pref.quality') }}</label>
<select <select
@ -291,7 +304,7 @@ onMounted(() => {
}" /> }" />
</div> </div>
<div class="left"> <div class="left pt">
<input <input
type="checkbox" type="checkbox"
name="pref-chk-preserve-pitch" name="pref-chk-preserve-pitch"
@ -499,6 +512,9 @@ label[for^='pref-chk'] {
.left + .left { .left + .left {
padding: 0; padding: 0;
} }
.left.pt {
padding-top: 1rem;
}
.table-wrap { .table-wrap {
overflow-x: auto; overflow-x: auto;
margin-bottom: 2rem; margin-bottom: 2rem;

View file

@ -127,20 +127,25 @@ async function Like() {
</div> </div>
<div class="statusbar-control-item center"> <div class="statusbar-control-item center">
<button <button
:style="{ :class="{
visibility: hidden: data.state.urls[
data.state.urls[ data.state.urls.findIndex((s) => s.url == data.state.url) - 1
data.state.urls.map(s => s.url).indexOf(data.state.url) - 1 ] == undefined &&
] || (player.state.loop != 1 || data.state.urls.length == 0),
(player.state.loop == 1 && data.state.urls.length > 1)
? 'visible'
: 'hidden',
}" }"
id="btn-previoustrack" id="btn-previoustrack"
aria-label="Play previous track" aria-label="Play previous track"
class="bi bi-chevron-bar-left clickable" class="bi bi-chevron-bar-left clickable"
@click="data.prevTrack"></button> @click="data.prevTrack"></button>
<button
:class="{ hidden: player.state.duration == 0 }"
id="btn-rewind"
aria-label="Rewind 10 seconds"
class="bi bi-chevron-left clickable"
@click="player.state.currentTime =
Math.max(0, player.state.currentTime - 10)"></button>
<button <button
id="btn-play-pause" id="btn-play-pause"
aria-label="Play or Pause" aria-label="Play or Pause"
@ -149,14 +154,19 @@ async function Like() {
@click="player.toggle('play')"></button> @click="player.toggle('play')"></button>
<button <button
:style="{ :class="{ hidden: player.state.duration == 0 }"
visibility: id="btn-forward"
data.state.urls[ aria-label="Forward 10 seconds"
data.state.urls.map(s => s.url).indexOf(data.state.url) + 1 class="bi bi-chevron-right clickable"
] || @click="player.state.currentTime =
(player.state.loop == 1 && data.state.urls.length > 1) Math.min(player.state.duration, player.state.currentTime + 10)"></button>
? 'visible'
: 'hidden', <button
:class="{
hidden: data.state.urls[
data.state.urls.findIndex((s) => s.url == data.state.url) + 1
] == undefined &&
(player.state.loop != 1 || data.state.urls.length == 0),
}" }"
id="btn-nexttrack" id="btn-nexttrack"
:aria-label="t('action.play_next_track')" :aria-label="t('action.play_next_track')"

View file

@ -95,7 +95,8 @@
"charts": "Charts", "charts": "Charts",
"library": "Library", "library": "Library",
"playback_rate": "Playback Rate", "playback_rate": "Playback Rate",
"preserves_pitch": "Preserve Pitch" "preserves_pitch": "Preserve Pitch",
"hls": "Prefer HLS over DASH"
}, },
"info": { "info": {
"see_all": "See All", "see_all": "See All",

View file

@ -111,11 +111,11 @@ export function useMetadata(now, data) {
export async function useManifest({ streams, duration, hls }) { export async function useManifest({ streams, duration, hls }) {
let url, mime; let url, mime;
const mse = window.MediaSource || window.ManagedMediaSource; const mse = window.MediaSource || window.ManagedMediaSource !== undefined;
const prefer_hls = useStore().getItem('hls') == 'true';
if (mse !== undefined && streams.length > 0) { if (mse && streams.length > 0 && !prefer_hls) {
const { useDash } = await import('./dash.js'); const { useDash } = await import('./dash.js');
const dash = useDash(streams, duration); const dash = useDash(streams, duration);
url = 'data:application/dash+xml;charset=utf-8;base64,' + btoa(dash); url = 'data:application/dash+xml;charset=utf-8;base64,' + btoa(dash);