Blog / JavaScript

Creer un visualiseur audio avec Web Audio API

Transformez l'audio en visualisations dynamiques et interactives avec la Web Audio API et Canvas. Du spectre de frequences a la forme d'onde, creez des experiences visuelles immersives.

Introduction

La Web Audio API est l'une des APIs les plus puissantes du navigateur. Elle permet d'analyser, de traiter et de generer de l'audio en temps reel. Combinee avec Canvas, elle ouvre la porte a des visualisations audio spectaculaires directement dans le navigateur.

Dans ce tutoriel, nous allons construire 3 types de visualisations differentes : un spectre de frequences en barres, une forme d'onde oscilloscope et un cercle radial reactif. Chaque exemple est accompagne du code complet et d'une demo interactive.

💡
Bon a savoir

La Web Audio API necessite une interaction utilisateur (clic) avant de pouvoir demarrer, conformement aux politiques de lecture automatique des navigateurs modernes.

1. Configuration de base

Avant de creer nos visualisations, nous devons configurer le contexte audio et l'analyseur. L'AnalyserNode est le coeur de toute visualisation audio : il extrait les donnees de frequence et de forme d'onde en temps reel.

audio-setup.js
// Creer le contexte audio
const audioContext = new AudioContext();
const analyser = audioContext.createAnalyser();

// fftSize determine la precision de l'analyse
// Plus la valeur est grande, plus l'analyse est fine
analyser.fftSize = 256;

// Connecter le microphone
navigator.mediaDevices.getUserMedia({ audio: true })
    .then(stream => {
        const source = audioContext.createMediaStreamSource(stream);
        source.connect(analyser);
        visualize();
    });

Les parametres cles de l'AnalyserNode

  • fftSize : Taille de la FFT (Fast Fourier Transform). Valeurs possibles : 32 a 32768. Determine le nombre de barres de frequence (fftSize / 2)
  • frequencyBinCount : Nombre de points de donnees disponibles (= fftSize / 2)
  • smoothingTimeConstant : Lissage temporel entre 0 et 1. Plus la valeur est haute, plus la transition est douce
  • minDecibels / maxDecibels : Plage de decibels pour la visualisation

2. Barres de frequence

Le spectre de frequences est la visualisation audio la plus classique. Chaque barre represente l'amplitude d'une bande de frequence specifique, des basses (a gauche) aux aigus (a droite).

frequency-bars.js
function drawBars(analyser, canvas) {
    const ctx = canvas.getContext('2d');
    const bufferLength = analyser.frequencyBinCount;
    const dataArray = new Uint8Array(bufferLength);

    function draw() {
        // Recuperer les donnees de frequence
        analyser.getByteFrequencyData(dataArray);

        // Effacer le canvas
        ctx.fillStyle = '#0a0a0f';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        const barWidth = canvas.width / bufferLength;

        dataArray.forEach((value, i) => {
            const barHeight = value / 1.5;
            // Degrade de couleur base sur la frequence
            const hue = (i / bufferLength) * 270 + 240;
            ctx.fillStyle = `hsl(${hue}, 70%, 50%)`;
            ctx.fillRect(
                i * barWidth,
                canvas.height - barHeight,
                barWidth - 1,
                barHeight
            );
        });

        requestAnimationFrame(draw);
    }
    draw();
}

Comment ca fonctionne

La methode getByteFrequencyData() remplit un tableau avec les amplitudes de chaque bande de frequence, sur une echelle de 0 a 255. Voici le detail :

  • requestAnimationFrame : Synchronise le rendu avec le rafraichissement de l'ecran (~60fps)
  • barWidth : Chaque barre occupe une fraction egale de la largeur du canvas
  • Couleur HSL : Le hue varie selon la position pour creer un degrade de couleurs naturel

3. Forme d'onde (Oscilloscope)

La visualisation en forme d'onde affiche le signal audio brut, comme un oscilloscope. C'est ideal pour voir la structure temporelle du son.

waveform.js
function drawWaveform(analyser, canvas) {
    const ctx = canvas.getContext('2d');
    const bufferLength = analyser.frequencyBinCount;
    const dataArray = new Uint8Array(bufferLength);

    function draw() {
        // Donnees de forme d'onde (pas de frequence)
        analyser.getByteTimeDomainData(dataArray);

        ctx.fillStyle = '#0a0a0f';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // Dessiner la courbe
        ctx.lineWidth = 2;
        ctx.strokeStyle = '#6366f1';
        ctx.beginPath();

        const sliceWidth = canvas.width / bufferLength;

        dataArray.forEach((value, i) => {
            const x = i * sliceWidth;
            const y = (value / 128) * (canvas.height / 2);
            i === 0
                ? ctx.moveTo(x, y)
                : ctx.lineTo(x, y);
        });

        ctx.stroke();
        requestAnimationFrame(draw);
    }
    draw();
}
📊
Difference entre les deux methodes

