ONLINE
setTimeout( function() { var bot = document.getElementById( "dlcFloatingBot" ); if (!bot) { return; } bot.addEventListener( "click", function() { var status = this.querySelector( "small" ); if (!status) { return; } if ( status.textContent .trim() === "ONLINE" ) { status.textContent = "HELLO 👋"; } else { status.textContent = "ONLINE"; } } ); }, 700 ); setTimeout(function () { var bot = document.getElementById( "dlcFloatingBot" ); if (!bot) { return; } /* IMPORTANT: Move the bot outside Carrd's page/container structure and attach it directly to BODY. */ document.body.appendChild(bot); bot.style.setProperty( "position", "fixed", "important" ); bot.style.setProperty( "right", "14px", "important" ); bot.style.setProperty( "bottom", "18px", "important" ); bot.style.setProperty( "left", "auto", "important" ); bot.style.setProperty( "top", "auto", "important" ); bot.style.setProperty( "z-index", "999999", "important" ); }, 1200);
Z z z
💭 THINKING...
(function(){ /* ===================================== GET ROBOT ELEMENTS ===================================== */ var bot = document.getElementById( "dlcFloatingBot" ); var menu = document.getElementById( "dlcBotMenu" ); var zzz = document.getElementById( "dlcBotZZZ" ); var thought = document.getElementById( "dlcBotThought" ); if( !bot || !menu || !zzz || !thought ){ return; } /* ===================================== IMPORTANT SETTINGS CHANGE THESE LATER WHEN WE KNOW THE EXACT SECTION NUMBERS + SOCIAL LINKS ===================================== */ /* BLUEPRINTS SECTION Example: "section04" Do NOT include # */ var BLUEPRINTS_SECTION = "section02"; /* DLC MUSIC STUDIO SECTION Change this to the section containing your main music studio. */ var MUSIC_STUDIO_SECTION = "section05"; /* YOUR SOCIAL LINKS Paste your actual profile links between the quotation marks. */ var YOUTUBE_URL = "https://youtube.com/@dlcdigital25?si=vbNgBkBdvzxTDEpf"; var TIKTOK_URL = "https://www.tiktok.com/@dlcdigital25?_r=1&_t=ZN-99cvbpM1whC"; var INSTAGRAM_URL = "https://www.instagram.com/dlcdigital25?stkn=MXFjMGM0a2JmbHB3Nw=="; /* ===================================== PREVENT DUPLICATE CONTROLLERS ===================================== */ if( bot.dataset.dlcMusicController === "active" ){ return; } bot.dataset.dlcMusicController = "active"; /* ===================================== MOVE FLOATING ITEMS TO BODY ===================================== */ document.body.appendChild( menu ); document.body.appendChild( zzz ); document.body.appendChild( thought ); /* ===================================== STATE ===================================== */ var sleeping = false; var menuOpen = false; var direction = -1; var paused = false; var pauseUntil = 0; var pauseType = ""; var centreUsed = false; /* Walking speed. 0.025 is the same calm walking speed that worked on Digital Folder. */ var speed = 0.025; /* ===================================== START POSITION ===================================== */ var botRect = bot.getBoundingClientRect(); var x = botRect.left; if( !x || x < 8 ){ x = window.innerWidth - ( bot.offsetWidth || 88 ) - 14; } bot.style.setProperty( "right", "auto", "important" ); bot.style.setProperty( "left", x + "px", "important" ); /* ===================================== ROBOT STATUS TEXT ===================================== */ function statusText( text ){ var status = bot.querySelector( "small" ); if(status){ status.textContent = text; } } /* ===================================== ZZZ POSITION ===================================== */ function positionZZZ(){ if( !sleeping ){ zzz.style.display = "none"; return; } var r = bot.getBoundingClientRect(); zzz.style.display = "block"; zzz.style.left = ( r.left + r.width / 2 - 27 ) + "px"; zzz.style.top = ( r.top - 27 ) + "px"; } /* ===================================== THOUGHT POSITION ===================================== */ function positionThought(){ if( thought.style.display !== "block" ){ return; } var r = bot.getBoundingClientRect(); var w = thought.offsetWidth || 110; var bx = r.left + r.width / 2 - w / 2; if( bx < 6 ){ bx = 6; } if( bx + w > window.innerWidth - 6 ){ bx = window.innerWidth - w - 6; } thought.style.left = bx + "px"; thought.style.top = ( r.top - 38 ) + "px"; } /* ===================================== MENU POSITION ===================================== */ function positionMenu(){ if( !menuOpen ){ return; } var r = bot.getBoundingClientRect(); var mw = menu.offsetWidth || 165; var mh = menu.offsetHeight || 320; /* Try above robot first. */ var mx = r.left + r.width - mw; var my = r.top - mh - 10; /* KEEP INSIDE SCREEN */ if( mx < 6 ){ mx = 6; } if( mx + mw > window.innerWidth - 6 ){ mx = window.innerWidth - mw - 6; } /* If there is not enough room above the robot, move menu beside it. */ if( my < 6 ){ my = Math.max( 6, r.top - 20 ); mx = r.left - mw - 10; if( mx < 6 ){ mx = r.right + 10; } if( mx + mw > window.innerWidth - 6 ){ mx = window.innerWidth - mw - 6; } } menu.style.left = mx + "px"; menu.style.top = my + "px"; } /* ===================================== MENU OPEN / CLOSE ===================================== */ function closeMenu(){ menuOpen = false; menu.classList.remove( "open" ); } function openMenu(){ menuOpen = true; updateSleepButton(); menu.classList.add( "open" ); requestAnimationFrame( positionMenu ); } /* ===================================== SLEEP BUTTON WORDING ===================================== */ function updateSleepButton(){ var button = menu.querySelector( '[data-action="sleep"]' ); if( !button ){ return; } button.textContent = sleeping ? "☀️ Wake Up" : "😴 Sleep"; } /* ===================================== CLICK ROBOT ===================================== */ bot.addEventListener( "click", function(event){ event.preventDefault(); event.stopPropagation(); if( menuOpen ){ closeMenu(); } else{ openMenu(); } } ); /* ===================================== PUT ROBOT TO SLEEP ===================================== */ function sleepBot(){ sleeping = true; paused = false; thought.style.display = "none"; bot.classList.add( "dlcSleeping" ); statusText( "SLEEPING" ); positionZZZ(); } /* ===================================== WAKE ROBOT ===================================== */ function wakeBot(){ sleeping = false; /* Remove sleeping class. */ bot.classList.remove( "dlcSleeping" ); /* Force brightness back in case a browser has held onto the filter. */ bot.style.removeProperty( "filter" ); bot.style.removeProperty( "opacity" ); /* Restore eye styling. */ var eyes = bot.querySelectorAll( ".floatVisor i" ); eyes.forEach( function(eye){ eye.style.removeProperty( "height" ); eye.style.removeProperty( "border-radius" ); eye.style.removeProperty( "box-shadow" ); } ); /* HIDE ZZZ */ zzz.style.display = "none"; statusText( "HELLO 👋" ); } /* ===================================== GLOBAL SLEEP COMMANDS Useful later if another DLC feature needs to control the robot. ===================================== */ window.dlcBotSleep = sleepBot; window.dlcBotWake = wakeBot; window.dlcBotToggleSleep = function(){ if( sleeping ){ wakeBot(); } else{ sleepBot(); } }; /* ===================================== OPEN SECTION ===================================== */ function openSection( section ){ if( !section ){ return; } closeMenu(); window.location.hash = section; } /* ===================================== OPEN SOCIAL PLATFORM ===================================== */ function openSocial( url, platformName ){ closeMenu(); if( !url ){ statusText( platformName ); thought.textContent = "🔗 ADD PROFILE LINK"; thought.style.display = "block"; positionThought(); setTimeout( function(){ thought.style.display = "none"; statusText( "ONLINE" ); }, 1800 ); return; } /* Open in another tab so visitors do not lose your DLC website. */ window.open( url, "_blank", "noopener,noreferrer" ); } /* ===================================== MENU ACTIONS ===================================== */ menu.addEventListener( "click", function(event){ var button = event.target.closest( "[data-action]" ); if( !button ){ return; } event.preventDefault(); event.stopPropagation(); var action = button.getAttribute( "data-action" ); /* ===================================== HOME ===================================== */ if( action === "home" ){ closeMenu(); window.location.hash = ""; window.scrollTo({ top:0, behavior: "smooth" }); return; } /* ===================================== BLUEPRINTS ===================================== */ if( action === "blueprints" ){ openSection( BLUEPRINTS_SECTION ); return; } /* ===================================== DLC MUSIC STUDIO ===================================== */ if( action === "studio" ){ openSection( MUSIC_STUDIO_SECTION ); return; } /* ===================================== YOUTUBE ===================================== */ if( action === "youtube" ){ openSocial( YOUTUBE_URL, "YOUTUBE" ); return; } /* ===================================== TIKTOK ===================================== */ if( action === "tiktok" ){ openSocial( TIKTOK_URL, "TIKTOK" ); return; } /* ===================================== INSTAGRAM ===================================== */ if( action === "instagram" ){ openSocial( INSTAGRAM_URL, "INSTAGRAM" ); return; } /* ===================================== SLEEP / WAKE ===================================== */ if( action === "sleep" ){ if( sleeping ){ wakeBot(); } else{ sleepBot(); } updateSleepButton(); closeMenu(); return; } } ); /* ===================================== CLICK OUTSIDE MENU ===================================== */ document.addEventListener( "click", function(event){ if( menuOpen && !menu.contains( event.target ) && !bot.contains( event.target ) ){ closeMenu(); } } ); /* ===================================== THINKING PAUSE ===================================== */ function startThinking( now ){ paused = true; pauseType = "thinking"; pauseUntil = now + 3200; thought.textContent = "💭 THINKING..."; thought.style.display = "block"; statusText( "THINKING" ); positionThought(); } /* ===================================== EDGE PAUSE ===================================== */ function edgePause( now ){ paused = true; pauseType = "edge"; pauseUntil = now + 1100; statusText( "WAITING" ); } /* ===================================== ANIMATION LOOP ===================================== */ var previousTime = performance.now(); function animate( now ){ var delta = Math.min( now - previousTime, 40 ); previousTime = now; /* ===================================== SLEEPING ===================================== */ if( sleeping ){ positionZZZ(); positionMenu(); requestAnimationFrame( animate ); return; } /* ===================================== PAUSED ===================================== */ if( paused ){ if( pauseType === "thinking" ){ var remaining = pauseUntil - now; if( remaining < 1700 ){ thought.textContent = "💡 NEED ANYTHING?"; } positionThought(); } if( now >= pauseUntil ){ paused = false; thought.style.display = "none"; statusText( "ONLINE" ); if( pauseType === "edge" ){ direction *= -1; centreUsed = false; } pauseType = ""; } positionMenu(); requestAnimationFrame( animate ); return; } /* ===================================== SCREEN BOUNDARIES ===================================== */ var width = bot.offsetWidth || 88; var minX = 8; var maxX = window.innerWidth - width - 8; var centre = ( minX + maxX ) / 2; /* ===================================== WALK ===================================== */ x += speed * direction * delta; /* ===================================== STOP AND THINK IN CENTRE ===================================== */ if( !centreUsed && Math.abs( x - centre ) < 3 ){ x = centre; centreUsed = true; startThinking( now ); } /* ===================================== LEFT EDGE ===================================== */ else if( x <= minX ){ x = minX; edgePause( now ); } /* ===================================== RIGHT EDGE ===================================== */ else if( x >= maxX ){ x = maxX; edgePause( now ); } /* ===================================== MOVE ROBOT ===================================== */ bot.style.setProperty( "left", x + "px", "important" ); positionMenu(); requestAnimationFrame( animate ); } requestAnimationFrame( animate ); /* ===================================== SCREEN RESIZE ===================================== */ window.addEventListener( "resize", function(){ var maxX = window.innerWidth - ( bot.offsetWidth || 88 ) - 8; if( x > maxX ){ x = maxX; } if( x < 8 ){ x = 8; } positionZZZ(); positionThought(); positionMenu(); } ); })();

