Web ブラウザ上でマイクからシンプルに Web Audio API で録音・再生するメモ

Web ブラウザ上でマイクからシンプルに Web Audio API で録音・再生するメモ

Web ブラウザ上でマイクからシンプルに Web Audio API で録音・再生するメモです。

背景

WebXR をするときに音声の録音・再生もやってみたい時があり、Recorderjs のような、なにかしらのライブラリはあえて使わずに、できるだけ標準の Web Audio API を使った実装をやってみたくなったので、やってみます。

2025/03/24 時点の情報で Chrome ブラウザで表示する形で試しています。

参考サイト

MediaRecorder - Web API | MDN

やはり MDN さんの記事が助けになりました。

実際のソース

このような UI です。録音開始ボタン、録音停止ボタン、音データ再生プレイヤー、ステータス表示(現在は未録音)があります。

以下がソースです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>シンプルな録音デモ</title>
  <style>
    body { font-family: sans-serif; margin: 20px; }
    button, audio, #status { margin: 5px; vertical-align: middle; }
  </style>
</head>
<body>
  <h1>録音デモ</h1>
  <button id="recordBtn">録音開始</button>
  <button id="stopBtn" disabled>録音停止</button>
  <audio id="audioPlayback" controls></audio>
  <div id="status">未録音</div>

  <script>

    let mediaRecorder = [];
    let stream = [];
    let recordedChunks = [];

    const recordBtn = document.getElementById("recordBtn");
    const stopBtn = document.getElementById("stopBtn");
    const audioPlayback = document.getElementById("audioPlayback");
    const statusDiv = document.getElementById("status");

    // 録音開始ボタンをクリックしたときの処理
    async function startRecording() {
      try {
        // MediaStream をオーディオのみの使用の宣言
        stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        // MediaRecorder 準備
        mediaRecorder = new MediaRecorder(stream);
        // 録音データをいったん集める配列
        recordedChunks = [];
        // 録音データがつどつど来た時の処理
        mediaRecorder.ondataavailable = event => {
          if (event.data && event.data.size > 0) {
            recordedChunks.push(event.data);
          }
        };
        // 録音終了処理
        mediaRecorder.onstop = () => {
          // データを Blob で記録し audioPlayback に渡す
          const blob = new Blob(recordedChunks, { type: "audio/webm" });
          audioPlayback.src = URL.createObjectURL(blob);
          // ステータスに報告
          statusDiv.textContent = "録音終了";
        };

        // 録音開始
        mediaRecorder.start();
        // UI 処理
        recordBtn.disabled = true;
        stopBtn.disabled = false;
        // ステータスに報告
        statusDiv.textContent = "録音中...";
      } catch (error) {
        // エラー処理
        console.error("録音開始に失敗しました:", error);
        statusDiv.textContent = "録音開始失敗";
      }
    }

    // 録音終了ボタンをクリックしたときの処理
    function stopRecording() {
      if (mediaRecorder && mediaRecorder.state === "recording") {
        // MediaRecorder 停止
        mediaRecorder.stop();
        // 対象のストリームに含まれるすべてのメディアトラックを停止
        stream.getTracks().forEach(track => track.stop());
        // UI 処理
        recordBtn.disabled = false;
        stopBtn.disabled = true;
      }
    }

    // クリックまわりの処理
    recordBtn.addEventListener("click", startRecording);
    stopBtn.addEventListener("click", stopRecording);
  </script>
</body>
</html>

これを、どこか HTTPS で動く場所で表示します。私の場合は GitHub Codespaces だと手軽に HTTPS 環境で試せるので、よく使っています。

このように録音開始をクリックすると MediaStream や MediaRecorder を準備して録音開始して、

録音終了をクリックするともろもろ停止して Audio Playback に録音したデータを再生するようにしています。

いままで MediaRecorder の仕様は把握していたものの、色々な記事や知見の寄せ集めでちょっと弱かったので、シンプルに組めるようになってよかったです。