diff --git a/NUXT/components/Player/index.vue b/NUXT/components/Player/index.vue index b59fde3..abc230d 100644 --- a/NUXT/components/Player/index.vue +++ b/NUXT/components/Player/index.vue @@ -1,23 +1,193 @@ @@ -33,23 +203,226 @@ export default { props: ["sources"], data() { return { + isFullscreen: false, + scrubbing: false, + controls: false, + percent: 0, + progress: 0, + buffered: 0, + duration: 0, + watched: 0, + total: 0, vidSrc: "", + vidWrs: "", }; }, mounted() { + console.log("sources", this.sources); this.vidSrc = this.sources[this.sources.length - 1].url; + this.vidWrs = this.sources[1].url; + let vid = this.$refs.player; + vid.addEventListener("loadeddata", (e) => { + console.log("%c loadeddata", "color: #00ff00"); + console.log(e); + //Video should now be loaded but we can add a second check + if (vid.readyState >= 3) { + vid.ontimeupdate = () => { + console.log("%c timeupdate", "color: #aaaaff"); + this.duration = vid.duration; + if (!this.scrubbing) this.progress = vid.currentTime; + this.percent = (vid.currentTime / vid.duration) * 100; + this.watched = this.$vuetube.humanTime(vid.currentTime); + this.total = this.$vuetube.humanTime(vid.duration); + }; + vid.onprogress = () => { + console.log("%c progress", "color: #ff00ff"); + this.buffered = (vid.buffered.end(0) / vid.duration) * 100; + }; + } + }); }, methods: { - handleFullscreenChange() { - if (document.fullscreenElement === this.$refs.player) { - this.$vuetube.statusBar.hide(); - this.$vuetube.navigationBar.hide(); + loadVideoFrames() { + // Exit loop if desired number of frames have been extracted + if (this.frames.length >= frameCount) { + this.visibleFrame = 0; + + // Append all canvases to container div + this.frames.forEach((frame) => { + this.frameContainerElement.appendChild(frame); + }); + return; + } + + // If extraction hasn’t started, set desired time for first frame + if (this.frames.length === 0) { + this.requestedTime = 0; } else { + this.requestedTime = this.requestedTime + this.frameTimestep; + } + + // Send seek request to video player for the next frame. + this.videoElement.currentTime = this.requestedTime; + }, + extractFrame(videoWidth, videoHeight) { + // Create DOM canvas object + var canvas = document.createElement("canvas"); + canvas.className = "video-scrubber-frame"; + canvas.height = videoHeight; + canvas.width = videoWidth; + + // Copy current frame to canvas + var context = canvas.getContext("2d"); + context.drawImage(this.videoElement, 0, 0, videoWidth, videoHeight); + this.frames.push(canvas); + + // Load the next frame + loadVideoFrames(); + }, + prefetch_file(url, fetched_callback, progress_callback, error_callback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", url, true); + xhr.responseType = "blob"; + + xhr.addEventListener( + "load", + function () { + if (xhr.status === 200) { + var URL = window.URL || window.webkitURL; + var blob_url = URL.createObjectURL(xhr.response); + fetched_callback(blob_url); + } else { + error_callback(); + } + }, + false + ); + + var prev_pc = 0; + xhr.addEventListener("progress", function (event) { + if (event.lengthComputable) { + var pc = Math.round((event.loaded / event.total) * 100); + if (pc != prev_pc) { + prev_pc = pc; + progress_callback(pc); + } + } + }); + xhr.send(); + }, + async extractFramesFromVideo(videoUrl, fps = 25) { + // fully download it first (no buffering): + console.log(videoUrl); + console.log(fps); + let videoBlob = await fetch(videoUrl, { + headers: { range: "bytes=0-567139" }, + }).then((r) => r.blob()); + console.log(videoBlob); + let videoObjectUrl = URL.createObjectURL(videoBlob); + let video = document.createElement("video"); + + let seekResolve; + video.addEventListener("seeked", async function () { + if (seekResolve) seekResolve(); + }); + + video.src = videoObjectUrl; + + // workaround chromium metadata bug (https://stackoverflow.com/q/38062864/993683) + while ( + (video.duration === Infinity || isNaN(video.duration)) && + video.readyState < 2 + ) { + await new Promise((r) => setTimeout(r, 1000)); + video.currentTime = 10000000 * Math.random(); + } + let duration = video.duration; + + let canvas = document.createElement("canvas"); + let context = canvas.getContext("2d"); + let [w, h] = [video.videoWidth, video.videoHeight]; + canvas.width = w; + canvas.height = h; + + let interval = 1; + let currentTime = 0; + + while (currentTime < duration) { + video.currentTime = currentTime; + await new Promise((r) => (seekResolve = r)); + + context.drawImage(video, 0, 0, w, h); + let base64ImageData = canvas.toDataURL(); + console.log(base64ImageData); + this.frames.push(base64ImageData); + + currentTime += interval; + } + console.log("%c frames", "color: #00ff00"); + console.log(this.frames); + }, + seek(e) { + console.log(`scrubbing ${e}`); + let vid = this.$refs.playerfake; + let canvas = this.$refs.preview; + this.$refs.playerfake.currentTime = e; + canvas + .getContext("2d") + .drawImage( + vid, + 0, + 0, + this.$refs.player.clientWidth / 3, + this.$refs.player.clientHeight / 3 + ); + }, + scrub(e) { + this.$refs.player.currentTime = e; + }, + handleFullscreenChange() { + console.log(this.$refs.player); + console.log(document.fullscreenElement); + if (document?.fullscreenElement === this.$refs.vidcontainer) { + // const cancellFullScreen = + // document.exitFullscreen || + // document.mozCancelFullScreen || + // document.webkitExitFullscreen || + // document.msExitFullscreen; + // cancellFullScreen.call(document); + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } + this.isFullscreen = false; this.$vuetube.statusBar.show(); this.$vuetube.navigationBar.show(); + } else { + // const element = document; + // const requestFullScreen = + // element.requestFullscreen || + // element.webkitRequestFullScreen || + // element.mozRequestFullScreen || + // element.msRequestFullScreen; + // requestFullScreen.call(element); + this.$refs.vidcontainer.requestFullscreen({ + requireOrientation: "landscape", + }); + this.isFullscreen = true; + this.$vuetube.statusBar.hide(); + this.$vuetube.navigationBar.hide(); } + // screen.orientation + // .lock("landscape") + // .then(function () { + // console.log("Locked"); + // }) + // .catch(function (error) { + // console.log(error); + // }); }, - getPlayer() { return this.$refs.player; }, diff --git a/NUXT/components/Player/legacy.vue b/NUXT/components/Player/legacy.vue deleted file mode 100644 index 789578e..0000000 --- a/NUXT/components/Player/legacy.vue +++ /dev/null @@ -1,418 +0,0 @@ - - - diff --git a/NUXT/pages/watch.vue b/NUXT/pages/watch.vue index 52cbe14..7a7ed9f 100644 --- a/NUXT/pages/watch.vue +++ b/NUXT/pages/watch.vue @@ -2,18 +2,7 @@
- - - - +