howler.jsの使い方
[音声ファイルの再生・停止]

オーディオライブラリ「howler.js」

Web Audio APIベースのモダンブラウザ用オーディオライブラリ。
デフォルトはWeb Audio APIですが、対応していない場合はHTML5 Audioにフォールバックしてくれるので、どのブラウザでもJSから簡単にオーディオ操作を可能にしてくれます。

howlerjs.com

JSで音声ファイルを扱う案件があった時に、Web Audio APIをそのまま使ってみたのですが、実装方法によってはChromeでは音が出るけどSafariやiOS Safariでは音が出ないとか、ブラウザごとの対応がめちゃくちゃ面倒でした。その点、「howler.js」を使うと簡単なオプションですんなり思った通りのことができてどのブラウザでも問題なく使えて非常に便利でした。

howler.jsの使い方

まずは使うための準備。

公式ドキュメントはこちら

  • Githubリポジトリがあるので、そこからダウンロードして使う
  • npmやYarnでモジュールを開発環境にインストールして使う
  • CDNを読み込ませる

どの方法でもOKです。

僕はYarnを使っているので下記コマンドでインストールしました。

$ yarn add -D howler

CDNでお手軽に使いたい場合は下記のタグをお使いください。(※Ver2.2.0)

<script src="https://cdn.jsdelivr.net/npm/howler@2.2.0/dist/howler.min.js"></script>

この記事の執筆時点では最新版が2.2.0でしたので、それ以外のバージョンを使う場合のCDNのリンクは下記からどうぞ。

実際の導入については下記のような形式

<script src="https://cdn.jsdelivr.net/npm/howler@2.2.0/dist/howler.min.js"></script>
<script>
  var sound = new Howl({
    src: ['sound.mp3']
  });
  //再生ボタンを押すと再生
  const playButton = document.getElementById("js-play");
  playButton.addEventListener('click', () => {
    //'sound.mp3'を再生
    sound.play();
  });

  //停止ボタンを押すと停止
  const stopButton = document.getElementById("js-stop");
  stopButton.addEventListener('click', () => {
    //'sound.mp3'を停止
    sound.stop();
  });
</script>

僕はモジュールからWebpackでバンドルして使いたいので外部ファイル化して下記のような形で使います。

import {Howl, Howler} from 'howler';

const sound = new Howl({
  src: ['sound.mp3']
});

const playButton = document.getElementById("js-play");
playButton.addEventListener('click', () => {
  sound.play();
});

const stopButton = document.getElementById("js-stop");
stopButton.addEventListener('click', () => {
  sound.stop();
});

オプションについて

const sound = new Howl({
  //複数のファイル形式を指定可能。配列順に評価しそのブラウザが対応するファイル形式を再生します。
  src      : ['sound.webm', 'sound.mp3', 'sound.wav'],
  //自動再生
  autoplay : true,
  //ループ再生
  loop     : true,
  //音量 0〜1.0
  volume   : 0.5,
  //再生速度 0.5〜4.0 (1.0がデフォルト)
  rate     : 1.5,
  //再生開始位置と終了位置の秒数をミリ秒で指定
  sprite   : {
    /*
    * offset Number 再生開始位置(ミリ秒)
    * duration Number 終了位置(ミリ秒)
    * loop Boolean ループするかどうか。デフォルトはfalse。省略可
    */
    key1: [offset, duration, (loop)]
  },
  //再生終了時のコールバック
  onend    : () => {
    console.log('Finished!');
  }
});

//spriteを再生
sound.play('key1');

このような形式で音量設定やコールバック関数などオプションを追加できます。
オプションについては、ここに記載しているコードは一部です。ドキュメントにすべてのオプションについて記載がありますので必要なものを指定してください。英語ですが内容を翻訳すればだいたいわかります。コールバック関数にはすべてonが接頭辞としてついていますし、かなり豊富に用意されているので用途に合わせて使いやすいです。

Options | howler.js

メソッドについて

オプションで指定できるコールバック関数以外にも、便利なイベント・メソッドが用意されていますので、こちらを使えば再生・停止・フェードなどいろいろな挙動を合わせてやりたいことはほとんどできるんじゃないかなと思います。

Methods | howler.js

一部を例として紹介します。

任意の音源のみにメソッドを使う

各メソッドの説明の前に、最初に説明しておきたいのがこちら。
howler.jsでは音源を読み込むとIDで管理してくれます。公式ではそのIDを「sound ID」と呼んでいる様です。sound IDの取得方法は下記の通り。

const sound = new Howl({
  src: ['sound.mp3']
});
const soundId = sound.play();

