From c443c57061154cff2a5c37a3c7aefd3eb978518d Mon Sep 17 00:00:00 2001 From: HxxxxxS <16c52527@opayq.com> Date: Mon, 6 May 2024 02:11:03 +0200 Subject: [PATCH] Initial commit --- index.html | 25 ++++++++ index.js | 31 +++++++++ package.json | 17 +++++ script.js | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++ styles.css | 12 ++++ 5 files changed, 263 insertions(+) create mode 100644 index.html create mode 100644 index.js create mode 100644 package.json create mode 100644 script.js create mode 100644 styles.css diff --git a/index.html b/index.html new file mode 100644 index 0000000..da03713 --- /dev/null +++ b/index.html @@ -0,0 +1,25 @@ + + + + + VFX2 + + + +
+
+
+ +
+
+ + + +
+ +
+
+ + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..661a66d --- /dev/null +++ b/index.js @@ -0,0 +1,31 @@ +const express = require('express'); +const app = express(); +const path = require('path'); + +const port = 8000 + +const videoFiles = [ + { "src": "assets/Blender Physics Simulations-8TGNRJDZX_o_compressed.webm"}, + { "src": "assets/Death Grips - Birds-XX5wk-6Mn5s_compressed.webm"}, + { "src": "assets/Jon Hopkins - 'Open Eye Signal' (Official Music Video)-Q04ILDXe3QE_compressed.webm"}, + { "src": "assets/Best Scene From Hackers The Movie-IyWv6snuZLk_compressed.webm"}, + { "src": "assets/$UICIDEBOY$ - O PANA!-VSXg2swBmrY_compressed.webm"}, + { "src": "assets/3D Fractals (Render Test 1)-xQ6nJYanKCY_compressed.webm"}, + { "src": "assets/Beyond The Minds Eye-wKxH51vPtHk -4_compressed.webm"}, + { "src": "assets/A Scene From Troll 2-HyophYBP_w4_compressed.webm"} + // Add more video files as needed +]; + +app.use(express.static(path.join(__dirname))); + +app.get('/', (req, res) => { + res.sendFile(path.join(__dirname, 'index.html')); +}); + +app.get('/api/videos', (req, res) => { + res.json(videoFiles); +}); + +app.listen(port, () => { + console.log('Server started on port', port); +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..39d583c --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "vfx2", + "version": "1.0.0", + "description": "", + "main": "script.js", + "scripts": { + "dev": "node index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.18.2", + "http-server": "^14.1.1" + } +} diff --git a/script.js b/script.js new file mode 100644 index 0000000..73f1f8b --- /dev/null +++ b/script.js @@ -0,0 +1,178 @@ +// Define a debug mode variable +let debugMode = true; + +const canvas = document.getElementById("videoCanvas"); +const ctx = canvas.getContext("2d"); + +const videos = [createVideoElement(), createVideoElement()]; +let videosLoaded = 0; +let aspectRatio = 1; + +window.addEventListener("DOMContentLoaded", () => { + let previousVideo + videos.forEach((video) => { + previousVideo = selectRandomVideo(previousVideo || video) + }); +}) + +videos.forEach((video) => { + video.addEventListener("loadedmetadata", handleVideoLoaded); + video.addEventListener("ended", handleVideoEnded); +}); + +function createVideoElement() { + const video = document.createElement("video"); + video.autoplay = true; + video.muted = true; + return video; +} + +function handleVideoLoaded() { + videosLoaded++; + if (videosLoaded === videos.length) { + updateCanvasSize(); + drawVideos(); + } +} + +function handleVideoEnded(event) { + const video = event.target; + selectRandomVideo(video); +} + +// Function to extract filename from full path and unescape it +function extractFilename(src) { + // Split the path by '/' + const parts = src.split('/'); + // Get the last part of the path (filename) + const filename = parts[parts.length - 1]; + // Unescape the filename and replace '%20' with whitespace + return decodeURIComponent(filename.replace(/\%20/g, ' ')); +} + +// Function to draw debug text on the canvas +function drawDebugText() { + // Set font style and color + ctx.font = "16px Arial"; + ctx.fillStyle = "white"; + + let corners = [[0,0],[1,1],[0,1],[1,0]]; + let padding = 20; + + videos.forEach((video,i) => { + //console.log("Drawing debug text for video",i,video); + + let corner = corners[i]; + let positionX = corner[0] === 0 ? padding : canvas.width - padding; + let positionY = corner[1] === 0 ? padding : canvas.height - padding; + + // Adjust position for bottom right corner to stay within canvas bounds + if (corner[0] === 1 && positionY + 40 > canvas.height) { + positionY = canvas.height - 40; + } + + // Set text alignment based on corner + ctx.textAlign = corner[0] === 0 ? "left" : "right"; + ctx.textBaseline = corner[1] === 0 ? "top" : "bottom"; + + // Draw debug text for the video + ctx.fillText(getFilename(video.src), positionX, positionY); + ctx.fillText("Dimensions: " + video.videoWidth + "x" + video.videoHeight, positionX, positionY + 20); + ctx.fillText(formatTime(video.currentTime) + "/" + formatTime(video.duration), positionX, positionY + 40); + // Add more debug information as needed + }); +} + + + +// Function to extract filename from full path +function getFilename(src) { + const parts = src.split('/'); + return decodeURIComponent(parts[parts.length - 1].replace(/\%20/g, ' ')); +} + + +// Helper function to format time in HH:MM:SS format +function formatTime(seconds) { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const remainingSeconds = Math.floor(seconds % 60); + return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`; +} + +// Modify the drawVideos function to include debug text drawing +function drawVideos() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + + // Resize the canvas to accommodate both videos side by side + canvas.width = Math.max(videos[0].videoWidth, videos[1].videoWidth); + canvas.height = Math.max(videos[0].videoHeight, videos[1].videoHeight); + + // Calculate positions for each video + const video1X = (canvas.width - videos[0].videoWidth) / 2; + const video1Y = (canvas.height - videos[0].videoHeight) / 2; + const video2X = (canvas.width - videos[1].videoWidth) / 2; + const video2Y = (canvas.height - videos[1].videoHeight) / 2; + + // Draw video 1 + ctx.drawImage(videos[0], video1X, video1Y, videos[0].videoWidth, videos[0].videoHeight); + + // Set composite operation to overlay + ctx.globalCompositeOperation = "overlay"; + + // Draw video 2 + ctx.drawImage(videos[1], video2X, video2Y, videos[1].videoWidth, videos[1].videoHeight); + + // Reset composite operation + ctx.globalCompositeOperation = "source-over"; + + // Draw debug text if debug mode is enabled + if (debugMode) { + drawDebugText(); + } + // Request next frame + requestAnimationFrame(drawVideos); +} + + +function updateCanvasSize() { + aspectRatio = Math.max( + videos[0].videoWidth / videos[0].videoHeight, + videos[1].videoWidth / videos[1].videoHeight + ); + + canvas.width = window.innerWidth; + canvas.height = window.innerWidth / aspectRatio; +} + +window.addEventListener("resize", updateCanvasSize); + +updateCanvasSize() + +function selectRandomVideo(videoElement) { + console.log("selectRandomVideo",videoElement) + fetch("/api/videos") + .then((response) => response.json()) + .then((videoFiles) => { + const otherVideo = videos.find((video) => video !== videoElement); + + let randomVideo; + do { + const randomIndex = Math.floor(Math.random() * videoFiles.length); + randomVideo = videoFiles[randomIndex]; + } while (randomVideo === otherVideo); + + videoElement.src = randomVideo.src; + videoElement.play(); + return videoElement + }); +} + +document.addEventListener('keydown', function(event) { + // Check if the pressed key is the one you want to bind + if (event.key === 'Enter') { // Change 'Enter' to the desired key + debugMode = !debugMode + console.log("debugMode:",debugMode) + } +}); \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..03474bb --- /dev/null +++ b/styles.css @@ -0,0 +1,12 @@ +body, html { + background: black; + height: 100%; + margin: 0; + padding: 0; +} + +#videoCanvas { + position: absolute; + width: 100%; + height: 100%; +}