DLC DIGITAL 25

Welcome to DLC Digital 25Learn the complete AI workflow I use to create engaging celebrity tribute videos. Discover the tools, prompts and techniques I've developed through hundreds of videos.⭐ Why learn from me?✓ Over 1 million YouTube views✓ 2700+ TikTok followers
1,500+ YouTube subscribers
1,600+ Instagram followers
✓ AI workflows refined through hundreds of videos✓ Step-by-step guides suitable for beginners

Youtube

Over 1 million YouTube views35,000+ YouTube views in the last 28 days

Tiktok

Nearly 40,000 likes across AI tribute videos.

Instagram

instagram stats

AI Video Blueprint

Learn the exact AI workflow I use to create professional celebrity tribute videos.Included:✔ AI prompts✔ Photo selection✔ Ai settings✔ Editing workflow✔ Thumbnail design✔ Upload strategy✔ Tips I’ve learned after hundreds of videos

Instant Digital Download
£19.99

🎹

Mini Piano

Play, record and create melodies

4
Now playing
Tap a key to begin 🎵
/* ============================ AUDIO SETUP ============================ */ let audioContext = null; let masterGain = null; let currentOctave = 4; let sustainOn = false; const activeNotes = {}; /* RECORDING */ let isRecording = false; let recordingStart = 0; let recordedNotes = []; /* ELEMENTS */ const volumeControl = document.getElementById( "volumeControl" ); const octaveDisplay = document.getElementById( "octaveDisplay" ); const noteDisplay = document.getElementById( "noteDisplay" ); const pianoStatus = document.getElementById( "pianoStatus" ); const sustainButton = document.getElementById( "sustainButton" ); const recordButton = document.getElementById( "recordButton" ); /* ============================ START AUDIO ============================ */ function ensureAudio() { if (!audioContext) { audioContext = new ( window.AudioContext || window.webkitAudioContext )(); masterGain = audioContext.createGain(); masterGain.gain.value = parseFloat( volumeControl.value ); masterGain.connect( audioContext.destination ); } if ( audioContext.state === "suspended" ) { audioContext.resume(); } } /* ============================ FREQUENCIES ============================ */ const noteOffsets = { "C": 0, "C#": 1, "D": 2, "D#": 3, "E": 4, "F": 5, "F#": 6, "G": 7, "G#": 8, "A": 9, "A#": 10, "B": 11 }; function getFrequency( noteName, octave ) { const semitone = noteOffsets[noteName]; const midi = 12 * (octave + 1) + semitone; return ( 440 * Math.pow( 2, (midi - 69) / 12 ) ); } /* ============================ PLAY NOTE ============================ */ function playNote( rawNote, recordIt = true ) { ensureAudio(); let noteName = rawNote; let octave = currentOctave; if ( rawNote === "C2" ) { noteName = "C"; octave = currentOctave + 1; } const id = rawNote; if ( activeNotes[id] ) { return; } const frequency = getFrequency( noteName, octave ); /* OSCILLATORS */ const oscillator1 = audioContext.createOscillator(); const oscillator2 = audioContext.createOscillator(); const gain = audioContext.createGain(); oscillator1.type = "triangle"; oscillator2.type = "sine"; oscillator1.frequency.value = frequency; oscillator2.frequency.value = frequency * 2; oscillator2.detune.value = -8; /* envelope */ const now = audioContext.currentTime; gain.gain.setValueAtTime( 0.001, now ); gain.gain.exponentialRampToValueAtTime( 0.75, now + 0.015 ); gain.gain.exponentialRampToValueAtTime( 0.35, now + 0.25 ); oscillator1.connect( gain ); oscillator2.connect( gain ); gain.connect( masterGain ); oscillator1.start(); oscillator2.start(); activeNotes[id] = { oscillator1, oscillator2, gain }; noteDisplay.textContent = noteName + octave; pianoStatus.textContent = "Playing " + noteName + octave + " 🎵"; /* RECORD NOTE */ if ( isRecording && recordIt ) { recordedNotes.push({ note: rawNote, time: performance.now() - recordingStart }); } /* visual key */ const key = document.querySelector( '[data-note="' + rawNote + '"]' ); if (key) { key.classList.add( "active" ); } } /* ============================ STOP NOTE ============================ */ function stopNote( rawNote ) { const note = activeNotes[rawNote]; if (!note) { return; } const now = audioContext.currentTime; const release = sustainOn ? 1.3 : 0.18; note.gain.gain.cancelScheduledValues( now ); note.gain.gain.setValueAtTime( Math.max( note.gain.gain.value, 0.001 ), now ); note.gain.gain.exponentialRampToValueAtTime( 0.001, now + release ); note.oscillator1.stop( now + release + 0.05 ); note.oscillator2.stop( now + release + 0.05 ); delete activeNotes[ rawNote ]; const key = document.querySelector( '[data-note="' + rawNote + '"]' ); if (key) { key.classList.remove( "active" ); } } /* ============================ POINTER PLAYING ============================ */ document .querySelectorAll( ".white-key, .black-key" ) .forEach( function(key) { key.addEventListener( "pointerdown", function(e) { e.preventDefault(); playNote( this.dataset.note ); } ); key.addEventListener( "pointerup", function() { stopNote( this.dataset.note ); } ); key.addEventListener( "pointercancel", function() { stopNote( this.dataset.note ); } ); key.addEventListener( "pointerleave", function() { stopNote( this.dataset.note ); } ); } ); /* ============================ OCTAVE ============================ */ document .getElementById( "octaveDown" ) .addEventListener( "click", function() { if ( currentOctave > 2 ) { currentOctave--; octaveDisplay.textContent = currentOctave; } } ); document .getElementById( "octaveUp" ) .addEventListener( "click", function() { if ( currentOctave < 6 ) { currentOctave++; octaveDisplay.textContent = currentOctave; } } ); /* ============================ VOLUME ============================ */ volumeControl.addEventListener( "input", function() { ensureAudio(); masterGain.gain.value = parseFloat( this.value ); } ); /* ============================ SUSTAIN ============================ */ sustainButton.addEventListener( "click", function() { sustainOn = !sustainOn; this.textContent = sustainOn ? "ON" : "OFF"; this.classList.toggle( "active", sustainOn ); pianoStatus.textContent = sustainOn ? "Sustain ON 🎶" : "Sustain OFF"; } ); /* ============================ RECORD ============================ */ recordButton.addEventListener( "click", function() { recordedNotes = []; recordingStart = performance.now(); isRecording = true; recordButton.classList.add( "recording" ); pianoStatus.textContent = "Recording... 🔴"; } ); /* ============================ STOP RECORDING ============================ */ document .getElementById( "stopButton" ) .addEventListener( "click", function() { isRecording = false; recordButton.classList.remove( "recording" ); pianoStatus.textContent = recordedNotes.length ? "Recording saved ✓" : "Recording stopped"; } ); /* ============================ PLAY RECORDING ============================ */ document .getElementById( "playButton" ) .addEventListener( "click", function() { if ( recordedNotes.length === 0 ) { pianoStatus.textContent = "Nothing recorded yet"; return; } pianoStatus.textContent = "Playing recording ▶"; recordedNotes.forEach( function(item) { setTimeout( function() { playNote( item.note, false ); setTimeout( function() { stopNote( item.note ); }, 350 ); }, item.time ); } ); } ); /* ============================ CLEAR RECORDING ============================ */ document .getElementById( "clearRecordingButton" ) .addEventListener( "click", function() { recordedNotes = []; isRecording = false; recordButton.classList.remove( "recording" ); pianoStatus.textContent = "Recording cleared ✓"; } );

