mirror of https://github.com/VueTubeApp/VueTube
fix player errors related to intervals / event handlers
This commit is contained in:
parent
aa32273f3d
commit
d2766f3af0
|
@ -202,12 +202,7 @@
|
||||||
:video="$refs.player"
|
:video="$refs.player"
|
||||||
:buffering="bufferingDetected"
|
:buffering="bufferingDetected"
|
||||||
@play="$refs.player.play(), $refs.audio.play()"
|
@play="$refs.player.play(), $refs.audio.play()"
|
||||||
@pause="
|
@pause="pauseHandler"
|
||||||
$refs.player.pause(),
|
|
||||||
$refs.audio.pause(),
|
|
||||||
clearTimeout(bufferingDetected),
|
|
||||||
(bufferingDetected = false)
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
<v-btn
|
<v-btn
|
||||||
v-if="!verticalFullscreen"
|
v-if="!verticalFullscreen"
|
||||||
|
@ -331,8 +326,8 @@
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
"
|
"
|
||||||
:value="buffered"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
|
:value="buffered"
|
||||||
:rotate="-90"
|
:rotate="-90"
|
||||||
:size="64"
|
:size="64"
|
||||||
>
|
>
|
||||||
|
@ -385,6 +380,9 @@ export default {
|
||||||
},
|
},
|
||||||
recommends: {
|
recommends: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -407,12 +405,13 @@ export default {
|
||||||
isVerticalVideo: false, // maybe rename(refactor everywhere used) to isShort
|
isVerticalVideo: false, // maybe rename(refactor everywhere used) to isShort
|
||||||
bufferingDetected: false,
|
bufferingDetected: false,
|
||||||
isMusic: false,
|
isMusic: false,
|
||||||
|
vid: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
console.log("sources", this.sources);
|
console.log("sources", this.sources);
|
||||||
console.log("recommends", this.recommends);
|
console.log("recommends", this.recommends);
|
||||||
let vid = this.$refs.player;
|
this.vid = this.$refs.player;
|
||||||
|
|
||||||
// TODO: this.$store.state.player.quality, check if exists and select the closest one
|
// TODO: this.$store.state.player.quality, check if exists and select the closest one
|
||||||
if (this.$store.state.player.preload) this.prebuffer(this.sources[5].url);
|
if (this.$store.state.player.preload) this.prebuffer(this.sources[5].url);
|
||||||
|
@ -437,7 +436,18 @@ export default {
|
||||||
|
|
||||||
// TODO: detect this.isMusic from the video or channel metadata instead of just SB segments
|
// TODO: detect this.isMusic from the video or channel metadata instead of just SB segments
|
||||||
|
|
||||||
this.$refs.player.addEventListener("loadeddata", (e) => {
|
this.$refs.player.addEventListener("loadeddata", this.loadedDataEvent);
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
screen.orientation.addEventListener("change", () =>
|
||||||
|
this.fullscreenHandler(false)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.cleanup();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
loadedDataEvent() {
|
||||||
// console.log(e);
|
// console.log(e);
|
||||||
// if (vid.networkState === vid.NETWORK_LOADING) {
|
// if (vid.networkState === vid.NETWORK_LOADING) {
|
||||||
// // The user agent is actively trying to download data.
|
// // The user agent is actively trying to download data.
|
||||||
|
@ -446,10 +456,10 @@ export default {
|
||||||
// if (vid.readyState < vid.HAVE_FUTURE_DATA) {
|
// if (vid.readyState < vid.HAVE_FUTURE_DATA) {
|
||||||
// // There is not enough data to keep playing from this point
|
// // There is not enough data to keep playing from this point
|
||||||
// }
|
// }
|
||||||
if (vid.readyState >= 3) {
|
if (this.vid.readyState >= 3) {
|
||||||
this.$refs.audio.play();
|
this.$refs.audio.play();
|
||||||
this.bufferingDetected = false;
|
this.bufferingDetected = false;
|
||||||
this.$refs.audio.currentTime = vid.currentTime;
|
this.$refs.audio.currentTime = this.vid.currentTime;
|
||||||
|
|
||||||
if (!this.isMusic) {
|
if (!this.isMusic) {
|
||||||
this.$refs.audio.playbackRate = this.$store.state.player.speed;
|
this.$refs.audio.playbackRate = this.$store.state.player.speed;
|
||||||
|
@ -461,81 +471,71 @@ export default {
|
||||||
|
|
||||||
this.$refs.player.loop = this.$store.state.player.loop;
|
this.$refs.player.loop = this.$store.state.player.loop;
|
||||||
this.$refs.audio.loop = this.$store.state.player.loop;
|
this.$refs.audio.loop = this.$store.state.player.loop;
|
||||||
this.$refs.player.addEventListener("timeupdate", () => {
|
this.$refs.player.addEventListener("timeupdate", this.timeUpdateEvent);
|
||||||
if (!this.seeking) this.progress = vid.currentTime; // for seekbar
|
|
||||||
|
|
||||||
// console.log("sb check", this.blocks);
|
|
||||||
// iterate over data.segments array
|
|
||||||
// for sponsorblock
|
|
||||||
if (this.blocks.length > 0)
|
|
||||||
this.blocks.forEach((sponsor) => {
|
|
||||||
let vidTime = vid.currentTime;
|
|
||||||
|
|
||||||
if (
|
|
||||||
vidTime >= sponsor.segment[0] &&
|
|
||||||
vidTime <= sponsor.segment[1]
|
|
||||||
) {
|
|
||||||
console.log("Skipping the sponsor");
|
|
||||||
this.$youtube.showToast("Skipped sponsor");
|
|
||||||
this.$refs.player.currentTime = sponsor.segment[1] + 1;
|
|
||||||
this.$refs.audio.currentTime = this.$refs.player.currentTime;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// TODO: handle video ending with a "replay" button instead of <playpause /> if not on loop
|
// TODO: handle video ending with a "replay" button instead of <playpause /> if not on loop
|
||||||
// TODO: split buffering into multiple sections as it should be for back/forth scrubbing
|
// TODO: split buffering into multiple sections as it should be for back/forth scrubbing
|
||||||
this.$refs.player.addEventListener("progress", () => {
|
this.$refs.player.addEventListener("progress", this.progressEvent);
|
||||||
if (this.bufferingDetected) {
|
this.$refs.player.addEventListener("waiting", this.waitingEvent);
|
||||||
this.$refs.audio.currentTime = vid.currentTime;
|
this.$refs.player.addEventListener("playing", this.playingEvent);
|
||||||
clearTimeout(this.bufferingDetected);
|
|
||||||
this.bufferingDetected = false;
|
|
||||||
}
|
|
||||||
if (this.$refs.audio.paused && !this.$refs.player.paused) this.$refs.audio.play();
|
|
||||||
this.buffered = (vid.buffered.end(0) / vid.duration) * 100;
|
|
||||||
});
|
|
||||||
|
|
||||||
// buffering detection & sync
|
|
||||||
let threshold = 250; //ms after which user perceives buffering
|
|
||||||
|
|
||||||
this.$refs.player.addEventListener("waiting", () => {
|
|
||||||
if (!this.$refs.player.paused) {
|
|
||||||
this.bufferingDetected = setTimeout(() => {
|
|
||||||
this.bufferingDetected = true;
|
|
||||||
this.$refs.audio.pause();
|
|
||||||
//show buffering
|
|
||||||
}, threshold);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.$refs.player.addEventListener("playing", () => {
|
|
||||||
if (this.bufferingDetected != false) {
|
|
||||||
clearTimeout(this.bufferingDetected);
|
|
||||||
this.$refs.audio.currentTime = vid.currentTime;
|
|
||||||
this.bufferingDetected = false;
|
|
||||||
this.$refs.audio.play();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
},
|
timeUpdateEvent() {
|
||||||
created() {
|
if (!this.seeking) this.progress = this.vid.currentTime; // for seekbar
|
||||||
screen.orientation.addEventListener("change", () =>
|
|
||||||
this.fullscreenHandler(false)
|
// console.log("sb check", this.blocks);
|
||||||
);
|
// iterate over data.segments array
|
||||||
},
|
// for sponsorblock
|
||||||
beforeDestroy() {
|
if (this.blocks.length > 0)
|
||||||
this.cleanup();
|
this.blocks.forEach((sponsor) => {
|
||||||
},
|
let vidTime = this.vid.currentTime;
|
||||||
methods: {
|
|
||||||
|
if (vidTime >= sponsor.segment[0] && vidTime <= sponsor.segment[1]) {
|
||||||
|
console.log("Skipping the sponsor");
|
||||||
|
this.$youtube.showToast("Skipped sponsor");
|
||||||
|
this.$refs.player.currentTime = sponsor.segment[1] + 1;
|
||||||
|
this.$refs.audio.currentTime = this.$refs.player.currentTime;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
progressEvent() {
|
||||||
|
if (this.bufferingDetected) {
|
||||||
|
this.$refs.audio.currentTime = this.vid.currentTime;
|
||||||
|
clearTimeout(this.bufferingDetected);
|
||||||
|
this.bufferingDetected = false;
|
||||||
|
}
|
||||||
|
if (this.$refs.audio.paused && !this.$refs.player.paused)
|
||||||
|
this.$refs.audio.play();
|
||||||
|
this.buffered = (this.vid.buffered.end(0) / this.vid.duration) * 100;
|
||||||
|
},
|
||||||
|
waitingEvent() {
|
||||||
|
// buffering detection & sync
|
||||||
|
let threshold = 250; //ms after which user perceives buffering
|
||||||
|
if (!this.$refs.player.paused) {
|
||||||
|
this.bufferingDetected = setTimeout(() => {
|
||||||
|
this.bufferingDetected = true;
|
||||||
|
this.$refs.audio.pause();
|
||||||
|
//show buffering
|
||||||
|
}, threshold);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
playingEvent() {
|
||||||
|
if (this.bufferingDetected != false) {
|
||||||
|
clearTimeout(this.bufferingDetected);
|
||||||
|
this.$refs.audio.currentTime = this.vid.currentTime;
|
||||||
|
this.bufferingDetected = false;
|
||||||
|
this.$refs.audio.play();
|
||||||
|
}
|
||||||
|
},
|
||||||
cleanup() {
|
cleanup() {
|
||||||
if (this.xhr) this.xhr.abort();
|
if (this.xhr) this.xhr.abort();
|
||||||
if (this.isFullscreen) this.exitFullscreen();
|
if (this.isFullscreen) this.exitFullscreen();
|
||||||
if (this.bufferingDetected) clearTimeout(this.bufferingDetected);
|
if (this.bufferingDetected) clearTimeout(this.bufferingDetected);
|
||||||
screen.orientation.removeEventListener("change");
|
screen.orientation.removeEventListener("change");
|
||||||
//! this.$refs.player.removeEventListener("loadeddata"); // NOTE: needs a function to be passed as the 2nd argument, but breaks if called with vue method as the 2nd argument in mounted()
|
this.$refs.player.removeEventListener("loadeddata", this.loadedDataEvent);
|
||||||
// this.$refs.player.removeEventListener("timeupdate");
|
this.$refs.player.removeEventListener("timeupdate", this.timeUpdateEvent);
|
||||||
this.$refs.player.removeEventListener("progress", () => {});
|
this.$refs.player.removeEventListener("progress", this.progressEvent);
|
||||||
this.$refs.player.removeEventListener("waiting", () => {});
|
this.$refs.player.removeEventListener("waiting", this.waitingEvent);
|
||||||
this.$refs.player.removeEventListener("playing", () => {});
|
this.$refs.player.removeEventListener("playing", this.playingEvent);
|
||||||
},
|
},
|
||||||
prebuffer(url) {
|
prebuffer(url) {
|
||||||
this.xhr = new XMLHttpRequest();
|
this.xhr = new XMLHttpRequest();
|
||||||
|
@ -689,15 +689,26 @@ export default {
|
||||||
this.isFullscreen = true;
|
this.isFullscreen = true;
|
||||||
|
|
||||||
//--- Fix pressing back button in fullscreen exiting the watch page ---//
|
//--- Fix pressing back button in fullscreen exiting the watch page ---//
|
||||||
this.$vuetube.addBackAction(new backType(
|
this.$vuetube.addBackAction(
|
||||||
() => { this.exitFullscreen(true); },
|
new backType(
|
||||||
() => { return this.isFullscreen; }
|
() => {
|
||||||
));
|
this.exitFullscreen(true);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
return this.isFullscreen;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
getPlayer() {
|
getPlayer() {
|
||||||
return this.$refs.player;
|
return this.$refs.player;
|
||||||
},
|
},
|
||||||
|
pauseHandler() {
|
||||||
|
this.$refs.player.pause();
|
||||||
|
this.$refs.audio.pause();
|
||||||
|
clearTimeout(this.bufferingDetected);
|
||||||
|
this.bufferingDetected = false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -21,41 +21,15 @@ export default {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
computed: {
|
||||||
return {
|
humanDuration() {
|
||||||
humanWatchTime: "0:00",
|
if (this.duration) return this.$vuetube.humanTime(this.duration);
|
||||||
humanDuration: "0:00",
|
return "0:00";
|
||||||
|
},
|
||||||
runWatchTimeUpdates: null
|
humanWatchTime() {
|
||||||
}
|
if (this.currentTime) return this.$vuetube.humanTime(this.currentTime);
|
||||||
|
return "0:00";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
//--- Only show end duration when 'this.duration' becomes defined ---//
|
|
||||||
const durationTimer = setInterval(() => {
|
|
||||||
if (this.duration) {
|
|
||||||
this.humanDuration = this.$vuetube.humanTime(this.duration);
|
|
||||||
return clearInterval(durationTimer);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
//--- END Only show end duration when 'this.duration' becomes defined ---//
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
updateWatchTime() {
|
|
||||||
this.humanWatchTime = this.$vuetube.humanTime(this.currentTime);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
controls(newVal) {
|
|
||||||
if (newVal) { // controls are VISIBLE
|
|
||||||
this.updateWatchTime(); // Call to immediately update
|
|
||||||
this.runWatchTimeUpdates = setInterval(this.updateWatchTime, 500);
|
|
||||||
} else { // Controls are INVISIBLE
|
|
||||||
clearInterval(this.runWatchTimeUpdates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -138,7 +138,7 @@ const module = {
|
||||||
}
|
}
|
||||||
// join the array into a string with : as a sepatrator
|
// join the array into a string with : as a sepatrator
|
||||||
let returntext = levels.join(":");
|
let returntext = levels.join(":");
|
||||||
console.log(returntext);
|
// console.log(returntext);
|
||||||
return returntext;
|
return returntext;
|
||||||
},
|
},
|
||||||
//--- End Convert Time To Human Readable String ---//
|
//--- End Convert Time To Human Readable String ---//
|
||||||
|
|
Loading…
Reference in New Issue