Web audio has two distinct use cases with very different requirements. Streaming audio (music, podcasts, voice) prioritizes file size and broad compatibility. Interactive audio (sound effects, game audio, notifications) prioritizes low latency and instant playback. The format you choose depends on which category you're serving.

This guide covers both paths: the <audio> element for streaming content and the Web Audio API for interactive use, with format recommendations for each.

Audio Format Comparison

FormatCodecCompressionBrowser SupportQuality at 128kbpsBest For
MP3MPEG-1 Layer IIILossy100%GoodUniversal audio, podcasts
AACAdvanced Audio CodingLossy100%BetterMusic streaming, Apple ecosystem
OpusOpus (IETF)Lossy96%+ExcellentWebRTC, voice, high-quality streaming
OGG (Vorbis)VorbisLossyChrome, Firefox, EdgeGoodOpen-source projects
WAVPCM (uncompressed)None100%Perfect (lossless)Sound effects, Web Audio API
FLACFLACLosslessChrome, Firefox, Edge, Safari 11+Perfect (lossless)Hi-fi streaming, archival
WebM (Opus)Opus in WebM containerLossyChrome, Firefox, EdgeExcellentWebRTC recordings

The short version: Use MP3 for maximum compatibility. Use Opus when you can (96%+ support, best quality-per-bit). Use WAV for interactive sound effects that need instant playback.

The

The <audio> element works like <video><source> elements provide format fallback.

<audio controls preload="metadata">
  <source src="track.opus" type="audio/opus">
  <source src="track.m4a" type="audio/mp4">
  <source src="track.mp3" type="audio/mpeg">
  <p>Your browser doesn't support audio. <a href="track.mp3">Download the track</a>.</p>
</audio>

Preload options:

  • none — Best for pages with many audio elements. No data fetched until play.
  • metadata — Downloads duration and other metadata (~10-50KB). Good default.
  • auto — Browser decides how much to buffer. Only use for the primary audio player on a page.

Styling the audio player: The default player varies wildly across browsers and can't be restyled with CSS. For custom UI, hide the default controls and build your own using the HTMLAudioElement API:

const audio = new Audio('track.mp3');

// Custom play/pause
playBtn.addEventListener('click', () => {
  audio.paused ? audio.play() : audio.pause();
});

// Progress tracking
audio.addEventListener('timeupdate', () => {
  const progress = audio.currentTime / audio.duration;
  progressBar.style.width = `${progress * 100}%`;
});

// Duration display
audio.addEventListener('loadedmetadata', () => {
  durationDisplay.textContent = formatTime(audio.duration);
});

Web Audio API for Interactive Audio

The Web Audio API provides low-level audio processing for games, music apps, visualizations, and any use case where the <audio> element's simple play/pause isn't enough.

// Create audio context (one per page)
const ctx = new AudioContext();

// Load and decode an audio file
async function loadSound(url) {
  const response = await fetch(url);
  const arrayBuffer = await response.arrayBuffer();
  return ctx.decodeAudioData(arrayBuffer);
}

// Play a sound effect
async function playEffect() {
  const buffer = await loadSound('/sounds/click.wav');
  const source = ctx.createBufferSource();
  source.buffer = buffer;
  source.connect(ctx.destination);
  source.start(0);
}

// Play with volume control
async function playWithVolume(url, volume = 0.5) {
  const buffer = await loadSound(url);
  const source = ctx.createBufferSource();
  const gain = ctx.createGain();
  gain.gain.value = volume;
  source.buffer = buffer;
  source.connect(gain).connect(ctx.destination);
  source.start(0);
}

Format choice for Web Audio API: Use WAV for short sound effects (under 5 seconds). WAV files don't need decoding — the raw PCM data goes straight to the audio buffer. For longer audio processed through the API, use MP3 or Opus — the browser decodes them during decodeAudioData().

AudioContext restrictions: Browsers require a user gesture (click, tap, keypress) before creating or resuming an AudioContext. This prevents pages from playing sound without user interaction.

// Resume context on first user interaction
document.addEventListener('click', () => {
  if (ctx.state === 'suspended') ctx.resume();
}, { once: true });

Bitrate Recommendations by Use Case

Use CaseFormatBitrateFile Size (1 min)
Voice/podcastMP3 or Opus64-96kbps0.5-0.7MB
Background musicMP3 or AAC128kbps0.96MB
Music (casual listening)AAC or Opus128-160kbps0.96-1.2MB
Music (high quality)Opus or AAC192-256kbps1.4-1.9MB
Sound effects (<5s)WAV1411kbps (CD quality)10.6MB (but clips are short)
Lossless streamingFLAC~800-1200kbps6-9MB