play()メソッドで音声を再生した時の返り値で取得できます。
メソッドの中にはこのIDを指定することができるものが多くあり、そういったものはIDを指定することで指定した音源だけにメソッドを適用できます。省略するとすべての音源に対してメソッドを適用します。そのため、複数の音源を別々に扱う場合はsound IDの指定が必須となります。

const soundId1 = sound.play();
const soundId2 = sound.play();

sound.fade(1, 0, 1000, soundId1);  // 1つ目の音源はフェードアウト
sound.fade(0, 1, 1000, soundId1);  // 2つ目の音源はフェードイン

↑実際こんな挙動はさせないと思いますが、別々に扱う例として書きました。

以下、各メソッドの一部を説明していくのですが、引数にsound IDが入るものは音源を指定できるということになりますので参考までに。

オーディオの再生

play()メソッドを使います。引数にsound IDを入れることもできます。

sound.play();

オーディオの停止

stop()メソッドを使います。引数にsound IDを入れることもできます。

sound.stop();

ミュートにする

mute()メソッドで再生を停止せずに音だけ消すことができます。
第2引数にsound IDを入れることもできます。

sound.mute();

音量を調整する

volume()メソッドで音量を0 〜 1.0の間で調整できます。
インスタンス化する時にvolumeオプションでも指定可能ですが、メソッドの場合は任意のタイミングで引数を渡すことで音量を設定でき、引数を渡さなければ現在の音量が返り値となります。第2引数にsound IDを入れることもできます。

const sound = new Howl({
  src      : ['sound.webm', 'sound.mp3', 'sound.wav'],
  //インスタンス化するときにオプションで設定可能
  volume   : 0.5
});

//引数を渡すとその音量になる
sound.volume(1.0);
//引数がなければ現在の音量を取得できる
const currentVolume = sound.volume();
console.log(currentVolume); //現在の音量

ファイルの読み込み状態を取得する

state()メソッドでオーディオの読み込み状態をunloadedloadingloadedの3つから取得できます。オーディオはすべてダウンロードが終わった状態でないと再生できないので、ダウンロードされて再生される状態になっているのがloadedになります。

const currentState = sound.state();
console.log(currentState); //unload or loading or loaded

再生中/停止中のフラグを取得する

playing()メソッドでtrueなら再生中、falseなら停止中のフラグを取得できます。これを使うと下記のようなコードで二重再生などのバグを防ぐことができます。引数にsound IDを入れることもできます。

playAudioHandler(e){
  //再生中の時は停止
  if (sound.playing()){
    sound.stop();
  }
  //停止中の時は再生
  else{
    sound.play();
  }
}

オーディオの長さを取得する

duration()メソッドでオーディオの長さを秒単位で取得できます。
オーディオファイルが読み込まれるまでは常に0を返す点に注意です。
引数にsound IDを入れることもできます。

sound.duration(); // 0

sound.load(); //オーディオを読み込み
sound.duration(); //218.07020408163265 小数点以下まで細かく取得できます

再生速度を変更する

rate()メソッドを使うと再生速度を調整できます。
オプションでも指定できますが、任意のタイミングで変えたい時はこちらが使えます。第1引数に0.5〜4.0まで指定でき、デフォルトは1.0となっています。第2引数にsound IDを入れることもできます。

sound.rate(1.5);

また、引数を設定しなければ現在の再生速度を取得できます。

const currentRate = sound.rate();
console.log(currentRate); //現在の再生速度

再生位置を設定する

seek()メソッドでオーディオの再生開始位置を設定できます。
第1引数に秒単位で設定します。第2引数にsound IDを入れることもできます。

sound.seek(20); //20秒後から再生

また、引数を設定しなければ現在の再生位置を取得できます。

const currentSeek = sound.seek();
console.log(currentSeek) //現在の再生位置

オーディオを読み込む

load()メソッドはデフォルトで呼び出されるが、duration()のようにファイルの読み込みが必須の場合や、preloadfalseに設定した場合は、オーディオを再生する前に呼び出す必要があります。

const sound = new Howl({
  src      : ['sound.webm', 'sound.mp3', 'sound.wav'],
  //preloadがtrueの場合はインスタンス化した時点でファイルを読み込む(デフォルトはtrue)任意のタイミングで読み込ませたい場合はfalseを指定しておく
  preload  : false
});

sound.play(); //再生されない
sound.duration(); // 取得できないので0になる

sound.load(); //読み込み
sound.play(); //再生される
sound.duration(); //取得できる

フェードイン・フェードアウト

