ちょっと話題の記事

オーディオファイルの扱いが簡単に!JavaScriptライブラリ「Howler.js」

オーディオファイルの取り扱いを簡単にしてくれるJavaScriptライブラリ「Howler.js」を紹介します。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ウェブでオーディオファイルを扱うのは「正気の沙汰ではない(要出典)」と言われており、Web Audio APIHTML5 Audio(HTMLMediaElement)を見ると、確かにそっ閉じしたくなる感じです。

そんなオーディオファイルの読み込みからブラウザごとの再生できるファイルの判定など、面倒な処理を任せてしまえるオーディオ関連のJavaScriptライブラリHowler.jsを紹介します。

公式サイト(サンプルあり):howler.js - JavaScript audio library for the modern web

リポジトリ:howler.js - GitHub

使い方

npmなら

npm i howler -D

CDNから読み込むなら

<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.1.2/howler.min.js"></script>

です。(サンプルコードはnpmを使う前提です)

ページを読み込んでオーディオファイルを再生するには、new Howl()にオーディオファイルのURLを渡してsoundオブジェクトを生成し、再生させるだけです。

import {Howl} from 'howler';

const sound = new Howl({
    src: 'path/to/audio.mp3'
});
sound.play();

「あれ?再生されない…だと…!?」と思った方、大丈夫です。ブラウザによっては、ページを読み込んだだけでは再生されません(NG: Safari・Chrome / OK: Firefox)。

最近のブラウザはユーザーがボタンをタップするなど、明確なアクションを取らないと音が流れないようになっています。Howler.jsではこの制限に対して、ウィンドウに対するtouchendイベントを検知して空のデータを再生し、この制限の解除を試みるようです。(autoplayオプションを設定している場合も、制限解除後に音が流れます)

続いては、1つのボタンで再生・停止を制御するサンプルです。sound.playing()で、soundインスタンスに紐づいた音が再生されているかどうかを確認し、処理を分岐しています。

import {Howl} from 'howler';
const sound = new Howl({
    src: 'path/to/audio.mp3'
});

// HTML側に`<button id="button1" />`がある前提で
const button1 = document.getElementById('button1').addEventListener('click', (e) => {
    if (sound.playing()) {
        sound.stop();
    } else {
        sound.play();
    }
});

サンプルはありませんが、sound.play()して返ってくるIDで状態を管理する、という方法もあります。

ちなみにsound.play()するごとに再生され、音が重なります。play()ごとにIDが発行されるため、例えば3回再生したうちの2回目のIDを使ってsound.stop(secondID)とすることで、2回目だけを止めるということも可能です。

オプション関連

インスタンスを生成するときに設定できるオプションです。たくさんオプションがありますが、その中からよく使いそうなものをご紹介。

src(必須)
再生するソースのURLやbase64 data URIsを指定します。配列を使って複数の値を渡すこともでき、その中からブラウザで再生できるファイルを再生してくれます。

読み込みはきちんと非同期処理が走るので、読み込みが済んでから再生されます。

また拡張子の指定がない場合は、formatオブションで指定しましょう。

volume(デフォルト:1.0)
音量の設定で、0.0から1.0の間で指定します。ちなみに再生するデバイスの音量に対する相対値で、例えば0.8で指定すれば、現在の音量の80%になります。

loop(デフォルト:false)
ループの設定です。

preload(デフォルト:true)
srcで指定されたファイルをあらかじめダウンロードします。falseにしておいて、ユーザーアクションに応じて.load()を走らせると、ギガを無駄に消費しないようにもできます(いわゆるLazy Loading)。

import {Howl} from 'howler';
const sound = new Howl({
    src: 'path/to/audio.mp3',
    preload: false
});

// HTML側に`<button id="button1" />`がある前提で
const button1 = document.getElementById('button1');
button1.addEventListener('click', (e) => {
    sound.load();
    sound.play();
});

format
ファイルフォーマットはhowler.jsが拡張子から勝手に判別してくれるのですが、前述の通りsrcに拡張子がない場合は指定する必要があります。

onload
ファイルの読み込みが終わったときに実行したい処理を設定します。またon〜のオプションは、後述するon()メソッドでも設定できます。

onplay
再生が始まったときに実行したい処理を設定します。IDを引数として使えます(イベント関連のほとんどのオプションが、IDを引数として使えます)。

import {Howl} from 'howler';
const sound = new Howl({
    src: 'path/to/audio.mp3',
    onplay: (id) => {
        console.log(id + 'で再生しているよ');
    }
});

onend
再生が終わったときに実行したい処理を設定します。

onstop
再生がストップしたときに実行したい処理を設定します。

他にもエラー関連のイベントもあるので、適切に設定できるといいですね。

メソッド関連

こちらもよく使いそうなものをご紹介。

IDを引数として渡せるメソッドでIDを渡さずに実行した場合、そのインスタンスに紐づいた音すべてが対象になります。

play([sprite/id])
音を再生します。IDを指定やスプライト名を指定できます。(スプライトは、任意の場所から再生するための設定で、詳細はドキュメント参照)

pause([id])
再生を一時停止します。

stop([id])
再生を停止します。

volume([volume], [id])
音量を0.0から1.0の間で設定します。

playing(id)
指定したインスタンスが再生されているかどうかを真偽値で返します。

on(event, function, [id]) / once(event, function, [id]) / off(event, [function], [id])
インスタンスにイベントの設定・削除を行います。onceは一度だけ実行されます。

使えるイベントは、load, loaderror, playerror, play, end, pause, stop, mute, volume, rate, seek, fade, unlockです。

load() / unload()
preloadを無効化している場合、load()で読み込みを開始します。unload()は、インスタンスを破棄して再生を停止します。

グローバルメソッド関連

Howlerオブジェクトで実行できる、全体を対象にしたメソッドです。こちらも一部をご紹介。

import {Howler} from 'howler';

Howler.volume(0.8);

mute(muted)
真偽値を渡して、ミュートのオン/オフを切り替えます(ちなみにHowler._mutedで、状態を取得できます)。

volume([volume])
全体の音量を0.0から1.0の間で設定します。個別に設定している音量にも影響し、この値を0.8で設定した場合、個別に0.5で設定されている音は、0.4の大きさになります。

その他にも

Web Audio APIを使うかどうか、自動で再生制限の解除を行うかなどのグローバルオプションや、今回は使いませんでしたが、音響を関連を細かく設定できるSpatialというプラグインもあります。

気になる方はぜひドキュメントをチェックしてみてくださいね!