HTML5のAudio要素簡易利用ガイド

WebAudio全盛のこの時代に役に立つかはわかりませんが
素直に実装すると結構ハマるポイントが多いので
メモがてら残しておきます。

# 概要

Audio要素とはHTML5から追加された要素で
この要素を使うことで音の再生や一時停止などをハンドリングできるので
音楽再生プレイヤーのような機能をJSだけで実現することができる。


# 主に持っている機能

* 再生/一時停止
* 再生位置変更（シーク）
* 音量変更

# 特徴

## 良い部分

* HTML5の初期段階からあり<br>スマホでは古い端末(iOS5、Android2.3以上ぐらい)でも再生することができる<br>※利用できるブラウザの範囲は狭いが後発のWeb Audioのほうができることは多い
* ストリーミングサーバーを設けず<br>Rangeリクエストで擬似的にストリーミングを実現させることができる

## 悪い部分

* `autoplay` という属性があり<br>これをtrueにするとユーザーのアクションを待たずに再生できるのだが<br>こちらはスマホでは無効化される<br>（自動再生開始によるユーザーの意図しないトラフィック発生を防ぐためらしい）
* スマホではユーザーアクションを伴わないと<br>読み込みや再生動作を開始できない場合が多いので、その想定で作ると良い
* ブラウザによって挙動や各種イベントの発生のタイミングが異なる。
* `controlers` と指定するとブラウザ側で再生や停止のコントロールUIを出してくれるが<br>[ブラウザによって表示やサイズの統一感がない。](http://qiita.com/tadfmac/items/14b3c679470e3c83d991)
* 音量調整の属性があるが、すべてのOSで使えるわけではなく、iOSでは非対応。




# Audioタグの再生フロー例

コードをベースに再生の一例を記載します。

```js
// オブジェクトを生成します
var url = "http://example.com/hogehoge.mp3";
var audio = new Audio(url);

// 実体ファイルをロードします。
audio.load();

// readyStateからロード状態を判断します。
if (audio.readyState === 4) {
  audio.play();
} else {
  // 再生可能状態でなければ再生可能状態になった時のイベント通知をセットします
  audio.addEventListener('canplaythrough', function (e) {
    audio.removeEventListener('canplaythrough', arguments.callee);
    audio.play();
  });
}

```

## 1.オブジェクトの生成

再生ファイルを生成します。情報取得元のソースは生成時でなくてもセットすることが出来ます。

## 2.実体ファイルをロード

実体ファイルをロードします。
ただし、スマートフォンの場合は `play()` までロードしない端末もあり
確実にここで始まるというわけではないので気をつけてください。

## 3.readyStateからロード状態を判断

audioタグはreadyStateで再生可能な状態かを判断できます。

|readyStateの値|状態名|説明
|:---|:----|:---|
|0|HAVE_NOTHING|ダウンロードしていない|
|1|HAVE_METADATA|メディアメタデータのダウンロード済み
|2|HAVE\_CURRENT_DATA|現在再生位置の直近までのデータダウンロード済み|
|3|HAVE\_FUTURE_DATA|再生位置に加え次フレームデータまでをダウンロード済み|
|4|HAVE\_ENOUGH_DATA|再生位置に加え次フレームデータまでをダウンロード済みであり、且つダウンロード速度から計算し、最後まで再生できるだけのデータをダウンロード済である状態|

だいたいは `4` でなければ再生出来ないことが多いので
4であるかしかチェックしないことが多いです。

## 4.再生可能状態でなければ再生可能状態になった時のイベント通知をセット

上記のロード状況において再生出来ない場合は
まだダウンロードが十分に終わっていない可能性があるので
`addEventListener` イベントをセットしてロード状況を確認します。

この場合は `canplaythrough` のイベントを見ます。なお、主なイベントの名称と内容に関しては以下のとおりです。

|イベント名称|説明|
|:---------|:----|
|canplaythrough|バッファリングのために止まること無く再生できる時に発火します。|
|canplay|再生可能なところまでデータをDLして再生可能になった時に発火します。|
|timeupdate|秒数が変化している際に、変わる度に発火されます。発火したタイミングで `currenttime` を取得すると現在の再生秒数が取れますが、これを利用してでUIを変更するのはオススメしません。|
|ended|再生が最後まで完了した時に発火します。|
|error|何かエラーが起きた時に発火します。ただし発火タイミングはブラウザによって様々なので一律同じところでエラーが呼ばれるとは限りません。|
|play|再生が開始するタイミングで発火します。一時停止からの復帰でも発火します。|
※canplaythroughに関して表記が正確ではなかったので修正しました（コメント欄参照）
他にもイベントがありますが他のモノに関しては[こちら](http://www.w3schools.com/tags/ref_av_dom.asp)を参考にして下さい。

またイベントの発火順番はブラウザや環境によって大きく異なりますので気をつけてください。
利用する主要な環境で検証して最適なタイミングで噛みあうように調整するようにしてください。

# 参考ページ

* [第1章 Audio/Video | SoftBank スマートフォン サービス開発支援サイト](https://www.support.softbankmobile.co.jp/partner_st/home_tech17/audiovideo.cfm)
* [iOS における HTML5 の audio 要素に関する制約を克服する](https://www.ibm.com/developerworks/jp/web/library/wa-ioshtml5/)
* [HTML5でiOS Webアプリを作ってみました -えほんのじかん(iPad版)- - Yahoo! JAPAN Tech Blog](http://techblog.yahoo.co.jp/lab/ehon/)
* [HTML Audio/Video DOM Reference](http://www.w3schools.com/tags/ref_av_dom.asp)
* [Takazudolog - 地獄のvideo／audio要素](http://takazudo.github.io/blog/entry/2013-02-06-videoaudio.html)
* [モバイルブラウザオーディオ調査・伝説の最期編 | クラウド番外地](http://outcloud.blogspot.jp/2015/11/htmlaudio.html)
* [最近増えてきた、音声を扱うアプリとHTMLでの実装についてPackaging HTML and Apps which deal with audio | Designers Hack（デザイナーズハック）](http://designers-hack.net/2012/12/html5_audio/)