これはMDNにあるWeb Audio APIの使用で扱っているサンプルを少し簡単にしたものです。
Web Audio APIの理解や使い方の参考にしてください。
もっと簡単なやつが見たい方は 『Web Audio APIの超簡単なサンプル』をどうぞ!
以下のサンプルでは、Web Audio APIを使って音源の再生と一時停止、ボリュームコントロールを行っています。
Web Audio APIを使ってみる上での注意点
今回紹介するサンプルを自分で作ってPC上で index.html をダブルクリックしても動きません。
たぶんコンソール上に以下のようなメッセージが出力されます。
MediaElementAudioSource outputs zeroes due to CORS access restrictions for ...
今回のように音声ソースを扱うサイトの場合、セキュリティの関係上ブラウザ側でアクセス制限が掛かって動作しません。
サンプルソースを自分のPCで実行するには、VsCode のLive Server などの機能拡張を利用したり、ローカルサーバ上で動作確認したり、あるいは直接レンタルサーバーなどにアップロードして動作確認する必要があります。
ソースコード
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="main.js"></script>
<title>Web Audio APIの利用</title>
</head>
<body>
<p>Web Audio APIを利用した音源の再生と停止・音量調整</p>
<!-- 利用する音声ファイル -->
<audio src="maou_bgm_8bit29.mp3"></audio>
<!-- 再生/一時停止ボタン -->
<button data-playing="false" role="switch" aria-checked="false">
<span>Play/Pause</span>
</button>
<!-- ボリューム調整バー -->
<p>Volume<input type="range" name="" id="volume" min="0" max="2" value="1" step="0.01" data-action="volume"></p>
</body>
</html>
main.js
// Web Audio APIの簡単なサンプル
/*
参考
Web Audio API入門 | MDN
https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API
Web Audio API の使用 | MDN
https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API
*/
window.addEventListener("load", ()=>{
// 古いブラウザ向けの設定
const AudioContext = window.AudioContext || window.webkitAudioContext;
// 音声コンテキスト作成
const audioContext = new AudioContext();
// 音声ファイル(入力元)を取得
const audio = document.querySelector("audio");
// 音声コンテキストに音声ファイルを設定する
const track = audioContext.createMediaElementSource(audio);
// PLAY/PAUSEボタン取得
const playButton = document.querySelector("button");
// PLAY/PAUSEボタンを押した時の処理
playButton.addEventListener(
"click",
function(){
// 音声(audioContext)が中断状態かどうかチェックする(中断であれば再開する)
if(audioContext.state === "suspended"){
audioContext.resume();
}
// data-set: playingの状態により再生と一時停止を制御
if(this.dataset.playing === "false"){
audio.play(); // 再生
this.dataset.playing = "true";
}
else if(this.dataset.playing === "true"){
audio.pause(); // 一時停止
this.dataset.playing = "false";
}
},
false
);
// 再生が終了したときの処理
audio.addEventListener(
"ended",
()=>{
playButton.dataset.playing = "false";
},
false
);
// 音量調整コンテキスト作成
const gainNode = audioContext.createGain();
// 音量調整バーを取得
const volumeControl = document.querySelector("[data-action='volume']");
// 音量調整をしたときの処理
volumeControl.addEventListener(
"input",
function(){
gainNode.gain.value = this.value;
},
false
);
// 設定済みの音声ファイルの音声コンテキストを音量コントロールと出力先(スピーカー)に接続
track.connect(gainNode).connect(audioContext.destination);
});
簡単な解説
HTML部分(index.html)
再生する音声ファイルはaudioタグとして記述しています。
<audio src="maou_bgm_8bit29.mp3"></audio>
このタグはmaou_bgm_8bit29.mp3という音声ファイルを読み込むためにだけ使っています。よって画面上には表示されない要素です。
今回使ったこのかわいい音声ファイルは、以下の魔王魂のサイトから自由に利用できます。
ボタンは再生と一時停止に利用するため、表示文字列をPlay/Pauseとしています。このPlay/Pauseの文字列はあくまでボタンの見た目です。
<button data-playing="false" role="switch" aria-checked="false">
<span>Play/Pause</span>
</button>
buttonタグに、再生と一時停止の状態を表す要素としてdata-playing=”false”を設定しています。
data-playingがtrueの場合を再生中、falseの場合を一時停止中として後述するJavaScript側で実装するようにします。
ボリュームコントロールはinputタグのrangeタイプとしてスライダー表示にしています。
<p>Volume<input type="range" name="" id="volume" min="0" max="2" value="1" step="0.01" data-action="volume"></p>
max=”2” となっていますが、Web Audio API自体のボリューム要素の数値は-3.4~3.4の範囲とされています。とは言え、0でミュートとなるので実際にはボリュームは0~3.4の範囲になるかと思います。
ここでいうmax=”2″の意味は、MDNの説明によると元の音量の2倍という意味になります。
この辺りの数値は動作確認後に適当に変更してみてください。
data-action=”volume”の項目は、JavaScript側からのDOM取得のために利用しているだけですので、id=”volume”などとしてDOM取得しても問題はありません。
JavaScript部分(main.js)
最初の記述は旧いブラウザに対応するための記述です。
最近のブラウザ(2024年時点)であれば必要ないと思われます。
const AudioContext = window.AudioContext || window.webkitAudioContext;
実際に上記の行をコメントアウトしても、わたしの利用しているChrome(バージョン: 124.0.6367.62)では動作しました。
Web Audio APIを使って音を鳴らすには、まずこのAudioContextのインスタンスを作成する必要があります。
// 音声コンテキスト作成
const audioContext = new AudioContext();
AudioContextのインスタンスに対して、音声ファイルを設定し、音量を設定し、出力先を設定することでWeb Audio APIを使った再生の準備が整います。Web Audio APIの重要な考え方は、AudioContextのインスタンスを通して全ての操作を行うということです。
まず音声ファイルの設定です。
// 音声ファイル(入力元)を取得
const audio = document.querySelector("audio");
// 音声コンテキストに音声ファイルを設定する
const track = audioContext.createMediaElementSource(audio);
index.htmlに記述されたaudioタグのDOM取得をしてから、AudioContextのメソッドであるcreateMediaElementSourceを使ってaudioContextの音声ファイルに設定しています。
今回のサンプルでは、ボタンイベントにより再生と一時停止を制御しています。
しかしこの部分の処理はWeb Audio APIとはほとんど関係がありません。従来のaudioタグを再生させるものとほぼ同じですが、1か所Web Audio APIと関係がありますので解説します。
再生用のボタンタグのDOM取得をします。
// PLAY/PAUSEボタン取得
const playButton = document.querySelector("button");
PLAY/PAUSEボタンを押した時の処理です。
// PLAY/PAUSEボタンを押した時の処理
playButton.addEventListener(
"click",
function(){
// 音声(audioContext)が中断状態かどうかチェックする(中断であれば再開する)
if(audioContext.state === "suspended"){
audioContext.resume();
}
// data-set: playingの状態により再生と一時停止を制御
if(this.dataset.playing === "false"){
audio.play(); // 再生
this.dataset.playing = "true";
}
else if(this.dataset.playing === "true"){
audio.pause(); // 一時停止
this.dataset.playing = "false";
}
},
false
);
最初のif文にある audioContext.state === “suspended” の意味は、audioContextが中断された状態にあるかどうかのチェックです。
audioContext.stateの状態が running でないと音を再生できません。
これは自動再生ブロックの問題があるため記述されています。
再生と一時停止の制御は、buttonタグのdata-playingに設定した値を使って切り替えています。
data-playingがtrueなら再生中、falseなら一時停止中を表すようにしてボタンを押すたびに切り替えます。
// data-set: playingの状態により再生と一時停止を制御
if(this.dataset.playing === "false"){
audio.play(); // 再生
this.dataset.playing = "true";
}
else if(this.dataset.playing === "true"){
audio.pause(); // 一時停止
this.dataset.playing = "false";
}
再生と一時停止はあくまでaudio要素としてaudio.play()、audio.pause()などと行っている点に注目してください。audioContextの状態はあくまで変化せずaudioの状態を変化させています。
例えば、audioContext.play() などとはできないのです。
音声が再生終了したときは、ボタンを押す押さないにかかわらず一時停止状態とするようにしなければ挙動がおかしくなってしまいます。
これはaudioオブジェクトの再生が終了したというイベントであるendedイベントに設定することで制御します。
// 再生が終了したときの処理
audio.addEventListener(
"ended",
()=>{
playButton.dataset.playing = "false";
},
false
);
endedイベント発生時にdata-playingをfalseとして一時停止状態に変化させています。
次に音量の設定をaudioContextに対して行います。
AudioContextのcreateGainメソッドを使うと音量調整が出来る様になります。
// 音量調整コンテキスト作成
const gainNode = audioContext.createGain();
inputタグに指定した[data-action=’volume’]を使って音量調整用のスライダーのDOM取得をしています。
// 音量調整バーを取得
const volumeControl = document.querySelector("[data-action='volume']");
スライダーを変化させたときのイベントはinputイベントです。
// 音量調整をしたときの処理
volumeControl.addEventListener(
"input",
function(){
gainNode.gain.value = this.value;
},
false
);
スライダーの現在値をgainNode.gain.valueに設定することでAudioContextに対して音量調整が出来ます。
最後にこれまでAudioContextインスタンスであるaudioContext変数に対して、音量設定と出力先(基本的にはスピーカー)を設定して完了です。
// 設定済みの音声ファイルの音声コンテキストを音量コントロールと出力先(スピーカー)に接続
track.connect(gainNode).connect(audioContext.destination);
上記の記述を見ると分かりますが、connect メソッドはつなげて記述ができます。
もし、音量コントロールが不要なら以下のように直接スピーカーに接続するように記述してもいいわけです。
track.connect(audioContext.destination);
参考
この記事はMDNの以下を参考に記述しました。
今回のサンプルをもっとシンプルにしたものが以下にあります。
コメント