commit 9f91635569cd709710ef9fe605f5fc8462f65b85 Author: Dejvino Date: Sat Nov 8 16:05:55 2025 +0100 Initial commit. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f0ad67f --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Music Video Generator + +After I'm done producing a music track, I still need to create a music video for it. Otherwise, I can't upload it to a video sharing site. + +This is a library of music video "generators", anything that can be recorded along with a music file to produce a music video. Usually, this means a dynamic HTML page with some kind of dynamic visuals. diff --git a/sparkles/img1.png b/sparkles/img1.png new file mode 100644 index 0000000..c66bb21 Binary files /dev/null and b/sparkles/img1.png differ diff --git a/sparkles/img2.png b/sparkles/img2.png new file mode 100644 index 0000000..be799bd Binary files /dev/null and b/sparkles/img2.png differ diff --git a/sparkles/img3.png b/sparkles/img3.png new file mode 100644 index 0000000..9758bc9 Binary files /dev/null and b/sparkles/img3.png differ diff --git a/sparkles/img4.png b/sparkles/img4.png new file mode 100644 index 0000000..e4a3675 Binary files /dev/null and b/sparkles/img4.png differ diff --git a/sparkles/img5.png b/sparkles/img5.png new file mode 100644 index 0000000..e591357 Binary files /dev/null and b/sparkles/img5.png differ diff --git a/sparkles/index.html b/sparkles/index.html new file mode 100644 index 0000000..6ee0ef7 --- /dev/null +++ b/sparkles/index.html @@ -0,0 +1,22 @@ + + + + + + Floating Beat Canvas + + + + + + + + + + \ No newline at end of file diff --git a/sparkles/script.js b/sparkles/script.js new file mode 100644 index 0000000..8454c7a --- /dev/null +++ b/sparkles/script.js @@ -0,0 +1,211 @@ +// --- Setup --- +const canvas = document.getElementById('beatCanvas'); // Ensure this ID matches your HTML +const ctx = canvas.getContext('2d'); + +// --- Configuration --- +const FADE_DURATION = 2000; // 1.5 seconds for fade in/out of background images +const DISPLAY_DURATION = 10000; // 4 seconds of full display time for background images +const TRANSITION_CYCLE = FADE_DURATION + DISPLAY_DURATION; // Total background image cycle length + +const NUM_SPARKLES = 100; // How many sparkles to have on screen +const SPARKLE_SIZE_MIN = 5; // Min radius for a sparkle +const SPARKLE_SIZE_MAX = 20; // Max radius for a sparkle +const SPARKLE_SPEED_MIN = 0.1; // Min speed for sparkle movement +const SPARKLE_SPEED_MAX = 0.5; // Max speed for sparkle movement +const SPARKLE_FADE_SPEED = 0.002; // How quickly sparkles fade in/out per frame (adjust for desired effect) + +// --- Global Pulse Configuration --- +const BEAT_INTERVAL = 500; // 120 BPM = 500ms per beat +let lastBeatTime = 0; +let beatPulse = 0; // 0 to 1, indicates how far into the current beat we are +const PULSE_DECAY = 0.03; // How quickly the pulse effect fades after the beat hits +const PULSE_STRENGTH = 0.3; // Maximum scale increase (e.g., 30% larger) + +let images = []; // Array to hold loaded Image objects for background +let currentImageIndex = 0; +let nextImageIndex = 1; +let cycleStartTime = 0; // Tracks the start time of the current background image display/fade cycle + +let sparkles = []; // Array to hold all sparkle objects + + // --- Sparkle Class (Pulsating) --- + class Sparkle { + constructor() { + this.reset(); + } + + reset() { + this.x = Math.random() * canvas.width; + this.y = Math.random() * canvas.height; + // Store the base radius, which will be scaled in draw() + this.baseRadius = SPARKLE_SIZE_MIN + Math.random() * (SPARKLE_SIZE_MAX - SPARKLE_SIZE_MIN); + this.speedX = (Math.random() - 0.5) * (SPARKLE_SPEED_MAX - SPARKLE_SPEED_MIN) + SPARKLE_SPEED_MIN; + this.speedY = (Math.random() - 0.5) * (SPARKLE_SPEED_MAX - SPARKLE_SPEED_MIN) + SPARKLE_SPEED_MIN; + this.alpha = Math.random(); + this.alphaDirection = Math.random() > 0.5 ? 1 : -1; + this.hue = Math.random() * 360; + } + + update() { + // Movement + this.x += this.speedX; + this.y += this.speedY; + + // Bounce off edges + if (this.x < 0 || this.x > canvas.width) this.speedX *= -1; + if (this.y < 0 || this.y > canvas.height) this.speedY *= -1; + + // Fade in/out + this.alpha += this.alphaDirection * SPARKLE_FADE_SPEED; + if (this.alpha > 1) { + this.alpha = 1; + this.alphaDirection = -1; + } else if (this.alpha < 0) { + this.alpha = 0; + this.alphaDirection = 1; + } + } + + draw() { + // Calculate the current pulsating radius based on global beatPulse + const currentRadius = this.baseRadius * (1 + beatPulse * PULSE_STRENGTH); + + ctx.globalAlpha = this.alpha; + ctx.beginPath(); + ctx.fillStyle = `hsl(${this.hue}, 100%, 75%)`; + ctx.arc(this.x, this.y, currentRadius, 0, Math.PI * 2); + ctx.fill(); + ctx.globalAlpha = 1; + } + } + + +function resizeCanvas() { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + // When canvas resizes, re-initialize sparkles to match new dimensions + sparkles = []; // Clear existing sparkles + for (let i = 0; i < NUM_SPARKLES; i++) { + sparkles.push(new Sparkle()); + } +} +window.addEventListener('resize', resizeCanvas); +resizeCanvas(); // Initial call to set canvas size and create initial sparkles + +// Load background images from the hidden div +const imageElements = Array.from(document.querySelectorAll('#imageAssets img')); +let imagesLoadedCount = 0; + +imageElements.forEach(imgEl => { + const img = new Image(); + img.src = imgEl.src; + img.onload = () => { + images.push(img); + imagesLoadedCount++; + if (imagesLoadedCount === imageElements.length) { + if (images.length < 2) { + console.error("Need at least two images for a fade transition."); + return; + } + nextImageIndex = (currentImageIndex + 1) % images.length; + requestAnimationFrame(animate); // Start animation once backgrounds are ready + } + }; + img.onerror = () => { + console.error("Failed to load image:", imgEl.src); + }; +}); + +if (imageElements.length === 0) { + console.error("No images found in the #imageAssets div. Please check your HTML and paths."); +} + +// Function to draw an image to cover the entire canvas without stretching. +function drawImageCover(image, alpha = 1) { + if (!image) return; + + ctx.globalAlpha = alpha; + + const imgAspectRatio = image.width / image.height; + const canvasAspectRatio = canvas.width / canvas.height; + + let sx, sy, sWidth, sHeight; + let dx, dy, dWidth, dHeight; + + if (imgAspectRatio > canvasAspectRatio) { + sHeight = image.height; + sWidth = image.height * canvasAspectRatio; + sx = (image.width - sWidth) / 2; + sy = 0; + } else { + sWidth = image.width; + sHeight = image.width / canvasAspectRatio; + sx = 0; + sy = (image.height - sHeight) / 2; + } + + dx = 0; + dy = 0; + dWidth = canvas.width; + dHeight = canvas.height; + + ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); + ctx.globalAlpha = 1; // Reset alpha +} + + + +// --- Main Animation Loop (Updated) --- +function animate(currentTime) { + requestAnimationFrame(animate); + + // 1. Clear the canvas for a fresh frame + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // --- Background Image Fading Logic --- + if (images.length >= 2) { + if (cycleStartTime === 0) { + cycleStartTime = currentTime; + } + + const elapsedTimeInCycle = currentTime - cycleStartTime; + + if (elapsedTimeInCycle < DISPLAY_DURATION) { + drawImageCover(images[currentImageIndex], 1); + } else if (elapsedTimeInCycle < TRANSITION_CYCLE) { + const fadeTime = elapsedTimeInCycle - DISPLAY_DURATION; + const fadeProgress = fadeTime / FADE_DURATION; + const alphaCurrent = 1 - fadeProgress; + const alphaNext = fadeProgress; + + drawImageCover(images[nextImageIndex], alphaNext); + drawImageCover(images[currentImageIndex], alphaCurrent); + } else { + currentImageIndex = nextImageIndex; + nextImageIndex = (currentImageIndex + 1) % images.length; + cycleStartTime = currentTime; + drawImageCover(images[currentImageIndex], 1); + } + } else if (images.length === 1) { + // If only one image, just display it + drawImageCover(images[0], 1); + } + + // 3. Beat Pulse Logic (Controls sparkle pulsation) + if (currentTime - lastBeatTime >= BEAT_INTERVAL) { + lastBeatTime = currentTime; + beatPulse = 1; // Beat hits! + } + beatPulse = Math.max(0, beatPulse - PULSE_DECAY); // Decay the pulse + + + // --- Sparkle Animation Logic (on top of background) --- + sparkles.forEach(sparkle => { + sparkle.update(); + sparkle.draw(); + }); +} + +window.onload = () => { + // Animation starts after background images are loaded +}; \ No newline at end of file diff --git a/sparkles/style.css b/sparkles/style.css new file mode 100644 index 0000000..0e7d096 --- /dev/null +++ b/sparkles/style.css @@ -0,0 +1,11 @@ +body { + margin: 0; + overflow: hidden; + background-color: #000; +} + +#beatCanvas { + display: block; + width: 100vw; + height: 100vh; +} \ No newline at end of file diff --git a/tv-player/bugs.html b/tv-player/bugs.html new file mode 100644 index 0000000..4b3af1c --- /dev/null +++ b/tv-player/bugs.html @@ -0,0 +1,310 @@ + + + + + + Gloomy Room Shadow Scene + + + + + + + +
+ Bugs scattering in a gloomy, shadow-casting room. (Use mouse to look around) +
+ + + + \ No newline at end of file diff --git a/tv-player/bugs_v2.html b/tv-player/bugs_v2.html new file mode 100644 index 0000000..991f61b --- /dev/null +++ b/tv-player/bugs_v2.html @@ -0,0 +1,381 @@ + + + + + + Gloomy Room Shadow Scene + + + + + + + +
+ Spiders scattering in a gloomy, shadow-casting room. (Use mouse to look around) +
+ + + + \ No newline at end of file diff --git a/tv-player/flies.html b/tv-player/flies.html new file mode 100644 index 0000000..913ccf3 --- /dev/null +++ b/tv-player/flies.html @@ -0,0 +1,538 @@ + + + + + + Gloomy Room Shadow Scene + + + + + + + +
+ Spiders and flies scattering in a gloomy, shadow-casting room. (Use mouse to look around) +
+ + + + \ No newline at end of file diff --git a/tv-player/flies_v2.html b/tv-player/flies_v2.html new file mode 100644 index 0000000..77a18ca --- /dev/null +++ b/tv-player/flies_v2.html @@ -0,0 +1,582 @@ + + + + + + Gloomy Room Shadow Scene with Bloom + + + + + + + + + + + + + +
+ Spiders and flies scattering in a gloomy, shadow-casting room with bloom. (Use mouse to look around) +
+ + + + \ No newline at end of file diff --git a/tv-player/index.html b/tv-player/index.html new file mode 100644 index 0000000..1431c3e --- /dev/null +++ b/tv-player/index.html @@ -0,0 +1,691 @@ + + + + + + Retro TV Player + + + + + + + + + +
+ + +
+ + + +
+ +

