2.

HTML5 <audio> 要素の使い方と autoplay / 複数 source / Web Audio API

編集
この記事の要点
  • <audio controls src="..."></audio> で音声を再生
  • <source> で複数フォーマット指定(mp3 / ogg / wav / aac)→ ブラウザが対応できる最初の 1 つを使用
  • autoplay は制限あり: モバイル / Chrome / Safari はユーザ操作なし自動再生不可muted 併用なら可
  • JavaScript API: .play() / .pause() / .currentTime / .volume / .duration
  • 高度な処理は Web Audio API(エフェクト・解析)、MSE(ストリーミング)

audio 要素の基本

HTML5 で導入。プラグイン不要で音声を Web ページに埋め込めます。

<!-- 最もシンプル: controls 付きで -->
<audio controls src="music.mp3"></audio>

<!-- 複数フォーマット対応(推奨) -->
<audio controls>
  <source src="music.mp3" type="audio/mpeg">
  <source src="music.ogg" type="audio/ogg">
  <source src="music.wav" type="audio/wav">
  <p>お使いのブラウザは audio タグに対応していません。
    <a href="music.mp3">音声ファイル</a>をダウンロードしてください。
  </p>
</audio>

<!-- 属性盛りだくさん -->
<audio
  controls
  autoplay
  muted
  loop
  preload="metadata"
  src="bgm.mp3"
  id="bgm">
</audio>

属性一覧

属性意味
src音声ファイル URL(<source> 無しのとき)
controlsブラウザ標準の再生 UI を表示
autoplay自動再生(多くのブラウザで制限あり)
loop繰り返し再生
mutedミュート初期状態
preloadnone / metadata / auto
crossoriginCORS 用 (anonymous / use-credentials)

主要フォーマットの対応状況

形式MIMEChromeFirefoxSafariEdge
MP3audio/mpeg
AACaudio/aac
Ogg Vorbisaudio/ogg×
Opusaudio/ogg; codecs=opus○ (14+)
WAVaudio/wav
FLACaudio/flac
WebM (Vorbis/Opus)audio/webm

最大公約数は MP3。容量効率を取るなら Opus(Safari 14+ 対応で可用に)。

autoplay の制限

ユーザの意図しない音声再生を防ぐため、ブラウザは autoplay を厳しく制限しています:

Chrome / Edge:
  - muted 付き autoplay: OK
  - 音声付き autoplay: ユーザがサイトを「よく訪問する」と判断されたときのみ
    (Media Engagement Index による)
  - iframe 内: allow=&quot;autoplay&quot; 属性必要

Safari (macOS / iOS):
  - 音声付き autoplay: 原則 NG
  - muted autoplay: OK
  - ユーザのクリック後なら可

Firefox:
  - サイトごとに許可設定
  - デフォルトは muted のみ許可
<!-- ✅ どこでも動く: muted で起動、ボタンで unmute -->
<audio id="bgm" autoplay muted loop src="bgm.mp3"></audio>
<button id="unmute">音量オン</button>

<script>
  document.getElementById('unmute').addEventListener('click', () => {
    const a = document.getElementById('bgm');
    a.muted = false;
  });
</script>

JavaScript API

const audio = document.querySelector('#bgm');

// 再生 / 一時停止
audio.play();          // Promise を返す(autoplay 制限で reject の可能性)
audio.pause();

// シーク
audio.currentTime = 60;     // 60 秒地点へ
console.log(audio.duration); // 総再生時間(秒)

// 音量 / 速度
audio.volume = 0.5;     // 0.0 ~ 1.0
audio.playbackRate = 1.5;  // 1.5 倍速
audio.muted = true;

// 状態
console.log(audio.paused);   // 一時停止中か
console.log(audio.ended);    // 再生終了したか
console.log(audio.readyState); // 0-4

// 再生 Promise を扱う
try {
    await audio.play();
} catch (err) {
    console.warn('再生失敗:', err);
    // → 多くは autoplay policy 違反
}

イベント

const a = document.querySelector('audio');

