ウェブアプリケーションで音を出すには。
- 平成22年 4月12日 公開
- 平成22年 4月13日 更新
- テーマ
JAVAスクリプトを用いて実現するブラウザ上で動作するヴィデオゲームやウェブアプリケーションにて効果音や音楽類を演奏するための方法に関するメモです。
<canvas>要素などの整備に依り、HTMLとJAVAスクリプトだけでヴィデオゲームやウェブアプリケーションが開発し易くなりましたが、音に関してはまだまだ実装の差異が大きいようです。
今回はブラウザ上で動作するヴィデオゲームやウェブアプリケーションで効果音などを出すための方法についてメモをしておきます。
- 尚、一般にウェブページを開いたときに断りなく音を出すのは非常に迷惑な行為です。ヴィデオゲームやウェブアプリケーションと言えども、ページを開いたらすぐに音が出ると言うのは慎みましょう。
初めにお断りしたい事。
今回はウェブアプリケーションのための解説です。
通常のウェブ文書でページを開いたらいきなり音が出ると言うのは、多くの場合閲覧者にとって迷惑になります。
ゲームなど音が出ても問題が無いアプリケーションでのみ音出しをするようにして下さい。
また、音楽演奏は旧式のOSなどでは過剰な負荷になり、クラッシュの原因になる場合があります。
- 特に複数の音源を同時に鳴らそうとすると、クラッシュを免れても演奏データが混乱して聞くに堪えない状況になる事も予想されます。
そう言った事も考慮するようにしましょう。
音出し機構の実装の差異。
音についてはウェブの標準ではないため、各ウェブブラウザの実装に大きな差異があります。
多くのウェブブラウザでは、音声の演奏を行うプラグイン(クイックタイムなど)を起動してそちらに処理を引き渡す事で、ウェブブラウザがサポートしない機構を実現しております。
多くのグラフィカルなウェブブラウザの場合。(平成22年 4月13日 更新)
インターネットエクスプローラを含む多くのグラフィカルなウェブブラウザ、すなわち
- ファイヤーフォックスなどのゲッコウ搭載ブラウザ
- オペラ
- サファリやグーグルクロームなどのKHTML搭載ブラウザ
- インターネットエクスプローラ 3.0以降
などには、<embed>要素でプラグインを起動出来ます。
- 現行のウェブブラウザでなら、<object>要素でも同様の事が可能ですし、実際HTML 4/XHTML 1では<embed>要素を使ってはいけない事にさえされておりましたが、HTML 5では晴れて<embed>要素が名誉回復する事となったため、こちらを使う事とします。
プラグインは、殆どの音源の形式に対応出来(あるプラグインが対応出来ない形式があった場合は、別のプラグインを用意すれば良い)、従って機構の拡張が容易になります。
加えて、上記のように多くのウェブブラウザが実装している方式のため、互換性の心配は殆どありません。
- ただ、ファイヤーフォックスなどに用いられているクイックタイムプラグインではMP3形式が再生出来ない場合があるようです。MPEGを用いるのであれば、MP3(MPEG-3ではない)ではなくMPEG-2やMEPG-4などにした方が良さそうです。
実際に<embed>要素をアプリケーションで用いるには。(平成22年 4月13日 更新)
実際にゲームなどのアプリケーションで<embed>要素を用いて音出すをするのであれば、以下のようにします。
動作のからくり。
先ず、<embed>要素は、それを含んだ文書が読み込まれた直後でのみプラグインを起動すると言う事に注意してください。
これの何が問題かと申しますと、一度読み込んで起動した後は、仮令JAVAスクリプトのDOM操作などでsrc属性などの値を変更しても、プラグインの動作が変わる事が無いと言う事を意味するからです。
従って、<embed>要素で音を出したい場合には、その都度<embed>要素を含んだHTML文書を開かなければなりません。
しかし、ゲームなりアプリケーションなりの土台となっているHTML文書を音を出す度に閉じる事は出来ません。
そこで、音を出したい場合には、土台となる文書と別に開けるような機構が必要になります。
これには、幾つかの方法があります。
- 別ウィンドウ
- 音出しのためとは言え、ウィンドウが余計に開くのは鬱陶しいですし、今日ではポップアップ広告を封じるために別ウィンドウが開かないように設定出来るウェブブラウザも多数あり、そのようなブラウザでは音が出なくなってしまう場合があります。
- フレーム
-
具体的には土台となる文書を収めるフレームと音出し専用のフレームを一つのフレームセットに嵌め込んで、音出しが必要になったら、音出し専用フレームに音出し用のHTML文書を書き出します。
このとき、音出し専用のフレームの幅は零で構いません。
しかし、今日ではフレームは様々な問題を孕んでいる事から敬遠されつつあります。
- インラインフレーム
-
具体的には土台となる文書の片隅に音出し専用のインラインフレーム(<iframe>要素)を埋め込み、音出しが必要になったら、音出し専用のインラインフレームに音出し用のHTML文書を書き出します。
このとき、音出し専用のインラインフレームの幅と高さは零で構いません。
実はインラインフレームはストリクト仕様から外されていたものの、非推奨とはされていなかった機構です。
ネットスケープ 4.x以前ではサポートがないと言う欠点はありますが、そんな旧式のブラウザでゲームやアプリケーションなど、よほど単純なもので無い限りほぼ不可能ですので、その意味でも除外されて問題は無いでしょう。
以上を考慮すると、インラインフレームを用いるのが最も良いと考えられます。
音出し用のHTMLにしても、わざわざ作成する事などなく、音出し専用のインラインフレーム(または別ウィンドウやフレーム)をdocument.open()メソッドでクリアした後、必要な<embed>要素をdocument.write()メソッドで書き出せば良いのです。
実際のやり方。
それでは、動作のからくりに従って実際にやってみましょう。
先ず、アプリケーションを実現するためのHTML文書には、以下のようなインラインフレームを埋め込みます。
<iframe id="SOUND" name="SOUND" src="dummy.html" width="1" height="1"></iframe>
ここで、dummy.htmlは何も演奏しないダミーのHTML文書です。
- 初めにお願いした通り、ページを開いていきなり音を出すのは宜しくないので、初めに埋め込んでいるダミーページでは音を出さないようにしましょう。
そして、ゲームなりアプリケーションのコードでは、音を出したい場合には、以下のようにして埋め込んだインラインフレーム内の文書をJAVAスクリプト操作で書換えます。
parent.SOUND.document.open()parent.SOUND.document.write('<embed src="'+音源のURL+'" width="1" height="1" loop="false" repeat="false" autoplay="true">');parent.SOUND.document.close()
このとき、SOUNDとは埋め込んだインラインフレームに付けたname属性/id属性の値となります。
- この方法はインラインでないフレームでも有効です。
- また、同じ文書に連続して書換える事で同じ音を連続して出させる事も可能です。
<embed>要素で音を出す方法の欠点。
<embed>要素はJAVAスクリプトに対応しているグラフィカルなウェブブラウザでは殆どの環境で利用が可能です。
しかしその一方、<embed>要素に依る演奏はプラグインの起動に時間が掛かり、かなり長いタイムラグが発生します。
従って、ゲームなどの効果音やアプリケーション操作時の警報音などリアルタイムで音を出したい場合には向いておりません。
インターネットエクスプローラの場合。
インターネットエクスプローラには、ネイティヴ?の演奏機能として、<bgsound>要素が用意されております。
<bgsound>要素は公式規格としては非公認ではありますが、<embed>要素に較べてタイムラグが遙かに短いので、ゲームなどの効果音やアプリケーション操作時の警報などリアルタイムで音を出す必要がある場合には有用です。
ウィンドウズの場合、<bgsound>要素でWAVE, WMA或いはMIDIなどウィンドウズメディアプレイヤーで再生出来る音源は一通り演奏出来ます(ウィンドウズメディアプレイヤーと連携させている?)。
- 但し、ウィンドウズメディアプレイヤーで演奏出来ない形式はやはり演奏出来ないようです。
実際に<bgsound>要素をアプリケーションで用いるには。
<bgsound>要素は、JAVAスクリプトでsrc属性の値を変更する度に新たに演奏するようになっております。
例えば、アプリケーションを実現するためのHTML文書には、以下のように<bgsound>要素を<head>要素内に埋め込みます。
<!--[if IE]><bgsound id="IESOUND" name="IESOUND" src="dummy.wav" loop="1" /><![endif]-->
ここで、dummy.mavは何も演奏しないダミーのWAVE音源です。
また、<bgsound>要素の前後の宣言はインターネットエクスプローラ以外ではコメントアウトとなるようにするためのものです。
あとはインターネットエクスプローラである場合に限り、この<bgsound>要素のsrc属性を操作します。
この方法としてはDOM操作でも良いのですが、それ以前のプロパティ操作で対応が可能です。
ただ、IE以外ではコメントアウトとなるようにしているため、インターネットエクスプローラであるかどうかの判断に、getElementById()メソッドが使えます。
具体的には、以下のようになるでしょう。
// インターネットエクスプローラの場合if ((bgsound=document.getElementById('IESOUND'))!=null) {bgsound.src='新たに出したい音の音源へのURL';}// 他の環境での音出しelse {…
このとき、IESOUNDとは埋め込んだ<bgsound>要素に付けたname属性/id属性の値となります。
<bgsound>要素で音を出す方法についての注意事項。
まず、<bgsound>要素は一文書に一箇所しか入れられません。複数箇所に入れると、スクリプトエラーになるようです。
また、<bgsound>要素のオブジェクトのsrcプロパティに値を入れると、それまで演奏していた音は強制停止となります。
これを用いて空のファイルへのURLをsrcプロパティに入れる事で演奏を強制終了させる事も可能です。
逆を言えば、BGMを流しながら必要に応じて効果音を出すと言う場合にはBGM側はインラインフレームで実現する必要があります。
- OSやインターネットエクスプローラのヴァージョンが旧いと、複数の音源を同時に再生した場合にブラウザどころかOSまでクラッシュする場合があります。複数の音源を同時に演奏するのは危険ですのでやめましょう。
そして、<bgsound>要素はあくまでもインターネットエクスプローラの独自実装ですので、常に他のブラウザ向けの別の方法と併用するようにしましょう。
HTML 5で導入された新たな機構。
HTML 5では、ウェブブラウザ上でアプリケーションを実現するために幾つかのマルティメディア関連の要素やオブジェクトを制定する事としております。
音を出す事については<audio>要素が用意されております。
現在、実装されているユーザエージェントは限られておりますが、ユーザエージェントが画像を<img>要素で埋め込めるのと同様にネイティヴで音源を埋め込めるようになります。
その結果、リアルタイムでの演奏が可能になります。
またJAVAスクリプトを用いて演奏を操作するために、<audio>要素関連のオブジェクトも定められております。
ただ、埋め込める音源の形式が著しく制限され、加えてサポートしている形式がまちまちになっていると言うより重大な問題があります。
<audio>要素に対応しているウェブブラウザ。
<audio>要素は現状、以下のブラウザで機能します。
- ファイヤーフォックス 3.5以降
- サポートしている形式はOGGのみです。
- サファリ 3.1以降
- サポートしているのはMP3, AAC, MAVEなどMPEGを用いた形式のみです。
- グーグルクローム 3以降
- サポートしているのはOGGとAAC形式です。
オペラ及びインターネットエクスプローラについては平成22年 4月12日現在まだサポートがないようです。
<audio>要素に対応しているウェブブラウザ。
<audio>要素は現状、以下のブラウザで機能します。
- ファイヤーフォックス 3.5以降
-
サポートしている形式はOGGのみです。
尚、制作者が実際に試したところ、音が途切れるなどの重大なトラブルが頻発しました(後述)。
- サファリ 3.1以降
- サポートしているのはMP3, AACなどMPEGを用いた形式のみです。
- グーグルクローム 3以降
- サポートしているのはOGGとMP3, AACなどMPEGを用いた形式です。
- オペラ 10.50以降
- サポートしているのはOGG形式です。
インターネットエクスプローラについては平成22年 4月12日現在まだサポートがないようです。
実際に<audio>要素をアプリケーションで用いるには。
アプリケーションで用いる場合は<audio>要素をHTML文書に埋め込む必要はありません。
AudioオブジェクトをJAVAスクリプトで発生させてそれを操作します。
尚、Audioオブジェクトは音源ごとに生成させる必要がありますが、一度生成させれば簡単なメソッドの実行で何度でも演奏が可能です。
具体的には、以下のようにします。
- 前提条件として、ファイヤーフォックスとクローム用のOGG音源とサファリ用のAAC音源(及び別の方法で演奏するインターネットエクスプローラ用のWMA音源)を用意します。両者の違いは拡張子(
.ogg及び.aac)で区別するものとします。
-
先ず、初期設定の段階で、Audioオブジェクトを正しくサポートしている事を確認したうえで音源オブジェクトを事前に用意します。
audio_ext='';// 利用する音源の拡張子。dummy=document.createElement('audio');if (dummy.src!=undefined) {// OGGとmp3のどちらかを判断audio_ext='.ogg';var s=dummy.canPlayType('audio/ogg').toLowerCase();if (s=='' || s=='no') audio_ext='.aac';// 音源の取り込み。audio_xxxx=new Audio('xxxx'+audio_ext);audio_yyyy=new Audio('yyyy'+audio_ext);…} -
あとは、演奏したいときに演奏したい音源のAudioオブジェクトに対して
play()メソッドを実行するだけです。簡単のため、函数形式で書いておきます。
// 引数で指定した音源を演奏する。
function play_sound(src) {// Audioオブジェクトを利用している場合。if (audio_ext!='') {eval('audio_'+src+'.play()');return;}// インターネットエクスプローラの場合。if ((bgsound=document.getElementById('IESOUND'))!=null) {IESOUND.src=src+'.wma';return;}// このあと、必要ならインラインフレームを用いた演奏処理を入れられます。}
ここでは、各音源のオブジェクトをそれぞれスカラ変数にしましたが、ハッシュにしても良いでしょう。
<audio>要素を用いる上で注意したい事。(平成22年 4月13日 更新)
ファイヤーフォックス 3.6の問題点。
ファイヤーフォックス 3.6では、幾つもの音源を利用していると、演奏が途切れ途切れになり、聴くに堪えないものとなる場合があります。
正直、ファイヤーフォックスに限って言えば、<embed>要素を用いる方が遙かに安定しております。
ですが、<embed>要素の方法はプラグインの起動によるタイムラグが生じるため、リアルタイムで演奏すべき効果音には適しません。
全ての方式に共通の注意点。
どのような方法であっても、以下の点に注意しなければなりません。
- 音を出される事を嫌う利用者もいる事は絶対に忘れてはいけません。通常のウェブ文書では開いたときに音楽を勝手に鳴らされると非常に迷惑になりますが、アプリケーションやゲームだからと言ってそのような事を勝手にして良い事にはなりません。
- どの方法を用いるにしても、音源の演奏と画面の進行の同期を取る事は出来ません。演奏に併せて画面の表示を待たせると事は決して出来ないのです。
- 現行のOSやウェブブラウザでは、BGMを鳴らしつつ必要に応じて別の効果音を出す事は造作ないようですが、旧式のOSやブラウザでそれをやると、デヴァイスの奪い合いなどでブラウザどころかOSまで吹っ飛ぶ事もあり、非常に危険です。複数音源の同時演奏は絶対に避けましょう。
実際にアプリケーションで利用するには。(平成22年 4月13日)
実際にゲームやアプリケーションなどで音声を出したいのであれば、以下の事を考える必要があります。
- 対応出来る環境
-
ゲームやアプリケーションではスクリプトの対応も必要ですが、音に限って言うなら、以下のような形になるでしょう。
- ネットスケープ 4.xなどの旧式ブラウザにも対応しなければならない場合
-
今日ではそんなケースは先ず無いでしょうが(そもそもDOMや<canvas>要素はそんな旧式のブラウザで動作しない)、その場合には音出し専用の<embed>要素を埋め込んだフレーム(表示される大きさは零で構わない)とメインのフレームをフレームセットに埋め込む必要があります。
但し、この方法はフレーム自体に問題が多い事と、演奏の際にタイムラグが発声すると言う問題があります。
- 旧式ブラウザには対応する必要が無い場合
-
この場合は、インラインフレーム(<iframe>要素)に<embed>要素を含んだHTML文書を読み込ませる事で演奏させる事が出来ます。
インラインフレームなのでフレームほどの問題は生じませんが、演奏の際にタイムラグが発声するという問題は依然残ります。
- 現行のブラウザだけに対応すれば良い場合
-
厳密には
現行
と言うより最新と言った方が正しいと思われますが、この場合はインターネットエクスプローラ向けの<bgsound>要素とその他の最新ブラウザに用意されているAudioオブジェクトを併用するのが最もスマートな方法です。ただ、制作者はファイヤーフォックス 3.6でのトラブルを経験しており、そのためインラインフレームで<embed>要素入り文書を埋め込む方法の併用も検討すべきかと思っております。
- 音源の形式(平成22年 4月13日)
-
音源の形式については、対応がまちまちなのが実情です。
詳細は後ほど機会があれば纏めたいと思いますが、少なくとも現行のウェブブラウザに対応するのであれば最低でも三種類は必要でしょう。
具体的には、
- OGG形式(ファイヤーフォックス・オペラでAudioオブジェクトを用いる場合)
- AAC形式(サファリ・クロームでAudioオブジェクトを用いる場合及び<embed>要素でプラグインを起動して演奏させる場合)
- WMA形式(インターネットエクスプローラで<bgsound>要素で演奏させる場合)
の三つが必要になります。
今回この文書を書いた経緯。
制作者は今までウェブページから音源を演奏する事については否定的であり、従ってそれらに関する技術について殆ど解説していない、否、意図的に解説を忌避してきました。
ただ、今後はHTML 5などの関連技術の普及でウェブブラウザ上で利用出来るゲームやアプリケーションが増える事が予想されるため、先ず実際に使ってみようと思い、かつて開発していたJAVAスクリプト二人麻雀・WEBTILEに効果音を導入するための準備を進めました。
実際に導入作業をして行くうちに様々なトラブルに遭遇したので、それらについてより一般的になるように纏めたものです。
WEBTILEについては、平成22年 4月12日現在まだ導入をしておりませんが、完成したら実際にどのような方法であらゆる環境に対応出来る音源演奏方法を導入したかを改めて解説したいと思っております。
- WEBTILEについても、四人打ちへの対応なども考えておりますが、実現は何時になるか分かりません…。