Ready.

+
+ + + + \ No newline at end of file diff --git a/tv-player/index_v0.html b/tv-player/index_v0.html new file mode 100644 index 0000000..96f52f8 --- /dev/null +++ b/tv-player/index_v0.html @@ -0,0 +1,436 @@ + + + + + + 3D CRT Television Model (Video Player) + + + + + + + + + +
+

Nostalgic CRT Display (Video Player)

+

Click and drag to rotate the bulky set. Load a video to replace the static!

+
+ + +
+ + +
+ + + + + +
+ +
+ + + + \ No newline at end of file diff --git a/tv-player/index_v2.html b/tv-player/index_v2.html new file mode 100644 index 0000000..d5820b1 --- /dev/null +++ b/tv-player/index_v2.html @@ -0,0 +1,267 @@ + + + + + + Retro TV Video Player (3D) + + + + + + + + + + + + + +
+
+

Retro TV Scene

+

+ Load a local MP4 file to play it on the 3D TV screen. The room is dark and dusty. +

+ + + +

Awaiting video file...

+
+
+ + + + + + \ No newline at end of file diff --git a/tv-player/index_v3.html b/tv-player/index_v3.html new file mode 100644 index 0000000..b6a2d7a --- /dev/null +++ b/tv-player/index_v3.html @@ -0,0 +1,719 @@ + + + + + + Retro TV Video Player (3D) + + + + + + + + + +
+ + +
+ + + +
+ +

Ready.

+
+ + + + \ No newline at end of file diff --git a/tv-player/index_v4.html b/tv-player/index_v4.html new file mode 100644 index 0000000..38cf7ab --- /dev/null +++ b/tv-player/index_v4.html @@ -0,0 +1,731 @@ + + + + + + Retro TV Video Player (3D) + + + + + + + + + +
+ + +
+ + + +
+ +

Ready.

+
+ + + + \ No newline at end of file diff --git a/tv-player/serve.sh b/tv-player/serve.sh new file mode 100755 index 0000000..51c5703 --- /dev/null +++ b/tv-player/serve.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +nix-shell -p python3 --run "python3 -m http.server -b 127.0.0.1 8000" \ No newline at end of file diff --git a/tv-player/textures/wall.jpg b/tv-player/textures/wall.jpg new file mode 100644 index 0000000..2fdd61d Binary files /dev/null and b/tv-player/textures/wall.jpg differ diff --git a/tv-player/vcr.html b/tv-player/vcr.html new file mode 100644 index 0000000..dbd0c02 --- /dev/null +++ b/tv-player/vcr.html @@ -0,0 +1,380 @@ + + + + + + VCR Playback Time (3D) + + + + + + + + \ No newline at end of file