L'API Web Audio en JavaScript
Apprenez l'API Web Audio JavaScript : créez un graphe audio avec AudioContext et AudioNodes, chargez des sons, contrôlez le volume, générez des tonalités et gérez la politique d'autoplay du navigateur.
La Web Audio API vous permet de générer, charger, traiter et lire du son directement dans le navigateur — sans aucun plugin. Ce guide vous présente ses éléments fondamentaux : comment créer un contexte audio, charger et lire des fichiers sonores, contrôler le volume, générer des tonalités avec un oscillateur, et contourner la politique d'autoplay du navigateur. Chaque exemple est court et autonome, prêt à être intégré dans une page pour entendre le résultat immédiatement.
Introduction à la Web Audio API
La Web Audio API est une API JavaScript destinée au traitement et à la synthèse audio dans les applications web. Contrairement à un simple élément <audio> — qui ne fait que lire un fichier du début à la fin — la Web Audio API vous offre un graphe de nœuds connectés qui acheminent, mélangent et transforment le son en temps réel. C'est l'outil idéal pour les jeux, les applications musicales, les synthétiseurs et les visualiseurs audio.
Penser en termes de graphes audio
Dans la Web Audio API, chaque son transite par une chaîne de nœuds, d'une source vers une destination :
source → (effets) → destination
(fichier, (gain, (vos
oscillateur) filtre) haut-parleurs)Les trois concepts que vous rencontrerez en premier :
- AudioContext — le conteneur qui gère l'ensemble du graphe et l'horloge audio. Vous en créez un par page et le réutilisez.
- AudioNode — une unité de traitement modulaire. Les nœuds sources produisent du son (un buffer ou un oscillateur), les nœuds d'effet le transforment (gain, filtre, panoramique), et le nœud destination l'envoie vers les haut-parleurs.
- AudioBuffer — des données audio décodées en mémoire, idéales pour les sons courts (effets, échantillons) que vous déclenchez répétitivement avec une synchronisation précise.
Vous construisez un graphe en appelant node.connect(otherNode). L'audio se termine toujours à audioContext.destination.
Premiers pas avec la Web Audio API
Pour travailler avec l'audio, vous commencez par créer un AudioContext, qui sert de conteneur à votre graphe audio.
Créer un AudioContext
const audioContext = new (window.AudioContext || window.webkitAudioContext)();Ceci initialise un nouvel AudioContext. Le fallback webkit couvre les anciennes versions de Safari ; les navigateurs modernes prennent en charge AudioContext directement, sans préfixe.
Attention à la politique d'autoplay. Les navigateurs créent le contexte dans un état
"suspended"et refusent de jouer du son tant que l'utilisateur n'a pas interagi avec la page (un clic ou une pression de touche). Reprenez toujours le contexte dans un gestionnaire d'événements avant de lancer la lecture :button.addEventListener("click", async () => { if (audioContext.state === "suspended") { await audioContext.resume(); } // ...la lecture peut maintenant commencer en toute sécurité });Si l'audio est muet sans erreur dans la console, un contexte non repris est la cause la plus fréquente.
Chargement et lecture audio
Pour lire un fichier sonore, vous le chargez dans un AudioBuffer, puis vous connectez un nœud source au contexte pour la lecture.
Chargement de fichiers audio
Cette fonction utilise la Fetch API et async/await pour télécharger le fichier et le décoder :
async function loadAudioFile(url, audioContext) {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
return audioBuffer;
}La fonction récupère le fichier, le lit comme un ArrayBuffer brut, puis le transmet à decodeAudioData, qui décompresse des formats comme MP3, WAV ou OGG en un AudioBuffer prêt à l'emploi. Le décodage s'effectue en dehors du thread principal et retourne une promesse, donc utilisez await.
Lecture de l'audio chargé
function playAudio(audioBuffer, audioContext) {
const sourceNode = audioContext.createBufferSource();
sourceNode.buffer = audioBuffer;
sourceNode.connect(audioContext.destination);
sourceNode.start();
}Cette fonction crée un BufferSourceNode, le pointe vers le buffer décodé, le connecte aux haut-parleurs (audioContext.destination), et démarre la lecture.
Un nœud source est à usage unique. Un
AudioBufferSourceNodene peut être démarré qu'une seule fois — une fois arrêté, vous devez en créer un nouveau pour rejouer le même buffer. L'AudioBufferlui-même est réutilisable, alors conservez le buffer et recréez le nœud source (peu coûteux) à chaque lecture :// ❌ Lève une exception après la première lecture : "cannot call start more than once" // sourceNode.start(); // sourceNode.start(); // ✅ Un nouveau nœud source à chaque lecture function playOnce(buffer, ctx) { const src = ctx.createBufferSource(); src.buffer = buffer; src.connect(ctx.destination); src.start(); }
Manipulation de l'audio
La Web Audio API révèle tout son potentiel lorsque vous insérez des nœuds d'effet entre la source et la destination. Le plus courant est le nœud de gain pour le contrôle du volume.
Créer un nœud de gain
function createGainNode(audioContext, volume) {
const gainNode = audioContext.createGain();
gainNode.gain.value = volume; // 1 = volume maximal, 0 = silence, 0.5 = moitié
return gainNode;
}Un GainNode multiplie le signal par sa valeur gain. La propriété gain est un AudioParam, ce qui signifie que vous pouvez aussi planifier des changements progressifs dans le temps (pour les fondus) plutôt que de définir une valeur brusquement :
// Fade from silent to full volume over 2 seconds, avoiding clicks/pops
gainNode.gain.setValueAtTime(0, audioContext.currentTime);
gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 2);Connexion de nœuds pour les effets audio
function applyEffects(audioBuffer, volume, audioContext) {
const sourceNode = audioContext.createBufferSource();
sourceNode.buffer = audioBuffer;
const gainNode = createGainNode(audioContext, volume);
// source → gain → destination
sourceNode.connect(gainNode);
gainNode.connect(audioContext.destination);
sourceNode.start();
}Ce code construit un graphe à trois nœuds : la source alimente le nœud de gain, et ce dernier alimente la destination. Insérez d'autres nœuds d'effet de la même manière — par exemple un BiquadFilterNode pour la mise en forme du timbre :
const filter = audioContext.createBiquadFilter();
filter.type = "lowpass"; // let low frequencies through, cut highs
filter.frequency.value = 800; // cutoff in Hz
sourceNode.connect(filter);
filter.connect(gainNode);
gainNode.connect(audioContext.destination);L'ordre est important : le signal circule dans le sens de vos appels connect.
Un exemple fonctionnel : un générateur de tonalités
Pour une démo autonome ne nécessitant aucun fichier audio, voici un générateur de tonalités construit à partir d'un oscillateur. Il gère également la politique d'autoplay en reprenant le contexte au premier clic.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Simple Tone Generator</title>
</head>
<body>
<h1>Simple Tone Generator</h1>
<button onclick="playTone()">Play Tone</button>
<button onclick="stopTone()">Stop Tone</button>
<script>
let audioContext;
let oscillator;
async function playTone() {
if (!audioContext) {
audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
}
// Satisfy the autoplay policy: resume on user gesture
if (audioContext.state === "suspended") {
await audioContext.resume();
}
if (!oscillator) {
oscillator = audioContext.createOscillator();
oscillator.type = "sine"; // Sine wave — other values are 'square', 'sawtooth', 'triangle'
oscillator.frequency.setValueAtTime(440, audioContext.currentTime); // A4 note, 440 Hz
oscillator.connect(audioContext.destination);
oscillator.start();
}
}
function stopTone() {
if (oscillator) {
oscillator.stop();
oscillator.disconnect();
oscillator = null; // Reset the oscillator to allow a new one to be created next time
}
}
</script>
</body>
</html>Fonctionnement :
- Nœud oscillateur — génère une onde sinusoïdale pure à 440 Hz (la note La4 utilisée pour l'accordage). Les autres valeurs de
typesont"square","sawtooth"et"triangle", chacune avec un timbre différent. - Fonctions de contrôle —
playTonereprend le contexte et démarre l'oscillateur ;stopTonel'arrête, le déconnecte et réinitialise la variable afin qu'un nouvel oscillateur puisse être créé lors de la prochaine utilisation. - Pourquoi réinitialiser
oscillator = null? Comme un nœud source de buffer, un oscillateur est à usage unique — une fois arrêté, il ne peut pas être redémarré, donc vous en créez un nouveau pour la prochaine tonalité.
Quand utiliser la Web Audio API
| Cas d'usage | À privilégier… |
|---|---|
| Lire une piste de fond ou un podcast | Un élément <audio> simple — plus facile, moins de code |
| Effets sonores dans un jeu avec synchronisation précise | Web Audio API + AudioBuffer |
| Contrôle du volume, fondus, filtres, panoramique | Nœuds gain/filtre/panoramique de la Web Audio API |
| Synthétiseurs et tonalités générées | OscillatorNode de la Web Audio API |
| Visualiseurs de forme d'onde/fréquence en temps réel | AnalyserNode de la Web Audio API |
Si vous avez seulement besoin de démarrer/arrêter la lecture, l'élément <audio> suffit. Choisissez la Web Audio API dès que vous avez besoin de traitement, de synchronisation ou de synthèse.
Conclusion
La Web Audio API transforme le navigateur en une table de mixage programmable : vous câblez un graphe de nœuds depuis une source, à travers des effets, jusqu'aux haut-parleurs, et contrôlez chaque étape en temps réel. Retenez ces points essentiels :
- Créez un seul
AudioContextet reprenez-le lors d'un geste utilisateur avant de lancer la lecture. - Réutilisez les
AudioBuffers, mais créez un nouveau nœud source/oscillateur pour chaque lecture. - Construisez des effets en chaînant les nœuds avec
connect(), en terminant toujours àaudioContext.destination.
Pour aller plus loin, explorez des fonctionnalités du navigateur comme la Web MIDI API pour connecter des instruments de musique, ou la Web Animations API pour synchroniser les visuels avec votre audio.