fade()メソッドはオーディオをフェードイン・フェードアウトするときに使います。
第1引数にフェード開始時の音量、
第2引数にフェード終了時の音量、
第3引数にフェードさせる時間(ミリ秒単位)を設定します。
第4引数にsound IDを入れることもできます。

//1秒かけてフェードイン
sound.fade(0, 1, 1000);
//1秒かけてフェードアウト
sound.fade(1, 0, 1000);

ちなみにフェードアウトしても、音声が0になるだけで再生は止まりません。
次に紹介するon()イベントでfade()を検知して停止する方法を紹介しています。

イベントを検知する

on()メソッドを使うとjQueryと似たような記法でload, loaderror, playerror, play, end, pause, stop, mute, volume, rate, seek, fade, unlockのイベントの発火を検知して関数を実行できます。第3引数にsound IDを入れることができます。

//フェードイベントを検知してオーディオを停止
sound.on('fade', () => {
  sound.stop();
});

さらに確実にフェードアウトのみを検知する場合はon()イベント内でvolume()を取得して判定すれば良いかなと思います。

//フェードアウトを検知してオーディオを停止
sound.on('fade', () => {
  const volume = sound.volume();
  //フェード後に音量が0になっていたら停止
  if(volume === 0){
    sound.stop();
  }
});

また、on()の場合は登録したイベントが発火するたびに検知しますが、1回だけ検知するonce()メソッドも用意されています。

//最初の1回だけ再生する
sound.once('load',() => {
  sound.play();
});

イベントを削除する

on()で登録したイベントを任意のタイミングで削除したい時は、off()メソッドを使います。第1引数にイベント名、第1引数にリスナーとして登録した関数、第3引数にsound IDを入れることができます。第2、第3引数は省略するとすべてのイベント、すべてのオーディオを対象にします。

const stopAudio = () => {
  sound.stop();
};
sound.on('fade', stopAudio);

//fadeイベントをすべて削除
sound.off('fade');

//stopAudioのみを削除
sound.off('fade', stopAudio);

howlerを破棄する

unload()メソッドを使うことで、howler.jsで作られたインスタンスを完全に破棄できます。unload()メソッドを使った音源のすべてが停止し、キャッシュからも削除されます。

sound.unload();

さいごに

今回はhowler.jsの基本的な使い方をメモしました。
ライブラリすべてを把握しているわけではないのでよく使う機能に限ってメモしましたが、単にWebサイトに設置して再生・停止できるようにするならこの記事の内容だけで十分だと思います。

機能が多すぎて、実際に使った機能以外はこの記事では説明しきれませんでしたが、もっと詳しく書いている記事を見つけたのでこちらも参考にしてみてください。

[HTML5] 音声ファイルをJSで再生/停止する – howler.js編

https://blog.katsubemakito.net/html5/audio-howlerjs1

jsのオーディオライブラリ、howler.jsを試してみた

https://qiita.com/okumurakengo/items/5ba385f50763ed79808d

howler.jsはここに記載していないオプション含め、もっとたくさんの機能が揃っています。ベースにWeb Audio APIを使っているのでうまく利用すれば「オーディオビジュアライザー」を作ることも可能です。

次回はhowler.jsを使って簡単なオーディオビジュアライザーを作ってみたいと思います!

記事一覧

RELATED

inoue
TIPS

【CSS + JS】テキストの無限ループアニメーション

inoue
TIPS

【Shopify】カートへの遷移を飛ばしてチェックアウトに進むボタンを設置する

inoue
TIPS

【JS】PhotoSwipe v5を使って画像をポップアップ表示する

inoue
TIPS

gulpでjpg・pngからAVIF画像を生成する

inoue
TIPS

【JS】MutationObserverでDOMを監視[PhotoSwipe(v5)+Swiper(v8)連携]

inoue
TIPS

【Google Sheets API】 スプレッドシートのデータをJSONで取得する

NEW POSTS

inoue
TRY

【WordPress】GA4連携の人気記事ランキング機能を自作プラグイン化してみた

inoue
TRY

【netlify】ビルドイメージを更新 [ Ubuntu Xenial 16.04 → Ubuntu Focal 20.04 ]

inoue
TIPS

【PHP】Google Business Profile APIを使ってクチコミを取得する

inoue
TRY

スクリーンショットのAPI「screendot」を使ってみた

inoue
TIPS

【window.matchMedia】メディアクエリでhoverが使えるデバイスを判定

inoue
TIPS

lax.jsの使い方【スクロール連動アニメーションの実装】

ブログ記事一覧
  • HOME
  • TIPS
  • howler.jsの使い方[音声ファイルの再生・停止]