getByteFrequencyData() renvoie le spectre de frequences (domaine frequentiel), tandis que getByteTimeDomainData() renvoie la forme d'onde brute (domaine temporel). Les deux utilisent le meme AnalyserNode.

4. Cercle radial

Le cercle radial est une visualisation plus artistique ou les barres de frequence sont disposees en cercle. C'est un effet tres populaire dans les lecteurs de musique et les experiences interactives.

radial-visualizer.js
function drawRadial(analyser, canvas) {
    const ctx = canvas.getContext('2d');
    const bufferLength = analyser.frequencyBinCount;
    const dataArray = new Uint8Array(bufferLength);
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const radius = 60;

    function draw() {
        analyser.getByteFrequencyData(dataArray);

        ctx.fillStyle = 'rgba(10, 10, 15, 0.2)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        for (let i = 0; i < bufferLength; i++) {
            const angle = (i / bufferLength) * Math.PI * 2;
            const barHeight = dataArray[i] / 3;
            const hue = (i / bufferLength) * 360;

            const x1 = centerX + Math.cos(angle) * radius;
            const y1 = centerY + Math.sin(angle) * radius;
            const x2 = centerX + Math.cos(angle) * (radius + barHeight);
            const y2 = centerY + Math.sin(angle) * (radius + barHeight);

            ctx.strokeStyle = `hsl(${hue}, 70%, 60%)`;
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.stroke();
        }
        requestAnimationFrame(draw);
    }
    draw();
}
⚠️
Performance

La visualisation radiale est plus couteuse en rendu. Sur mobile, reduisez le fftSize a 128 et limitez le nombre de barres dessinees pour maintenir un framerate fluide.

5. Utiliser un fichier audio

Plutot que le microphone, vous pouvez aussi visualiser un fichier audio ou un element <audio>. C'est souvent plus pratique pour les sites avec un lecteur musical integre.

audio-file.js
// Utiliser un element <audio> existant
const audio = document.querySelector('audio');
const audioContext = new AudioContext();
const analyser = audioContext.createAnalyser();

// Creer la source a partir de l'element audio
const source = audioContext.createMediaElementSource(audio);
source.connect(analyser);

// Important : connecter aussi a la destination pour entendre l'audio
analyser.connect(audioContext.destination);

// Lancer la visualisation quand l'audio joue
audio.addEventListener('play', () => {
    audioContext.resume();
    drawBars(analyser, canvas);
});
💡
Astuce importante

Quand vous utilisez createMediaElementSource(), n'oubliez pas de connecter l'analyseur a audioContext.destination, sinon l'audio sera muet ! Avec le microphone, cette connexion n'est pas necessaire car on ne veut pas de retour audio.

Bonnes pratiques

Voici les recommandations essentielles pour creer des visualiseurs audio performants et accessibles :

Performance

  • Reduisez le fftSize sur mobile : 128 ou 64 suffisent pour un rendu fluide
  • Utilisez requestAnimationFrame plutot que setInterval pour synchroniser avec l'ecran
  • Evitez les allocations dans la boucle : creez vos tableaux en dehors de la fonction draw
  • Nettoyez les ressources : fermez l'AudioContext et arretez le stream micro quand la page est quittee

Accessibilite et UX

  • Demandez la permission : l'acces au micro doit etre declenche par un clic utilisateur
  • Gerez les erreurs : prevoyez le cas ou l'utilisateur refuse l'acces au micro
  • Respectez prefers-reduced-motion : proposez une version statique pour les utilisateurs sensibles

Nettoyage des ressources

cleanup.js
// Arreter proprement le visualiseur
function stopVisualizer(stream, audioContext, animationId) {
    // Arreter le micro
    stream.getTracks().forEach(track => track.stop());

    // Fermer le contexte audio
    audioContext.close();

    // Arreter l'animation
    cancelAnimationFrame(animationId);
}

Conclusion

La Web Audio API ouvre un monde de possibilites creatives. En combinant l'analyse de frequences avec Canvas, vous pouvez creer des visualisations uniques qui reagissent au son en temps reel.

Les trois types de visualisation que nous avons vus (barres, forme d'onde, cercle radial) ne sont que le debut. Vous pouvez les combiner, ajouter des effets de particules, ou meme utiliser WebGL pour des rendus 3D.

🎨
Allez plus loin

Decouvrez nos effets interactifs bases sur l'audio dans notre bibliotheque d'effets, avec code copiable en un clic.