JavaScript でプログラムを作成していると、クイズの正解・不正解やゲームの効果音、操作の確認音や警告など、音を鳴らしたいことがあります。
JavaScript で音を鳴らすには、外部ファイルを再生する方法と、 JavaScript に埋め込んだデータを再生する方法の 2 種類があるようです。
効果音などの再生すべきデータが比較的小さい場合は JavaScript に埋め込む方法のほうが便利に思えましたが、 多少面倒な下準備が必要でしたので、その手順について記録しました。
データ量が小さくない音声ファイルを再生したい場合はファイル名を指定しての再生が簡単ですが、 ボタンが押されてから音声ファイルのダウンロードが始まるようですので、 ここで扱っている小さいファイルでも、気のせいか多少の遅延が起きています。
動作としては、次の「再生」ボタンを押したときのようになります。
※ 「再生」ボタンを押すと音がなりますので、音量にはお気をつけください。
外部 .js ファイルに埋め込んだ音声データ(wav 形式)を再生します。
外部 .js ファイルに埋め込んだ音声データ(mp3 形式)を再生します。
この html ファイルに JavaScript 関数を記述して埋め込んだ音声データ(wav 形式)を再生します。
wav ファイルをサーバー上に置いてファイル名指定で再生します。
mp3 ファイルをサーバー上に置いてファイル名指定で再生します(mp3 を再生できる環境のみで動作します)。
いずれも Windows 10 PC の Chrome、Edge、Firefox で正常に再生できました。
Android 端末では、Chrome、Firefox、Edge、DuckDuckGo ともに、正常に再生できました。
なお、本サイトの
ご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
投稿 June 13, 2022
外部ファイルとして音声データを持つのではなく、JavaScript コードに埋め込む場合のコードについてです。
まず最初に、どういう形になるのかを確認しておきます。
var base64 = '〜 BASE64 エンコードされた wav データ 〜'; var sound = new Audio("data:audio/wav;base64," + base64); sound.play();
上のコードでは、3 段階で音を鳴らしています。
変数 base64 には、BASE64 という形式に変換された wav データを指定しています。 BASE64 を簡単に言うなら、0〜255 のデータを持つバイナリデータを、 6 ビット、つまり半角英数文字で表現できる 64 種類の文字に置き換えたもの、だそうです。 ですのでこの部分は、英数文字が羅列された文字列というイメージです。
次に今設定した BASE64 データを JavaScript の Audio クラスの初期化で使って、 再生できるようにします。 ここに外部の音声ファイル名を指定するとそれを再生してくれるようで、 このあと「ファイルのまま配置して再生する」で扱っています。
できた Audio オブジェクトで play 関数を呼び出して、音を再生します。
ここでは音声データとして wav 形式の data:audio/wav を指定していますが、 この部分を data:audio/mp3 に書き換えれば、base64 データを mp3 にして容量を減らせます。 ただ、mp3 だと必ずしもすべてのデバイスに対応しているわけではない、というようなネット情報もありますので、調査が必要です。
このように流れは簡単ですが、問題はどうやって BASE64 エンコードされた wav データを作成するか、です。
投稿 June 13, 2022
再生したい wav や mp3 データファイルを BASE64 形式にする方法です。
再生する wav や mp3 データファイルは、
BASE64 変換についてネットを検索すると、ユーティリティが多数見つかります。 また、プログラムから利用できるライブラリも多数あるようですが、それらは使いません。 メインマシンに必要ではないものは入れたくありません。
ここでの環境は Windows 10 Pro です。 Mac の場合は、確認はできませんが 「JavaScript で Beep 音を鳴らす方法(Qiita)」 に書かれている方法で、同じことができるようです。
Windows には certutil というツールが用意されていました。
これを使うには、コマンドプロンプトを起動する必要があります。 「スタート」メニューを開き、 W の欄にある「Windows システムツール」をクリックします。
展開されたプログラムの中に「コマンド プロンプト」がありますので、クリックして起動します。
BASE64 エンコードには、 certutil の -encode を使います。
形式は certutil -encode infile outfile とされていますので、infile に入力ファイル名を、outfile に出力ファイル名を指定するだけです。 ファイル名またはパスに半角スペースが含まれる場合は、ダブルクォーテーションで囲えば問題ないと思います。 どちらもフルパスで指定すると、間違いがありません。
すると、次のようなファイルができます。
-----BEGIN CERTIFICATE-----
UklGRjiLAgBXQVZFZm10IBAAAAABAAIARKwAABCxAgAEABAAZGF0YRSLAgAAAAEA
AAABAAAAAQAAAAEAAAABAAEAAgABAAEAAQABAAEAAQABAAEAAgABAAIAAgACAAIA
AgABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAAAAQABAAEAAQABAAEA
AQACAAEAAgABAAEAAQABAAEAAQAAAAEAAAAAAP//AAD//////v////7/////////
////////AAAAAAAAAAAAAAAAAAAAAAAA//////7//v/9//3//f/9//z//P/8//z/
// 中略
jwCPAMIAwwDRANEAvQC9AIQAhAAzADQA6//s/8L/xP+u/6//lv+Y/3f/eP9b/1z/
Uv9S/2v/a/+d/53/0f/R/w==
-----END CERTIFICATE-----
先頭と末尾の行に目印が書き込まれているほか、 親切にも(証明書の仕様かもしれませんが) 64 バイト(文字)ごとに改行が入っています。 この改行が JavaScript にするときに厄介になります。
JavaScript で Audio に渡すデータには、もちろん目印の行は含めてはいけませんが、 その間にあるデータ行をこのまま JavaScript のソースに書き込むと、改行している部分で正しく認識されないことになります。
なお、BASE64 の詳細については、 「base64 ってなんぞ??理解のために実装してみた(Qiita)」 を参照すると良さそうです。
投稿 June 13, 2022
JavaScript で BASE64 データを変数に設定している部分、 上記でできたデータをそのまま書き込むと次のようになりますが、正しく認識されません。
var base64 = ' UklGRjiLAgBXQVZFZm10IBAAAAABAAIARKwAABCxAgAEABAAZGF0YRSLAgAAAAEA AAABAAAAAQAAAAEAAAABAAEAAgABAAEAAQABAAEAAQABAAEAAgABAAIAAgACAAIA // 中略 jwCPAMIAwwDRANEAvQC9AIQAhAAzADQA6//s/8L/xP+u/6//lv+Y/3f/eP9b/1z/ Uv9S/2v/a/+d/53/0f/R/w==';
多くのプログラミング言語と同じように、JavaScript でも行の末尾に
var base64 = "\ UklGRjiLAgBXQVZFZm10IBAAAAABAAIARKwAABCxAgAEABAAZGF0YRSLAgAAAAEA\ AAABAAAAAQAAAAEAAAABAAEAAgABAAEAAQABAAEAAQABAAEAAgABAAIAAgACAAIA\ // 中略 jwCPAMIAwwDRANEAvQC9AIQAhAAzADQA6//s/8L/xP+u/6//lv+Y/3f/eP9b/1z/\ Uv9S/2v/a/+d/53/0f/R/w==";
これで改行なく連結されていると解釈されます。
PC の Chrome ブラウザで試したところではこれで問題なく、短い音を JavaScript で再生できるようになりましたが、 音声データ wav ファイルは、本当に短いデータであっても数キロバイトになりますし、1 秒でも 100 KB を超えたりします。
certutil は親切にも 64 バイトごとに改行を入れて読みやすくしてくれていますから、 1 KB で 16 行のデータとなります。 ですので 10 KB なら 160 行、100 KB なら 1,600 行になりますから、 JavaScript にコピーしてすべての行末に¥サインを付けるのは面倒、あるいは不可能です。
そこで、テキストファイルの各行末に¥サインを付与する自動化するツールを作成しました。
投稿 June 13, 2022
ツールのコードの説明は別ページで扱おうと考えていますので、 ここではダウンロード先と動作(使い方)だけ記録します。
ダイアログに certutil で変換したテキストファイル(先頭と末尾の目印行は先に削除しておくとより楽です)をドロップすると、 エディットコントロールに読み込まれます。
「行末に¥を付ける」のチェックボックスにチェックを入れ、 「変換実行」ボタンをクリックすれば、 作成するファイルの名前を付けるダイアログが表示された後、変換処理が行われ、できたファイルが自動的に開かれます。
certutil は 1 行で 64 文字しか記録されていませんので、行数が増えがちです。 1 行を 128 文字にして半分の行数にしたい場合は、「1 行の最小文字数」の欄に 128 と入力してから 「変換実行」ボタンをクリックします。 元データの行単位で処理され、蓄積して指定の文字数に満たない場合は次の行も足していきます。 ですので必ずしも全行が 128 文字で統一されるわけではありません。
では、なぜわざわざ「行末に¥を付ける」のチェックボックスがあり、初期状態で非チェック状態なのでしょうか?
Google が管理していると思われるサイトに、 「No line continuations」 という資料がありました。
これによると、「たとえ ES5 が規定していようとも、末尾¥つなぎはおかしなエラーの原因になるので使わないように」とされています。
ES5 とは、2009 年の ECMAScript バージョン 5 を意味しているということです。 ECMAScript とは、JavaScript の基準になっている書き方の規約のようです。
ES5 は 2015 年に ES6 となって以降、頻繁に更新され、今は 2020 年の ES11 となり、もしかしたらもっと新しくなっているようです。 詳しくは「ECMAScript」を参照してください。
ということですので、これに従うと、次のように「文字列の加算」で構成するほうが安全なようです。
const longString = 'This is a very long string that far exceeds the 80 ' + 'column limit. It does not contain long stretches of spaces since ' + 'the concatenated strings are cleaner.';
つまり、「行末に¥を付ける」にチェックを入れない場合は、この形式で出力する、ということにしています。
この文字列連結ツールは、参考のためにダウンロードできるようにしてあります。
私なら、完全に信用できるサイト以外からのダウンロードはしませんが、
興味がある方のために、実行ファイルを圧縮したものを置いておきます。
安全に努めているマシンで用意したファイルですが、お試しいただく場合は、完全に自己責任でお願いします。
OS は Windows 10 以降、ランタイムなど環境の用意は
実行ファイルを含む zip ファイルのダウンロードは、
https://www.straightapps.com/download/saConnectTextLines.zip
です。上記 URL をブラウザのアドレスバーに入力すると、ダウンロードできます。
正しい zip ファイルのタイムスタンプは 2022/6/13 13:08:06、 正しい実行ファイルのタイムスタンプ(更新日時)は 2022/6/13 13:06:45 で、 zip 内は実行ファイル1つだけです。 zip ファイルサイズは 1,903,071 バイト、 実行ファイルのサイズは 3,520,512 バイトです。 パスワードは設定していません。
投稿 June 13, 2022
ここまで苦労して音声データファイルを BASE64 に変換して JavaScript に埋め込んできましたが、 毎回 BASE64 に変換するのは面倒なので、ファイルのまま置いておいた場合の再生方法も試しました。
ボタンのクリック onclick 処理に、直接音を鳴らすコードを書きこんでいますが、もちろん別関数にして呼び出しても問題ありません。
<button onclick="var sound = new Audio('wav/omt-correct.wav');sound.play();" title="再生"> 再生 </button>
button の onclick に記述されているのは Audio クラスを作成して再生する JavaScript コードで、最初のものと違うのはファイル名を指定しているところだけです。 ボタンが押されてから初めて wav ファイルをダウンロードして再生するのでしょうから、 サイズが大きくなれば、時間がかかるかも知れません。
wav ファイルをサーバー上に置いてファイル名指定で再生します。
mp3 ファイルをサーバー上に置いてファイル名指定で再生します(mp3 を再生できる環境のみで動作します)。
少なくとも効果音程度なら問題なさそうです。 一度再生した音声データがちゃんとキャッシュされていれば、 再生のたびにダウンロードしなくて済むでしょうから、そうなっていることを期待します。
JavaScript で URL に指定されたパラメータを解析する方法について、書いています。
JavaScript で画面上に表示したボールを、キー入力またはタップで移動させるコードについて、書いています。
因数分解を楽しもう! パズルを解く感覚で、因数分解の練習をたくさんして、マスターしよう!
ウェブ開発に関するトピックは、「ウェブ開発トップ」にまとめられています。