Voice vs music: Voice audio has much less frequency content than music, so it compresses extremely well. A podcast at 64kbps Opus sounds clean because the codec only needs to represent speech frequencies (300Hz-3.4kHz primarily). Music at 64kbps sounds muddy because the codec is struggling to represent the full 20Hz-20kHz range.

Embedding Podcasts and Long-Form Audio

For podcast or long-form audio players, the key considerations are streaming (don't force full download before play) and seeking (let users jump to any point).

<audio controls preload="metadata" style="width: 100%">
  <source src="episode.mp3" type="audio/mpeg">
</audio>

Streaming works automatically with MP3 and AAC when served from a CDN that supports Range requests. The browser downloads in chunks and can seek to any position without downloading everything before it. Most CDNs and static hosts support Range requests by default.

MP3 is the universal podcast format. Every podcast player, every directory (Apple Podcasts, Spotify, Google Podcasts), and every browser supports MP3. Don't use Opus or OGG for podcast distribution — many players won't recognize them.

Encoding for podcasts:

# Mono voice podcast (smallest file size)
ffmpeg -i recording.wav -c:a libmp3lame -q:a 6 -ac 1 episode.mp3
# Result: ~80kbps VBR mono, ~0.6MB per minute

# Stereo music podcast
ffmpeg -i recording.wav -c:a libmp3lame -q:a 4 -ac 2 episode.mp3
# Result: ~165kbps VBR stereo, ~1.2MB per minute

Sound Effects for Web Applications

UI sound effects (button clicks, notifications, transitions) need two things: small file size and instant playback. The Web Audio API with pre-loaded buffers delivers both.

// Sound effect manager
class SoundManager {
  constructor() {
    this.ctx = new AudioContext();
    this.buffers = new Map();
  }

  async load(name, url) {
    const res = await fetch(url);
    const buf = await res.arrayBuffer();
    this.buffers.set(name, await this.ctx.decodeAudioData(buf));
  }

  play(name, volume = 1.0) {
    if (this.ctx.state === 'suspended') this.ctx.resume();
    const buffer = this.buffers.get(name);
    if (!buffer) return;
    const source = this.ctx.createBufferSource();
    const gain = this.ctx.createGain();
    gain.gain.value = volume;
    source.buffer = buffer;
    source.connect(gain).connect(this.ctx.destination);
    source.start(0);
  }
}

// Usage
const sounds = new SoundManager();
await sounds.load('click', '/sounds/click.wav');
await sounds.load('success', '/sounds/success.wav');

btn.addEventListener('click', () => sounds.play('click', 0.3));

Format for sound effects: Use WAV (16-bit, 44.1kHz) for clips under 2 seconds — they're typically 50-200KB and decode instantly. For longer effects (ambient loops, music stings), use Opus or MP3 to reduce download size. Pre-load all sound effects on page load so they play without network latency.

Audio Encoding and Format Conversion

FFmpeg handles all audio format conversions:

# WAV to MP3 (VBR, high quality)
ffmpeg -i input.wav -c:a libmp3lame -q:a 2 output.mp3

# WAV to Opus (best quality-per-bit)
ffmpeg -i input.wav -c:a libopus -b:a 128k output.opus

# WAV to AAC
ffmpeg -i input.wav -c:a aac -b:a 128k output.m4a

# FLAC to MP3 (lossless to lossy)
ffmpeg -i input.flac -c:a libmp3lame -q:a 4 output.mp3

# Extract audio from video
ffmpeg -i video.mp4 -vn -c:a libmp3lame -q:a 4 audio.mp3

Or use ChangeThisFile for browser-based conversions: WAV to MP3 | FLAC to MP3 | OGG to MP3 | AAC to MP3 | MP4 to MP3

Web audio format selection follows a simple rule: MP3 for compatibility, Opus for quality, WAV for latency. Most web applications only need one of these three. Pick based on your use case, encode at the recommended bitrate, and handle the AudioContext user-gesture requirement if using the Web Audio API.

For format conversions, ChangeThisFile supports all major audio format pairs — WAV to MP3, FLAC to MP3, MP3 to OGG, and dozens more. Convert in the browser when possible (files never leave your device) or server-side for larger files.