PIANO NOTES

C C G G A A G
F F E E D D C
G G F F E E D
G G F F E E D
C C G G A A G
F F E E D D C

New site launched please visit digitalfolder.co.uk

AI Video Blueprint

After successful payment you'll receive immediate access to your download.🔒 Secure payments processed by PayPal • Instant digital download

Need help with your project?

Whether you're just starting or looking to grow, I'd be happy to help.
I can assist with:
✅ AI celebrity tribute videos
✅ Video editing and workflow advice
✅ AI prompts and animation guidance
✅ Website design and setup
✅ Digital product creation
✅ General questions about my AI workflow
Simply fill in the form above and I'll get back to you as soon as possible.

Watch one of my latest AI celebrity tribute videos.Singer of:🎤Rainbow🎶Black Sabbath🎤Dio

🎸 Virtual Guitar

Tap a fret to play a note

Tap any fret 🎵
(function() { var audioContext = null; var guitarMode = "clean"; function getAudioContext() { if (!audioContext) { var AudioContextClass = window.AudioContext || window.webkitAudioContext; audioContext = new AudioContextClass(); } if ( audioContext.state === "suspended" ) { audioContext.resume(); } return audioContext; } function midiToFrequency(midi) { return 440 * Math.pow( 2, (midi - 69) / 12 ); } /* Standard guitar tuning: 6th string E2 = MIDI 40 5th string A2 = 45 4th string D3 = 50 3rd string G3 = 55 2nd string B3 = 59 1st string E4 = 64 */ var strings = [ { name: "E", midi: 40 }, { name: "A", midi: 45 }, { name: "D", midi: 50 }, { name: "G", midi: 55 }, { name: "B", midi: 59 }, { name: "E", midi: 64 } ]; var noteNames = [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ]; function midiToName(midi) { var note = noteNames[ midi % 12 ]; var octave = Math.floor( midi / 12 ) - 1; return note + octave; } function playGuitarNote(midi) { var ctx = getAudioContext(); var now = ctx.currentTime; var frequency = midiToFrequency( midi ); /* Main oscillator */ var oscillator = ctx.createOscillator(); var gain = ctx.createGain(); /* Extra overtone gives it more of a plucked-string feel */ var overtone = ctx.createOscillator(); var overtoneGain = ctx.createGain(); /* Tone filter */ var filter = ctx.createBiquadFilter(); if ( guitarMode === "bright" ) { oscillator.type = "sawtooth"; overtone.type = "triangle"; filter.type = "lowpass"; filter.frequency.value = 4200; } else if ( guitarMode === "mute" ) { oscillator.type = "triangle"; overtone.type = "sine"; filter.type = "lowpass"; filter.frequency.value = 1400; } else { oscillator.type = "triangle"; overtone.type = "sine"; filter.type = "lowpass"; filter.frequency.value = 2800; } oscillator.frequency.value = frequency; overtone.frequency.value = frequency * 2; /* Guitar-like attack and decay */ gain.gain.setValueAtTime( 0.0001, now ); gain.gain.exponentialRampToValueAtTime( 0.7, now + 0.015 ); if ( guitarMode === "mute" ) { gain.gain.exponentialRampToValueAtTime( 0.0001, now + 0.35 ); } else { gain.gain.exponentialRampToValueAtTime( 0.0001, now + 1.4 ); } overtoneGain.gain.setValueAtTime( 0.18, now ); overtoneGain.gain.exponentialRampToValueAtTime( 0.0001, now + 0.6 ); oscillator.connect( gain ); overtone.connect( overtoneGain ); gain.connect( filter ); overtoneGain.connect( filter ); filter.connect( ctx.destination ); oscillator.start( now ); overtone.start( now ); oscillator.stop( now + 1.5 ); overtone.stop( now + 0.7 ); document.getElementById( "guitarStatus" ).textContent = "🎵 " + midiToName( midi ); } /* BUILD FRETBOARD */ function buildFretboard() { var board = document.getElementById( "guitarFretboard" ); board.innerHTML = ""; for ( var s = 0; s < strings.length; s++ ) { var row = document.createElement( "div" ); row.style.cssText = "display:grid;" + "grid-template-columns:52px repeat(13,1fr);" + "align-items:center;" + "min-height:52px;" + "position:relative;"; /* String name */ var label = document.createElement( "div" ); label.textContent = strings[s].name; label.style.cssText = "text-align:center;" + "font-weight:bold;" + "font-size:16px;" + "color:#f1d39c;"; row.appendChild( label ); /* Frets 0 to 12 */ for ( var fret = 0; fret <= 12; fret++ ) { (function( stringIndex, fretNumber ) { var fretButton = document.createElement( "button" ); var midi = strings[ stringIndex ].midi + fretNumber; fretButton.type = "button"; fretButton.textContent = fretNumber === 0 ? "O" : fretNumber; fretButton.style.cssText = "height:48px;" + "margin:2px;" + "border:0;" + "border-right:2px solid #b7a67b;" + "background:rgba(0,0,0,0.18);" + "color:#eee;" + "font-size:12px;" + "font-weight:bold;" + "position:relative;" + "cursor:pointer;"; /* Draw string across fret */ var stringLine = document.createElement( "span" ); var thickness = 1 + ((strings.length - stringIndex) * 0.35); stringLine.style.cssText = "position:absolute;" + "left:0;" + "right:0;" + "top:50%;" + "height:" + thickness + "px;" + "background:#d6d6d6;" + "transform:translateY(-50%);" + "pointer-events:none;" + "opacity:0.9;"; fretButton.appendChild( stringLine ); fretButton.addEventListener( "click", function() { playGuitarNote( midi ); fretButton.style.background = "rgba(65,130,255,0.35)"; setTimeout( function() { fretButton.style.background = "rgba(0,0,0,0.18)"; }, 120 ); } ); row.appendChild( fretButton ); })( s, fret ); } board.appendChild( row ); } } /* SOUND MODE BUTTONS */ document.getElementById( "guitarCleanBtn" ).addEventListener( "click", function() { guitarMode = "clean"; document.getElementById( "guitarStatus" ).textContent = "Clean guitar selected 🎸"; } ); document.getElementById( "guitarBrightBtn" ).addEventListener( "click", function() { guitarMode = "bright"; document.getElementById( "guitarStatus" ).textContent = "Bright guitar selected ✨"; } ); document.getElementById( "guitarMuteBtn" ).addEventListener( "click", function() { guitarMode = "mute"; document.getElementById( "guitarStatus" ).textContent = "Palm mute selected 🤘"; } ); buildFretboard(); })();
🐍

