Team Ai
Apppublic

itpasotm/Audio-Visualizer

sourceHugging Facemitupdated 2y agoView on Hugging Face
0likes
index.html372 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="ru">3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>Audio Visualizer</title>7    <style>8        * {9            margin: 0;10            padding: 0;11            box-sizing: border-box;12        }13 14        body {15            background: #0f0f1a;16            color: #fff;17            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;18            overflow-x: hidden;19        }20 21        .container {22            width: 100%;23            min-height: 100vh;24            padding: 20px;25            position: relative;26        }27 28        header {29            text-align: center;30            padding: 40px 0;31            animation: fadeIn 1s ease-in;32        }33 34        h1 {35            font-size: 3em;36            margin-bottom: 20px;37            background: linear-gradient(45deg, #ff6b6b, #4ecdc4);38            -webkit-background-clip: text;39            -webkit-text-fill-color: transparent;40        }41 42        .visualizer-container {43            width: 100%;44            height: calc(100vh - 200px);45            margin: 0 auto;46            background: rgba(255, 255, 255, 0.05);47            border-radius: 15px;48            padding: 20px;49            position: relative;50        }51 52        canvas {53            width: 100%;54            height: 100%;55            border-radius: 10px;56            background: rgba(0, 0, 0, 0.3);57        }58 59        .controls {60            position: fixed;61            bottom: 20px;62            left: 50%;63            transform: translateX(-50%);64            display: flex;65            gap: 10px;66            flex-wrap: wrap;67            justify-content: center;68            z-index: 100;69        }70 71        button {72            padding: 10px 20px;73            border: none;74            border-radius: 25px;75            background: linear-gradient(45deg, #ff6b6b, #4ecdc4);76            color: white;77            cursor: pointer;78            transition: transform 0.2s;79        }80 81        button:hover {82            transform: scale(1.05);83        }84 85        input[type="file"] {86            display: none;87        }88 89        .visualization-styles {90            position: fixed;91            top: 20px;92            right: 20px;93            display: flex;94            gap: 10px;95            flex-direction: column;96            z-index: 100;97        }98 99        .style-option {100            padding: 8px 15px;101            border-radius: 15px;102            background: rgba(255, 255, 255, 0.1);103            cursor: pointer;104            transition: background 0.3s;105        }106 107        .style-option:hover {108            background: rgba(255, 255, 255, 0.2);109        }110 111        .center-image {112            position: absolute;113            top: 50%;114            left: 50%;115            transform: translate(-50%, -50%);116            max-width: 200px;117            max-height: 200px;118            z-index: 10;119        }120 121        .background-image {122            position: absolute;123            top: 0;124            left: 0;125            width: 100%;126            height: 100%;127            object-fit: cover;128            opacity: 0.3;129            z-index: 1;130        }131 132        .fullscreen-btn {133            position: fixed;134            top: 20px;135            left: 20px;136            z-index: 100;137        }138 139        .credit {140            position: fixed;141            bottom: 10px;142            right: 20px;143            font-size: 14px;144            opacity: 0.7;145            z-index: 100;146        }147 148        @keyframes fadeIn {149            from {150                opacity: 0;151                transform: translateY(-20px);152            }153            to {154                opacity: 1;155                transform: translateY(0);156            }157        }158 159        @media (max-width: 768px) {160            .visualizer-container {161                padding: 10px;162            }163 164            h1 {165                font-size: 2em;166            }167        }168    </style>169</head>170<body>171    <div class="container">172        <header>173            <h1>Audio Visualizer</h1>174        </header>175 176        <div class="visualizer-container" id="visualizer-container">177            <canvas id="visualizer"></canvas>178            <img id="centerImage" class="center-image" style="display: none;">179            <img id="backgroundImage" class="background-image" style="display: none;">180        </div>181 182        <div class="controls">183            <button onclick="document.getElementById('audioInput').click()">Upload Audio</button>184            <button onclick="document.getElementById('imageInput').click()">Upload Center Image</button>185            <button onclick="document.getElementById('bgImageInput').click()">Upload Background</button>186            <button id="playPause">Play</button>187            <input type="file" id="audioInput" accept="audio/*">188            <input type="file" id="imageInput" accept="image/*,video/gif">189            <input type="file" id="bgImageInput" accept="image/*,video/gif">190        </div>191 192        <button class="fullscreen-btn" onclick="toggleFullscreen()">Fullscreen</button>193 194        <div class="visualization-styles">195            <div class="style-option" data-style="bars">Bars</div>196            <div class="style-option" data-style="wave">Wave</div>197            <div class="style-option" data-style="circle">Circle</div>198        </div>199 200        <div class="credit">by Софронов Артемий</div>201    </div>202 203    <script>204        let audioContext, analyser, source;205        const canvas = document.getElementById('visualizer');206        const ctx = canvas.getContext('2d');207        let animationId;208        let currentStyle = 'bars';209        let centerImage = document.getElementById('centerImage');210        let backgroundImage = document.getElementById('backgroundImage');211        let bassValue = 0;212 213        function resizeCanvas() {214            canvas.width = canvas.clientWidth * window.devicePixelRatio;215            canvas.height = canvas.clientHeight * window.devicePixelRatio;216        }217        resizeCanvas();218        window.addEventListener('resize', resizeCanvas);219 220        document.getElementById('audioInput').addEventListener('change', function(e) {221            const file = e.target.files[0];222            const audio = new Audio();223            audio.src = URL.createObjectURL(file);224            setupAudioContext(audio);225        });226 227        document.getElementById('imageInput').addEventListener('change', function(e) {228            const file = e.target.files[0];229            centerImage.src = URL.createObjectURL(file);230            centerImage.style.display = 'block';231        });232 233        document.getElementById('bgImageInput').addEventListener('change', function(e) {234            const file = e.target.files[0];235            backgroundImage.src = URL.createObjectURL(file);236            backgroundImage.style.display = 'block';237        });238 239        function setupAudioContext(audio) {240            if (audioContext) audioContext.close();241            242            audioContext = new (window.AudioContext || window.webkitAudioContext)();243            analyser = audioContext.createAnalyser();244            source = audioContext.createMediaElementSource(audio);245            246            source.connect(analyser);247            analyser.connect(audioContext.destination);248            249            analyser.fftSize = 256;250            251            audio.play();252            draw();253        }254 255        function draw() {256            const bufferLength = analyser.frequencyBinCount;257            const dataArray = new Uint8Array(bufferLength);258            259            function animate() {260                animationId = requestAnimationFrame(animate);261                analyser.getByteFrequencyData(dataArray);262                263                ctx.fillStyle = 'rgba(15, 15, 26, 0.2)';264                ctx.fillRect(0, 0, canvas.width, canvas.height);265                266                // Get bass value for image animation267                bassValue = dataArray.slice(0, 10).reduce((a, b) => a + b) / 10;268                269                if (centerImage.style.display !== 'none') {270                    const scale = 1 + (bassValue / 255) * 0.2;271                    centerImage.style.transform = `translate(-50%, -50%) scale(${scale})`;272                }273                274                switch(currentStyle) {275                    case 'bars':276                        drawBars(dataArray, bufferLength);277                        break;278                    case 'wave':279                        drawWave(dataArray, bufferLength);280                        break;281                    case 'circle':282                        drawCircle(dataArray, bufferLength);283                        break;284                }285            }286            287            animate();288        }289 290        function drawBars(dataArray, bufferLength) {291            const barWidth = canvas.width / bufferLength;292            293            for(let i = 0; i < bufferLength; i++) {294                const barHeight = dataArray[i] * canvas.height / 255;295                296                const gradient = ctx.createLinearGradient(0, canvas.height, 0, 0);297                gradient.addColorStop(0, '#ff6b6b');298                gradient.addColorStop(1, '#4ecdc4');299                300                ctx.fillStyle = gradient;301                ctx.fillRect(i * barWidth, canvas.height - barHeight, barWidth - 1, barHeight);302            }303        }304 305        function drawWave(dataArray, bufferLength) {306            ctx.beginPath();307            ctx.strokeStyle = '#4ecdc4';308            ctx.lineWidth = 2;309            310            for(let i = 0; i < bufferLength; i++) {311                const x = i * (canvas.width / bufferLength);312                const y = (dataArray[i] / 128.0) * (canvas.height / 2);313                314                if(i === 0) {315                    ctx.moveTo(x, y);316                } else {317                    ctx.lineTo(x, y);318                }319            }320            321            ctx.stroke();322        }323 324        function drawCircle(dataArray, bufferLength) {325            const centerX = canvas.width / 2;326            const centerY = canvas.height / 2;327            const radius = Math.min(centerX, centerY) - 50;328            329            ctx.beginPath();330            ctx.strokeStyle = '#ff6b6b';331            ctx.lineWidth = 2;332 333            for(let i = 0; i < bufferLength; i++) {334                const angle = i * 2 * Math.PI / bufferLength;335                const amplitude = (dataArray[i] * radius / 255) + radius;336                337                const x = centerX + amplitude * Math.cos(angle);338                const y = centerY + amplitude * Math.sin(angle);339                340                if(i === 0) {341                    ctx.moveTo(x, y);342                } else {343                    ctx.lineTo(x, y);344                }345            }346            347            ctx.closePath();348            ctx.stroke();349 350            // Draw base circle351            ctx.beginPath();352            ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);353            ctx.strokeStyle = 'rgba(255, 107, 107, 0.3)';354            ctx.stroke();355        }356 357        document.querySelectorAll('.style-option').forEach(option => {358            option.addEventListener('click', function() {359                currentStyle = this.dataset.style;360            });361        });362 363        function toggleFullscreen() {364            if (!document.fullscreenElement) {365                document.documentElement.requestFullscreen();366            } else {367                document.exitFullscreen();368            }369        }370    </script>371</body>372</html>