a.addEventListener('loadedmetadata', () => console.log('長さ:', a.duration));
a.addEventListener('canplay', () => console.log('再生可能'));
a.addEventListener('play', () => console.log('再生開始'));
a.addEventListener('pause', () => console.log('一時停止'));
a.addEventListener('ended', () => console.log('再生終了'));
a.addEventListener('timeupdate', () => {
    document.querySelector('#current').textContent = a.currentTime.toFixed(1);
});
a.addEventListener('error', () => console.error('エラー:', a.error));
a.addEventListener('waiting', () => console.log('バッファリング中'));
a.addEventListener('volumechange', () => console.log('音量:', a.volume));

カスタム UI を作る

<audio id="track" src="song.mp3"></audio>
<button id="playPause">▶</button>
<input type="range" id="seek" min="0" max="100" value="0">
<span id="time">0:00 / 0:00</span>

<script>
const track = document.getElementById('track');
const btn = document.getElementById('playPause');
const seek = document.getElementById('seek');
const time = document.getElementById('time');

btn.onclick = () => {
    if (track.paused) {
        track.play();
        btn.textContent = '⏸';
    } else {
        track.pause();
        btn.textContent = '▶';
    }
};

track.ontimeupdate = () => {
    seek.value = (track.currentTime / track.duration) * 100;
    time.textContent = formatTime(track.currentTime) + ' / ' + formatTime(track.duration);
};

seek.oninput = () => {
    track.currentTime = (seek.value / 100) * track.duration;
};

function formatTime(sec) {
    const m = Math.floor(sec / 60);
    const s = Math.floor(sec % 60).toString().padStart(2, '0');
    return `${m}:${s}`;
}
</script>

Web Audio API でエフェクト

音量調整・イコライザ・解析など高度な処理は Web Audio API を使います:

const audioCtx = new AudioContext();
const audio = document.querySelector('audio');
const source = audioCtx.createMediaElementSource(audio);

// 音量を上げる
const gain = audioCtx.createGain();
gain.gain.value = 1.5;

// FFT 解析(ビジュアライザ用)
const analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;

source.connect(gain).connect(analyser).connect(audioCtx.destination);

// 周波数データ取得
const buf = new Uint8Array(analyser.frequencyBinCount);
function draw() {
    analyser.getByteFrequencyData(buf);
    // buf を canvas に描画 → ビジュアライザ完成
    requestAnimationFrame(draw);
}
draw();

// 再生開始(ユーザ操作後に呼ぶ)
audio.play();
audioCtx.resume();   // Safari 等で必要

ストリーミング(MSE)

Media Source Extensions を使うと、JS から音声チャンクを供給できます。HLS / DASH 配信に必須:

const mediaSource = new MediaSource();
const audio = document.querySelector('audio');
audio.src = URL.createObjectURL(mediaSource);

mediaSource.addEventListener('sourceopen', async () => {
    const sb = mediaSource.addSourceBuffer('audio/mpeg');
    const chunks = await fetchChunks();   // 自前で取得
    for (const chunk of chunks) {
        sb.appendBuffer(chunk);
        await new Promise(r => sb.addEventListener('updateend', r, {once:true}));
    }
    mediaSource.endOfStream();
});

// HLS は hls.js ライブラリ利用が一般的
// import Hls from 'hls.js';
// const hls = new Hls();
// hls.loadSource('stream.m3u8');
// hls.attachMedia(audio);

アクセシビリティ

  • controls を出して、キーボード操作可能に
  • 字幕付き音声なら <track>(ただし audio 要素では公式サポート外、video のみ)→ 代替テキストを近くに置く
  • 背景音楽の自動再生は避ける(音響過敏症の方への配慮)
  • テキスト書き起こしを併設すると検索性も a11y も向上

FAQ

Q: play() が rejected されるのはなぜ?
A: autoplay policy 違反です。ユーザのクリック等のジェスチャ後に呼ぶか、muted 状態で開始してください。

Q: ファイルが大きくて遅い
A: preload="metadata" でメタデータだけ先読み、Opus / AAC でサイズ削減、CDN を使う、Range リクエストで部分配信を有効化。

Q: iOS Safari で動かない
A: ① ユーザ操作後に play() ② muted 初期化 ③ preload="auto" 試行。それでもダメなら HLS でのストリーミング検討。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. video要素
  2. audio要素
  3. source要素
  4. track要素
  5. embed要素

最近更新/作成されたページ