Snake

Eat the food, grow longer and beat your best score

Score0
Best0
Speed1
Press Start
📱 Use the arrows on mobile
⌨️ Use arrow keys or W A S D on a computer
(function() { var canvas = document.getElementById( "snakeCanvas" ); var ctx = canvas.getContext( "2d" ); var scoreBox = document.getElementById( "snakeScore" ); var bestBox = document.getElementById( "snakeBest" ); var speedBox = document.getElementById( "snakeSpeed" ); var message = document.getElementById( "snakeMessage" ); var startButton = document.getElementById( "snakeStartButton" ); var pauseButton = document.getElementById( "snakePauseButton" ); var grid = 20; var tileCount = canvas.width / grid; var snake = []; var food = { x:5, y:5 }; var direction = { x:1, y:0 }; var nextDirection = { x:1, y:0 }; var score = 0; var speedLevel = 1; var gameTimer = null; var running = false; var paused = false; var bestScore = 0; try { bestScore = Number( localStorage.getItem( "dlcSnakeBest" ) ) || 0; } catch(error) { bestScore = 0; } bestBox.textContent = bestScore; function randomFood() { var valid = false; while (!valid) { food.x = Math.floor( Math.random() * tileCount ); food.y = Math.floor( Math.random() * tileCount ); valid = true; for ( var i = 0; i < snake.length; i++ ) { if ( snake[i].x === food.x && snake[i].y === food.y ) { valid = false; break; } } } } function resetGame() { snake = [ { x:8, y:10 }, { x:7, y:10 }, { x:6, y:10 } ]; direction = { x:1, y:0 }; nextDirection = { x:1, y:0 }; score = 0; speedLevel = 1; scoreBox.textContent = score; speedBox.textContent = speedLevel; paused = false; running = true; message.style.display = "none"; randomFood(); startLoop(); } function startLoop() { if (gameTimer) { clearInterval( gameTimer ); } var speed = Math.max( 65, 145 - ((speedLevel - 1) * 10) ); gameTimer = setInterval( gameStep, speed ); } function gameStep() { if ( !running || paused ) { return; } direction.x = nextDirection.x; direction.y = nextDirection.y; var newHead = { x: snake[0].x + direction.x, y: snake[0].y + direction.y }; /* WALL COLLISION */ if ( newHead.x < 0 || newHead.y < 0 || newHead.x >= tileCount || newHead.y >= tileCount ) { gameOver(); return; } /* BODY COLLISION */ for ( var i = 0; i < snake.length; i++ ) { if ( snake[i].x === newHead.x && snake[i].y === newHead.y ) { gameOver(); return; } } snake.unshift( newHead ); /* FOOD */ if ( newHead.x === food.x && newHead.y === food.y ) { score++; scoreBox.textContent = score; randomFood(); var newSpeed = Math.floor( score / 5 ) + 1; if ( newSpeed !== speedLevel ) { speedLevel = newSpeed; speedBox.textContent = speedLevel; startLoop(); } } else { snake.pop(); } draw(); } function draw() { ctx.clearRect( 0, 0, canvas.width, canvas.height ); /* FOOD */ ctx.beginPath(); ctx.arc( food.x * grid + grid / 2, food.y * grid + grid / 2, grid * 0.35, 0, Math.PI * 2 ); ctx.fillStyle = "#ff4055"; ctx.fill(); /* SNAKE */ for ( var i = 0; i < snake.length; i++ ) { var part = snake[i]; if (i === 0) { ctx.fillStyle = "#8a72ff"; } else { ctx.fillStyle = "#5034c9"; } ctx.fillRect( part.x * grid + 2, part.y * grid + 2, grid - 4, grid - 4 ); } } function gameOver() { running = false; clearInterval( gameTimer ); if ( score > bestScore ) { bestScore = score; bestBox.textContent = bestScore; try { localStorage.setItem( "dlcSnakeBest", bestScore ); } catch(error) {} } message.innerHTML = "Game Over
" + "" + "Score: " + score + ""; message.style.display = "block"; } function setDirection( newDirection ) { if (!running) { return; } if ( newDirection === "up" && direction.y !== 1 ) { nextDirection = { x:0, y:-1 }; } else if ( newDirection === "down" && direction.y !== -1 ) { nextDirection = { x:0, y:1 }; } else if ( newDirection === "left" && direction.x !== 1 ) { nextDirection = { x:-1, y:0 }; } else if ( newDirection === "right" && direction.x !== -1 ) { nextDirection = { x:1, y:0 }; } } startButton.addEventListener( "click", resetGame ); pauseButton.addEventListener( "click", function() { if (!running) { return; } paused = !paused; if (paused) { message.textContent = "Paused"; message.style.display = "block"; pauseButton.textContent = "▶ Continue"; } else { message.style.display = "none"; pauseButton.textContent = "⏸ Pause"; } } ); document .querySelectorAll( "#dlcSnakeGame [data-direction]" ) .forEach( function(button) { button.addEventListener( "pointerdown", function(event) { event.preventDefault(); setDirection( this.getAttribute( "data-direction" ) ); } ); } ); document.addEventListener( "keydown", function(event) { var key = event.key.toLowerCase(); if ( key === "arrowup" || key === "w" ) { event.preventDefault(); setDirection( "up" ); } else if ( key === "arrowdown" || key === "s" ) { event.preventDefault(); setDirection( "down" ); } else if ( key === "arrowleft" || key === "a" ) { event.preventDefault(); setDirection( "left" ); } else if ( key === "arrowright" || key === "d" ) { event.preventDefault(); setDirection( "right" ); } } ); draw(); })();
🥁 Drum Kit
Tap the drums or use the keyboard
🥁 Tap a drum to begin
(function(){ const drums = document.querySelectorAll( "#dlcDrumKit .drum" ); const status = document.getElementById( "drumStatus" ); let drumAudio = null; function ensureDrumAudio(){ if(!drumAudio){ drumAudio = new( window.AudioContext || window.webkitAudioContext )(); } if( drumAudio.state === "suspended" ){ drumAudio.resume(); } } /* SIMPLE TEST SOUND */ function playTestSound( name, button ){ ensureDrumAudio(); const now = drumAudio.currentTime; const osc = drumAudio.createOscillator(); const gain = drumAudio.createGain(); /* Different pitch for each drum temporarily. */ const frequencies = { kick:90, snare:180, hihat:400, crash:520, ride:620, tom1:220, tom2:170, floor:120 }; osc.type = "sine"; osc.frequency .setValueAtTime( frequencies[name] || 200, now ); gain.gain .setValueAtTime( 0.8, now ); gain.gain .exponentialRampToValueAtTime( 0.001, now+.25 ); osc.connect( gain ); gain.connect( drumAudio.destination ); osc.start(); osc.stop( now+.26 ); /* FLASH */ button.classList.add( "hit" ); setTimeout( function(){ button.classList.remove( "hit" ); }, 100 ); if(status){ status.textContent = "🔊 " + name.toUpperCase(); } } drums.forEach( function(button){ button.addEventListener( "pointerdown", function(event){ event.preventDefault(); playTestSound( this.dataset.drum, this ); } ); } ); })();

Drum kit in progress 🚧

🎧

Remix Station

Scratch • remix • sample • record

100
DLC
REMIX
VINYL DECK
READY Drag record backwards & forwards
✨ DJ Effects
🎛 Sample Pads
🎙 Voice Recorder
🎧 Remix Station ready
(function(){ var root = document.getElementById( "dlcRemix" ); if(!root){ return; } /* ===================================== ELEMENTS ===================================== */ var record = document.getElementById( "rmxRecord" ); var deckStatus = document.getElementById( "rmxDeckStatus" ); var status = document.getElementById( "rmxStatus" ); var volume = document.getElementById( "rmxVolume" ); var bpmText = document.getElementById( "rmxBpmText" ); /* ===================================== AUDIO ===================================== */ var RemixAudioClass = window.AudioContext || window.webkitAudioContext; var remixAudio = null; var remixMaster = null; var remixFilter = null; var remixDelay = null; var remixFeedback = null; var remixDry = null; var remixWet = null; function ensureRemixAudio(){ if(!remixAudio){ remixAudio = new RemixAudioClass(); remixMaster = remixAudio.createGain(); remixMaster.gain.value = parseFloat( volume.value ); remixFilter = remixAudio.createBiquadFilter(); remixFilter.type = "lowpass"; remixFilter.frequency.value = 18000; remixDelay = remixAudio.createDelay( 1 ); remixDelay.delayTime.value = .22; remixFeedback = remixAudio.createGain(); remixFeedback.gain.value = 0; remixDry = remixAudio.createGain(); remixWet = remixAudio.createGain(); remixDry.gain.value = 1; remixWet.gain.value = 0; /* DRY */ remixFilter.connect( remixDry ); remixDry.connect( remixMaster ); /* ECHO */ remixFilter.connect( remixDelay ); remixDelay.connect( remixFeedback ); remixFeedback.connect( remixDelay ); remixDelay.connect( remixWet ); remixWet.connect( remixMaster ); remixMaster.connect( remixAudio.destination ); } if( remixAudio.state === "suspended" ){ remixAudio.resume(); } } /* ===================================== CONNECT SOUND ===================================== */ function connectRemix( node ){ node.connect( remixFilter ); } /* ===================================== KICK ===================================== */ function remixKick(){ ensureRemixAudio(); var now = remixAudio.currentTime; var osc = remixAudio.createOscillator(); var gain = remixAudio.createGain(); osc.type = "sine"; osc.frequency .setValueAtTime( 145, now ); osc.frequency .exponentialRampToValueAtTime( 45, now+.18 ); gain.gain .setValueAtTime( .85, now ); gain.gain .exponentialRampToValueAtTime( .001, now+.25 ); osc.connect( gain ); connectRemix( gain ); osc.start(); osc.stop( now+.27 ); } /* ===================================== SNARE OSCILLATOR VERSION ===================================== */ function remixSnare(){ ensureRemixAudio(); var now = remixAudio.currentTime; var a = remixAudio.createOscillator(); var b = remixAudio.createOscillator(); var gain = remixAudio.createGain(); a.type = "square"; b.type = "triangle"; a.frequency.value = 180; b.frequency.value = 330; gain.gain .setValueAtTime( .28, now ); gain.gain .exponentialRampToValueAtTime( .001, now+.12 ); a.connect(gain); b.connect(gain); connectRemix( gain ); a.start(); b.start(); a.stop( now+.13 ); b.stop( now+.13 ); } /* ===================================== METALLIC HI-HAT ===================================== */ function remixHat(){ ensureRemixAudio(); var now = remixAudio.currentTime; var gain = remixAudio.createGain(); gain.gain .setValueAtTime( .11, now ); gain.gain .exponentialRampToValueAtTime( .001, now+.07 ); [ 3100, 4210, 5320, 6460 ] .forEach( function(freq){ var osc = remixAudio .createOscillator(); osc.type = "square"; osc.frequency.value = freq; osc.connect( gain ); osc.start(); osc.stop( now+.08 ); } ); connectRemix( gain ); } /* ===================================== BEAT ===================================== */ var bpm = 100; var beatTimer = null; var beatStep = 0; var beatPlaying = false; function beatInterval(){ return ( 60000 / bpm ) / 2; } function beatTick(){ if(!beatPlaying){ return; } if( beatStep % 4 === 0 ){ remixKick(); } if( beatStep % 4 === 2 ){ remixSnare(); } remixHat(); beatStep++; } function startBeat(){ ensureRemixAudio(); stopBeatTimer(); beatPlaying = true; beatStep = 0; beatTick(); beatTimer = setInterval( beatTick, beatInterval() ); record.classList.add( "spinning" ); deckStatus.textContent = "PLAYING"; status.textContent = "🎵 Beat playing"; } function stopBeatTimer(){ if(beatTimer){ clearInterval( beatTimer ); beatTimer = null; } } function stopBeat(){ beatPlaying = false; stopBeatTimer(); deckStatus.textContent = "STOPPED"; status.textContent = "⏹ Beat stopped"; } /* ===================================== RECORD ROTATION ===================================== */ var recordAngle = 0; var recordSpeed = 0; var scratching = false; var lastPointerAngle = 0; function pointerAngle( event ){ var r = record.getBoundingClientRect(); var cx = r.left + r.width/2; var cy = r.top + r.height/2; return Math.atan2( event.clientY - cy, event.clientX - cx ); } /* ===================================== SCRATCH SOUND ===================================== */ function scratchSound( movement ){ ensureRemixAudio(); var amount = Math.min( 1, Math.abs( movement )*3 ); if(amount<.02){ return; } var now = remixAudio.currentTime; var osc = remixAudio.createOscillator(); var gain = remixAudio.createGain(); osc.type = "sawtooth"; var frequency = movement >= 0 ? 280 + amount*700 : 110 + amount*300; osc.frequency .setValueAtTime( frequency, now ); osc.frequency .exponentialRampToValueAtTime( Math.max( 65, frequency*.55 ), now+.055 ); gain.gain .setValueAtTime( .12 + amount*.14, now ); gain.gain .exponentialRampToValueAtTime( .001, now+.07 ); osc.connect( gain ); connectRemix( gain ); osc.start(); osc.stop( now+.075 ); } /* ===================================== SCRATCH INPUT ===================================== */ record.addEventListener( "pointerdown", function(event){ event.preventDefault(); ensureRemixAudio(); scratching = true; lastPointerAngle = pointerAngle( event ); recordSpeed = 0; deckStatus.textContent = "SCRATCH"; try{ record.setPointerCapture( event.pointerId ); } catch(error){} } ); record.addEventListener( "pointermove", function(event){ if(!scratching){ return; } event.preventDefault(); var angle = pointerAngle( event ); var delta = angle - lastPointerAngle; /* WRAP ANGLE */ if( delta > Math.PI ){ delta -= Math.PI*2; } if( delta < -Math.PI ){ delta += Math.PI*2; } recordAngle += delta * 180 / Math.PI; recordSpeed = delta*20; lastPointerAngle = angle; scratchSound( delta ); } ); function stopScratch(){ if(!scratching){ return; } scratching = false; deckStatus.textContent = beatPlaying ? "PLAYING" : "READY"; } record.addEventListener( "pointerup", stopScratch ); record.addEventListener( "pointercancel", stopScratch ); /* ===================================== ANIMATE VINYL ===================================== */ function animateRecord(){ if(!scratching){ if(beatPlaying){ recordAngle += .9; } else{ recordAngle += recordSpeed; recordSpeed *= .94; } } record.style.transform = "rotate(" + recordAngle + "deg)"; requestAnimationFrame( animateRecord ); } requestAnimationFrame( animateRecord ); /* ===================================== BEAT BUTTONS ===================================== */ document .getElementById( "rmxBeat" ) .addEventListener( "click", startBeat ); document .getElementById( "rmxStop" ) .addEventListener( "click", stopBeat ); /* ===================================== BPM ===================================== */ function refreshBeat(){ bpmText.textContent = bpm; if(beatPlaying){ stopBeatTimer(); beatTimer = setInterval( beatTick, beatInterval() ); } } document .getElementById( "rmxBpmDown" ) .addEventListener( "click", function(){ bpm = Math.max( 60, bpm-5 ); refreshBeat(); } ); document .getElementById( "rmxBpmUp" ) .addEventListener( "click", function(){ bpm = Math.min( 180, bpm+5 ); refreshBeat(); } ); /* ===================================== VOLUME ===================================== */ volume.addEventListener( "input", function(){ ensureRemixAudio(); remixMaster.gain.value = parseFloat( this.value ); } ); /* ===================================== ECHO ===================================== */ var echoOn = false; document .getElementById( "rmxEcho" ) .addEventListener( "click", function(){ ensureRemixAudio(); echoOn = !echoOn; remixFeedback.gain.value = echoOn ? .32 : 0; remixWet.gain.value = echoOn ? .45 : 0; this.classList.toggle( "active", echoOn ); status.textContent = echoOn ? "✨ Echo ON" : "Echo OFF"; } ); /* ===================================== FILTER ===================================== */ var filterOn = false; document .getElementById( "rmxFilter" ) .addEventListener( "click", function(){ ensureRemixAudio(); filterOn = !filterOn; remixFilter.frequency .setTargetAtTime( filterOn ? 750 : 18000, remixAudio.currentTime, .05 ); this.classList.toggle( "active", filterOn ); status.textContent = filterOn ? "🎛 Filter ON" : "Filter OFF"; } ); /* ===================================== BRAKE ===================================== */ document .getElementById( "rmxBrake" ) .addEventListener( "click", function(){ ensureRemixAudio(); var now = remixAudio.currentTime; var osc = remixAudio.createOscillator(); var gain = remixAudio.createGain(); osc.type = "sawtooth"; osc.frequency .setValueAtTime( 420, now ); osc.frequency .exponentialRampToValueAtTime( 55, now+.8 ); gain.gain .setValueAtTime( .20, now ); gain.gain .exponentialRampToValueAtTime( .001, now+.82 ); osc.connect( gain ); connectRemix( gain ); osc.start(); osc.stop( now+.84 ); recordSpeed = -4; status.textContent = "🛑 Brake effect"; } ); /* ===================================== STUTTER ===================================== */ document .getElementById( "rmxStutter" ) .addEventListener( "click", function(){ ensureRemixAudio(); for( var i=0; i<6; i++ ){ setTimeout( function(){ remixSnare(); }, i*70 ); } status.textContent = "⚡ Stutter"; } ); /* ===================================== PITCH FX ===================================== */ function pitchEffect( up ){ ensureRemixAudio(); var now = remixAudio.currentTime; var osc = remixAudio.createOscillator(); var gain = remixAudio.createGain(); osc.type = "sawtooth"; var start = up ? 120 : 850; var end = up ? 900 : 90; osc.frequency .setValueAtTime( start, now ); osc.frequency .exponentialRampToValueAtTime( end, now+.45 ); gain.gain .setValueAtTime( .16, now ); gain.gain .exponentialRampToValueAtTime( .001, now+.48 ); osc.connect( gain ); connectRemix( gain ); osc.start(); osc.stop( now+.5 ); } document .getElementById( "rmxPitchDown" ) .addEventListener( "click", function(){ pitchEffect( false ); status.textContent = "⬇ Pitch down"; } ); document .getElementById( "rmxPitchUp" ) .addEventListener( "click", function(){ pitchEffect( true ); status.textContent = "⬆ Pitch up"; } ); /* ===================================== AIR HORN ===================================== */ document .getElementById( "rmxHorn" ) .addEventListener( "click", function(){ ensureRemixAudio(); var now = remixAudio.currentTime; [ 185, 233 ] .forEach( function(freq){ var osc = remixAudio.createOscillator(); var gain = remixAudio.createGain(); osc.type = "sawtooth"; osc.frequency.value = freq; gain.gain .setValueAtTime( .22, now ); gain.gain .setValueAtTime( .22, now+.25 ); gain.gain .exponentialRampToValueAtTime( .001, now+.75 ); osc.connect( gain ); connectRemix( gain ); osc.start(); osc.stop( now+.77 ); } ); status.textContent = "📣 AIR HORN!"; } ); /* ===================================== SAMPLER PADS ===================================== */ function samplerSound( pad ){ ensureRemixAudio(); var now = remixAudio.currentTime; var osc = remixAudio.createOscillator(); var gain = remixAudio.createGain(); if(pad===1){ osc.type = "sawtooth"; osc.frequency .setValueAtTime( 700, now ); osc.frequency .exponentialRampToValueAtTime( 80, now+.35 ); } else if(pad===2){ osc.type = "square"; osc.frequency .setValueAtTime( 1200, now ); osc.frequency .exponentialRampToValueAtTime( 180, now+.25 ); } else if(pad===3){ osc.type = "sine"; osc.frequency .setValueAtTime( 80, now ); osc.frequency .exponentialRampToValueAtTime( 42, now+.4 ); } else{ osc.type = "sawtooth"; osc.frequency .setValueAtTime( 90, now ); osc.frequency .exponentialRampToValueAtTime( 1000, now+.6 ); } gain.gain .setValueAtTime( .25, now ); gain.gain .exponentialRampToValueAtTime( .001, now+.65 ); osc.connect( gain ); connectRemix( gain ); osc.start(); osc.stop( now+.67 ); } document .querySelectorAll( "#dlcRemix .rmx-pad" ) .forEach( function(button){ button.addEventListener( "pointerdown", function(event){ event.preventDefault(); var pad = parseInt( this.dataset.pad, 10 ); samplerSound( pad ); this.classList.add( "hit" ); var self = this; setTimeout( function(){ self.classList.remove( "hit" ); }, 100 ); status.textContent = "🎛 Sample Pad " + pad; } ); } ); /* ===================================== VOICE RECORDING ===================================== */ var micStream = null; var micRecorder = null; var micChunks = []; var voicePlayer = document.getElementById( "rmxVoicePlayer" ); var micRecordButton = document.getElementById( "rmxMicRecord" ); var deleteVoice = document.getElementById( "rmxDeleteVoice" ); document .getElementById( "rmxMicRecord" ) .addEventListener( "click", async function(){ if( !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia ){ status.textContent = "⚠️ Microphone recording unavailable"; return; } try{ micStream = await navigator .mediaDevices .getUserMedia({ audio:true }); micChunks = []; micRecorder = new MediaRecorder( micStream ); micRecorder.ondataavailable = function(event){ if( event.data && event.data.size > 0 ){ micChunks.push( event.data ); } }; micRecorder.onstop = function(){ var blob = new Blob( micChunks, { type: micRecorder.mimeType || "audio/webm" } ); var url = URL.createObjectURL( blob ); voicePlayer.src = url; voicePlayer.style.display = "block"; deleteVoice.style.display = "block"; micRecordButton .classList.remove( "recording" ); status.textContent = "🎙 Voice recording saved ✓"; if(micStream){ micStream .getTracks() .forEach( function(track){ track.stop(); } ); } }; micRecorder.start(); this.classList.add( "recording" ); status.textContent = "🔴 Recording voice..."; } catch(error){ status.textContent = "🎙 Microphone permission was not granted"; } } ); document .getElementById( "rmxMicStop" ) .addEventListener( "click", function(){ if( micRecorder && micRecorder.state !== "inactive" ){ micRecorder.stop(); } } ); deleteVoice .addEventListener( "click", function(){ voicePlayer.pause(); voicePlayer.removeAttribute( "src" ); voicePlayer.load(); voicePlayer.style.display = "none"; deleteVoice.style.display = "none"; micChunks = []; status.textContent = "🗑 Voice recording deleted"; } ); })();

Remix station kit in progress 🚧

About

Hi, I’m David, founder of DLC Digital 25.I create AI-animated celebrity tribute videos that have generated over 1 million YouTube views and tens of thousands of interactions across social media.After creating hundreds of videos, I’ve developed workflows that help produce professional-looking AI content faster and more consistently.Now I’m sharing the methods, blueprints and guides I use so others can learn the same process.Every technique shared on this website is based on my own workflow and experience creating AI tribute videos.

  • Privacy Policy

  • Contact

  • Terms & Conditions

  • FaQ

Privacy policy

At DLC Digital 25, your privacy is important.If you purchase a product or contact me through this website, I may collect your name, email address and any information you choose to provide.Your information is used only to:• Deliver your digital products• Respond to your enquiries• Provide customer supportI will never sell or share your personal information with third parties unless required by law.Payments are processed securely through PayPal. DLC Digital 25 does not store your payment details.If you would like your personal information removed, please contact me using the details below.Last updated: August 2026

Contact

If you have any questions about my digital products, your order or would like a custom AI video created, I’d love to hear from you.Email:[email protected]I aim to reply within 24 hours.Thank you for visiting DLC Digital 25.

Terms

Digital products are delivered electronically.Due to the nature of downloadable products, refunds are generally not available once the file has been sent unless required by law or if there has been a technical problem with delivery.

Frequently Asked Questions

●How do I receive the blueprint?
Immediately after payment you'll be redirected to your download.
●Can I use my phone?
Yes.
Much of the workflow can be completed on a mobile device.
●Do I need ChatGPT?
I recommend using ChatGPT to help with research, planning, captions and prompt creation
●Can beginners follow this guide?
Yes. The blueprint is designed for complete beginners.

Thank you for your purchase!

Your AI Video Blueprint is ready.Click the button below to download your PDF.