fix player errors related to intervals / event handlers

This commit is contained in:
Ethan Matzdorf 2022-10-06 22:12:06 -04:00
parent aa32273f3d
commit d2766f3af0
3 changed files with 104 additions and 119 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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 ---//