mirror of
https://github.com/VueTubeApp/VueTube
synced 2024-11-25 12:45:17 +00:00
player settings: preload
This commit is contained in:
parent
51b0be2acd
commit
c598603450
6 changed files with 180 additions and 73 deletions
|
@ -33,8 +33,12 @@
|
|||
:height="isFullscreen ? '100%' : 'auto'"
|
||||
style="transition: filter 0.15s ease-in-out, transform 0.15s linear"
|
||||
:class="
|
||||
controls || seeking || skipping
|
||||
? verticalFullscreen
|
||||
controls ||
|
||||
seeking ||
|
||||
skipping ||
|
||||
($store.state.player.preload && buffered < 100)
|
||||
? verticalFullscreen &&
|
||||
!($store.state.player.preload && buffered < 100)
|
||||
? 'dim-ish'
|
||||
: 'dim'
|
||||
: ''
|
||||
|
@ -137,6 +141,7 @@
|
|||
|
||||
<!-- controls container -->
|
||||
<div
|
||||
v-if="$refs.player && $refs.player.currentSrc"
|
||||
style="transition: opacity 0.15s ease-in-out"
|
||||
:style="
|
||||
controls && !seeking
|
||||
|
@ -248,7 +253,7 @@
|
|||
<v-spacer />
|
||||
<!-- // TODO: merge the bottom 2 into 1 reusable component -->
|
||||
<quality
|
||||
v-if="$refs.player"
|
||||
v-if="$refs.player && $refs.player.currentSrc"
|
||||
:sources="sources"
|
||||
:current-source="$refs.player"
|
||||
@quality="qualityHandler($event)"
|
||||
|
@ -309,6 +314,22 @@
|
|||
($refs.player.currentTime = $event), ($refs.audio.currentTime = $event)
|
||||
"
|
||||
/>
|
||||
|
||||
<v-progress-circular
|
||||
v-if="$store.state.player.preload && buffered < 100"
|
||||
style="
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
"
|
||||
:value="buffered"
|
||||
color="primary"
|
||||
:rotate="-90"
|
||||
:size="64"
|
||||
>
|
||||
<b>{{ buffered }}%</b>
|
||||
</v-progress-circular>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -381,7 +402,7 @@ export default {
|
|||
let vid = this.$refs.player;
|
||||
|
||||
// TODO: this.$store.state.player.quality, check if exists and select the closest one
|
||||
if (this.$store.state.player.prebuffer) this.prebuffer(this.sources[0].url);
|
||||
if (this.$store.state.player.preload) this.prebuffer(this.sources[0].url);
|
||||
else {
|
||||
this.audSrc = this.sources[this.sources.length - 1].url;
|
||||
this.vidSrc = this.sources[0].url;
|
||||
|
@ -439,26 +460,29 @@ export default {
|
|||
);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.xhr.abort();
|
||||
if (this.isFullscreen) this.exitFullscreen();
|
||||
screen.orientation.removeEventListener("change");
|
||||
},
|
||||
methods: {
|
||||
prebuffer(url) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", url, true);
|
||||
xhr.responseType = "blob";
|
||||
this.xhr = new XMLHttpRequest();
|
||||
this.xhr.open("GET", url, true);
|
||||
this.xhr.responseType = "blob";
|
||||
|
||||
xhr.addEventListener(
|
||||
this.xhr.addEventListener(
|
||||
"load",
|
||||
() => {
|
||||
if (xhr.status === 200) {
|
||||
var blob = xhr.response;
|
||||
if (this.xhr.status === 200) {
|
||||
var blob = this.xhr.response;
|
||||
console.error(this.xhr);
|
||||
this.blobToDataURL(blob, (dataurl) => {
|
||||
console.log(dataurl);
|
||||
this.vidSrc = dataurl;
|
||||
this.buffered = 100;
|
||||
});
|
||||
} else {
|
||||
console.error("errorred pre-fetch", xhr.status);
|
||||
console.error("errorred pre-fetch", this.xhr.status);
|
||||
}
|
||||
},
|
||||
false
|
||||
|
@ -466,17 +490,18 @@ export default {
|
|||
|
||||
var prev_pc = 0;
|
||||
// TODO: big progress overlay (##%) to replace controls while loading if pre-buffering is enabled
|
||||
xhr.addEventListener("progress", (event) => {
|
||||
this.xhr.addEventListener("progress", (event) => {
|
||||
if (event.lengthComputable) {
|
||||
var pc = Math.round((event.loaded / event.total) * 100);
|
||||
if (pc != prev_pc) {
|
||||
prev_pc = pc; // ##%
|
||||
console.log("buffering progress", pc);
|
||||
if (pc < 100) this.buffered = pc;
|
||||
console.warn(this.xhr);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
xhr.send();
|
||||
this.xhr.send();
|
||||
},
|
||||
blobToDataURL(blob, callback) {
|
||||
var a = new FileReader();
|
||||
|
|
|
@ -6,63 +6,92 @@
|
|||
<!-- // TODO: quality auto-adjustment settings -->
|
||||
<!-- // TODO: Data saver -->
|
||||
<!-- // TODO: Player UI -->
|
||||
<!-- <v-divider v-if="!$store.state.tweaks.roundTweak" />
|
||||
|
||||
<v-divider v-if="!$store.state.tweaks.roundTweak" />
|
||||
|
||||
<h3 class="ml-8 mt-8">
|
||||
<v-icon class="mb-1 mr-1">mdi-play-speed</v-icon>
|
||||
Preload
|
||||
Preload (UNSTABLE)
|
||||
</h3>
|
||||
|
||||
<v-card
|
||||
flat
|
||||
class="mx-4 my-2 pa-4 d-flex flex-row justify-between background"
|
||||
:class="
|
||||
$store.state.tweaks.roundTweak > 0
|
||||
? $vuetify.theme.dark
|
||||
? 'lighten-1'
|
||||
: 'darken-1'
|
||||
: ''
|
||||
"
|
||||
class="mx-4 mt-2 mb-8 background"
|
||||
:style="{
|
||||
borderRadius: `${$store.state.tweaks.roundTweak / 2}rem`,
|
||||
border: preload
|
||||
? `2.1px solid var(--v-primary-base) !important`
|
||||
: '2.1px solid var(--v-background-base)',
|
||||
borderRadius: `${$store.state.tweaks.roundTweak / 1.9}rem`,
|
||||
}"
|
||||
@click="(preload = !preload), $vuetube.haptics.hapticsImpactLight(1)"
|
||||
>
|
||||
<div>
|
||||
Pre-buffer video data before playback to avoid buffering pauses.
|
||||
<b class="red--text">(can be data intensive it high quality presets)</b>
|
||||
<br />
|
||||
<br />
|
||||
<hr class="primary mr-6" style="opacity: 0.25" />
|
||||
<span class="overline">Buffering threshold: 15%</span>
|
||||
</div>
|
||||
<v-spacer />
|
||||
<v-switch
|
||||
v-model="preload"
|
||||
style="pointer-events: none"
|
||||
class="mt-0"
|
||||
inset
|
||||
/>
|
||||
<br />
|
||||
<v-card
|
||||
flat
|
||||
class="pa-4 d-flex flex-row background"
|
||||
:class="
|
||||
$store.state.tweaks.roundTweak > 0
|
||||
? $vuetify.theme.dark
|
||||
? 'lighten-1'
|
||||
: 'darken-1'
|
||||
: ''
|
||||
"
|
||||
:style="{
|
||||
borderRadius: `${$store.state.tweaks.roundTweak / 2}rem`,
|
||||
}"
|
||||
@click="(preload = !preload), $vuetube.haptics.hapticsImpactLight(1)"
|
||||
>
|
||||
<div class="pr-4">
|
||||
<div style="font-size: 0.75rem">
|
||||
Pre-buffer video data before playback to avoid buffering pauses.
|
||||
<b class="primary--text">
|
||||
(can be data intensive at high quality presets)
|
||||
</b>
|
||||
</div>
|
||||
<div
|
||||
:class="preload ? 'primary' : 'background'"
|
||||
class="my-3 mr-6 rounded-right"
|
||||
style="width: 100%; height: 2px; margin-left: -1.1rem"
|
||||
/>
|
||||
<div>Buffering Threshold · {{ preloadUpTo }}%</div>
|
||||
<div
|
||||
class="background--text"
|
||||
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
|
||||
style="font-size: 0.75rem"
|
||||
>
|
||||
The video will start playing after this much of the video is loaded.
|
||||
<b class="red--text">(doesn't work yet)</b>
|
||||
</div>
|
||||
</div>
|
||||
<v-switch
|
||||
v-model="preload"
|
||||
style="pointer-events: none"
|
||||
class="mt-0"
|
||||
inset
|
||||
/>
|
||||
</v-card>
|
||||
<v-slider
|
||||
v-model="speed"
|
||||
step=".25"
|
||||
thumb-size="64"
|
||||
style="transition-duration: 0.3s; transition-property: all"
|
||||
:rules="[(s) => s <= 4 || 'Might cause issues with buffering.']"
|
||||
:min="0.25"
|
||||
:max="16"
|
||||
v-show="preload"
|
||||
v-model="preloadUpTo"
|
||||
:min="1"
|
||||
:max="100"
|
||||
thumb-label
|
||||
persistent-hint
|
||||
height="20"
|
||||
:hint="preloadUpTo <= 10 || 'This can take a very long time.'"
|
||||
class="pt-4 px-0 pb-1"
|
||||
track-color="background"
|
||||
thumb-color="primary background--text"
|
||||
style="z-index: 69420; position: absolute; bottom: -1.83rem"
|
||||
:style="{
|
||||
borderRadius: `${$store.state.tweaks.roundTweak / 4}rem`,
|
||||
width: `calc(100% - 2rem - ${$store.state.tweaks.roundTweak}rem)`,
|
||||
left: `${$store.state.tweaks.roundTweak / 2 + 1}rem`,
|
||||
}"
|
||||
@input="$vuetube.haptics.hapticsImpactLight(0)"
|
||||
>
|
||||
<template #thumb-label="{ value }">
|
||||
<b class="background--text" style="font-size: 1.15rem">
|
||||
{{ value.toFixed(2) }}x
|
||||
</b>
|
||||
</template>
|
||||
</v-slider>
|
||||
</v-card> -->
|
||||
</v-card>
|
||||
|
||||
<v-divider v-if="!$store.state.tweaks.roundTweak" />
|
||||
<v-divider v-if="!$store.state.tweaks.roundTweak && !preload" />
|
||||
|
||||
<h3 class="ml-8 mt-8">
|
||||
<v-icon class="mb-1 mr-1">mdi-speedometer</v-icon>
|
||||
|
@ -79,7 +108,7 @@
|
|||
>
|
||||
<v-card
|
||||
flat
|
||||
class="mb-1 pa-4 d-flex flex-row justify-between background"
|
||||
class="mb-1 pa-4 d-flex flex-row background"
|
||||
:class="
|
||||
$store.state.tweaks.roundTweak > 0
|
||||
? $vuetify.theme.dark
|
||||
|
@ -114,16 +143,9 @@
|
|||
inset
|
||||
/>
|
||||
</v-card>
|
||||
<v-card flat class="d-flex flex-row justify-between background">
|
||||
<v-card flat class="d-flex flex-row background">
|
||||
<speed
|
||||
class="background mr-1 px-4 d-flex justify-center align-center"
|
||||
style="
|
||||
font-size: 1.5rem !important;
|
||||
font-weight: bold !important;
|
||||
color: black !important;
|
||||
background: red;
|
||||
text-shadow: 0 0 2rem green;
|
||||
"
|
||||
:current-speed="speed"
|
||||
:class="
|
||||
$store.state.tweaks.roundTweak > 0
|
||||
|
@ -142,7 +164,6 @@
|
|||
step=".25"
|
||||
thumb-size="64"
|
||||
class="pa-0 pt-5 pl-6 pb-2 ma-0 background"
|
||||
style="transition-duration: 0.3s; transition-property: all"
|
||||
:rules="[(s) => s <= 4 || 'Might cause issues with buffering.']"
|
||||
:min="0.25"
|
||||
:max="16"
|
||||
|
@ -176,7 +197,18 @@ export default {
|
|||
components: {
|
||||
speed,
|
||||
},
|
||||
data: function () {
|
||||
return this.initializeState();
|
||||
},
|
||||
computed: {
|
||||
loop: {
|
||||
get() {
|
||||
return this.$store.state.player.loop;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit("player/setLoop", value);
|
||||
},
|
||||
},
|
||||
speed: {
|
||||
get() {
|
||||
return this.$store.state.player.speed;
|
||||
|
@ -201,6 +233,49 @@ export default {
|
|||
this.$store.commit("player/setPreload", value);
|
||||
},
|
||||
},
|
||||
preloadUpTo: {
|
||||
get() {
|
||||
return this.$store.state.player.preloadUpTo;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit("player/setPreloadUpTo", value);
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
initializeState() {
|
||||
return {
|
||||
toggles: [
|
||||
{
|
||||
value: false,
|
||||
name: "Captions",
|
||||
icon: "mdi-closed-caption",
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
name: "Autoskip",
|
||||
icon: "mdi-skip-next",
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
action: () => {},
|
||||
value: false,
|
||||
name: "Mute",
|
||||
icon: "mdi-volume-off",
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
action: () => {
|
||||
this.loop = !this.loop;
|
||||
},
|
||||
value: this.loop,
|
||||
name: "Loop",
|
||||
icon: "mdi-sync-circle",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
<v-divider v-if="!$store.state.tweaks.roundTweak" />
|
||||
<v-card
|
||||
flat
|
||||
class="d-flex flex-row justify-between mx-4 mb-4 pa-4 background"
|
||||
class="d-flex flex-row mx-4 mb-4 pa-4 background"
|
||||
:class="
|
||||
$store.state.tweaks.roundTweak > 0
|
||||
? $vuetify.theme.dark
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<!-- // TODO: Top and Bottom bar color selection -->
|
||||
<v-card
|
||||
flat
|
||||
class="mx-4 my-2 px-4 py-2 d-flex flex-row justify-between background"
|
||||
class="mx-4 my-2 px-4 py-2 d-flex flex-row background"
|
||||
style="transition-duration: 0.3s; transition-property: border-radius"
|
||||
:class="
|
||||
roundTweak > 0 ? ($vuetify.theme.dark ? 'lighten-1' : 'darken-1') : ''
|
||||
|
@ -35,7 +35,7 @@
|
|||
|
||||
<v-card
|
||||
flat
|
||||
class="mx-4 my-2 px-4 py-2 d-flex flex-row justify-between background"
|
||||
class="mx-4 my-2 px-4 py-2 d-flex flex-row background"
|
||||
style="transition-duration: 0.3s; transition-property: border-radius"
|
||||
:class="
|
||||
roundTweak > 0 ? ($vuetify.theme.dark ? 'lighten-1' : 'darken-1') : ''
|
||||
|
@ -79,7 +79,7 @@
|
|||
<!-- margin: $store.state.tweaks.roundTweak > 0 ? '0 1rem' : '0', -->
|
||||
<v-card
|
||||
flat
|
||||
class="mb-1 px-4 py-2 d-flex flex-row justify-between background"
|
||||
class="mb-1 px-4 py-2 d-flex flex-row background"
|
||||
:class="
|
||||
roundTweak > 0 ? ($vuetify.theme.dark ? 'lighten-1' : 'darken-1') : ''
|
||||
"
|
||||
|
@ -107,7 +107,7 @@
|
|||
</v-card>
|
||||
<v-card
|
||||
flat
|
||||
class="mb-1 px-4 py-2 d-flex flex-row justify-between background"
|
||||
class="mb-1 px-4 py-2 d-flex flex-row background"
|
||||
:class="
|
||||
roundTweak > 0 ? ($vuetify.theme.dark ? 'lighten-1' : 'darken-1') : ''
|
||||
"
|
||||
|
@ -151,7 +151,7 @@
|
|||
<template #thumb-label="{ value }">
|
||||
<div
|
||||
class="pa-4 background"
|
||||
:style="{ borderRadius: value * 3 + 'px !important' }"
|
||||
:style="{ borderRadius: value * 3.5 + 'px !important' }"
|
||||
></div>
|
||||
</template>
|
||||
</v-slider>
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<v-icon v-else class="ml-4">mdi-chevron-down</v-icon>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex justify-space-around"
|
||||
class="d-flex justify-space-between"
|
||||
:class="
|
||||
$store.state.tweaks.roundWatch && $store.state.tweaks.roundTweak > 0
|
||||
? $vuetify.theme.dark
|
||||
|
|
|
@ -3,6 +3,7 @@ export const state = () => ({
|
|||
speed: 1,
|
||||
speedAutosave: null,
|
||||
preload: null,
|
||||
preloadUpTo: 100,
|
||||
// quality: null,
|
||||
// qualityAutoSwitch: null,
|
||||
// shortFullscreen: null,
|
||||
|
@ -20,6 +21,8 @@ export const mutations = {
|
|||
(JSON.parse(localStorage.getItem("speedAutosave")) === false)
|
||||
);
|
||||
state.preload = JSON.parse(localStorage.getItem("preload")) === true; // defaults to false
|
||||
state.preloadUpTo =
|
||||
JSON.parse(localStorage.getItem("preloadUpTo")) || 100; // defaults to 100(percent)
|
||||
}
|
||||
},
|
||||
setLoop(state, payload) {
|
||||
|
@ -38,4 +41,8 @@ export const mutations = {
|
|||
state.preload = payload;
|
||||
localStorage.setItem("preload", payload);
|
||||
},
|
||||
setPreloadUpTo(state, payload) {
|
||||
state.preloadUpTo = payload;
|
||||
localStorage.setItem("preloadUpTo", payload);
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue