HTML5

HyperText Markup Language 5 video element.

video 要素

 video 要素は HTML5 で新たに導入された要素で、注目度が高い機能の 1つでしょう。これまでウェブ・ページにビデオを組み込みたい場合は、Flash などのプラグインが使われてきました。しかし、HTML5 では、プラグインなしに、ビデオをウェブ・ページに組み込むことができるのです。

 ただ単にビデオを再生するだけであれば、video 要素の価値は、プラグインを使わないという点だけです。しかも、サイトのユーザーから見れば、プラグインが使われていようが、使われてなかろうが、あまり関係がありません。再生できれば、それで良いのです。

 とはいえ、video 要素に価値がないというわけではありません。プラグインに頼らないことのメリットがあります。

 まず、特定の企業に依存したテクノロジーではなく、標準化されたテクノロジーであるという点です。特定の企業に依存したテクノロジーは、その企業の方針によって、今後、どうなるかわかりません。ある時点で、突然、特許料を求めてくる可能性も否めません。また、内部がブラックボックス化されることになります。そのテクノロジーを開発した企業が情報を公開しない限り、ウェブ制作者がそのテクノロジーの詳細を把握することは難しくなります。実際には、Flash のように、すでに広く使われているようなテクノロジーでは、そのようなことは考えられないとは思いますが、特定の企業がコントロールしているテクノロジーは、常にこのようなリスクをはらんでいると言えます。

 もう 1つのメリットとは、プラグインでないことにより、video 要素にスタイルシートを適用でき、JavaScript からビデオを制御できるという点です。さらに、HTML5 で規定されている他の API と連携できる点が注目に値します。例えば、video 要素で再生されているビデオの 1シーンを、Canvas に取り込むこともできるのです。

 このように、これまでのように、ただ単にビデオを再生するだけでなく、ビデオという素材を様々な方法で料理できるのが魅力なのです。まだまだ、そのようなウェブ・アプリケーションの例は多くありませんが、ブラウザの実装が整えば、これまでにはないようなビデオの使い方が出てくることでしょう。

video 要素の概要

カテゴリー
フロー・コンテンツ
フレージング・コンテンツ
エンベデッド・コンテンツ
controls コンテンツ属性が存在する場合:インタラクティブ・コンテンツ
コンテンツ・モデル
src コンテンツ属性が存在する場合:トランスペアレント。ただし、この要素の中に別の video 要素や audio 要素を入れてはいけません。
src コンテンツ属性が存在しない場合:1つ以上の source 要素。その次にトランスペアレント。ただし、この要素の中に別の video 要素や audio 要素を入れてはいけません。
利用可能な場所
エンベデッッド・コンテンツが期待される場所
タグの省略
不可。開始と終了タグの両方が必要。
要素固有のコンテンツ属性
src
ビデオ・ファイルのアドレスを指定します。
poster
ビデオが利用可能になる前に表示させたい画像ファイルのアドレスを指定します。
autobuffer
ユーザーによってビデオが最後まで再生される可能性が高いことをユーザーエージェントに伝える論理属性です。
autoplay
ビデオが利用可能になったらすぐに再生を開始することを指示する論理属性です。
loop
ビデオの再生が終了したら最初に戻って再生を続けることを指示する論理属性です。
controls
ビデオの再生や停止などのユーザー・インターフェイスを表示させることを指示する論理属性です。
width
ビデオの横幅を CSS ピクセルを指定します。
height
ビデオの縦幅を CSS ピクセルで指定します。
標準的なスタイル
-

video 要素の簡単な使い方

 では、まず最初に、video 要素の使い方を簡単に見て行きましょう。video 要素で再生させたいビデオのファイル URL を、src コンテンツ属性に指定します。これだけで、ビデオの準備が完了です。

 とはいえ、src コンテンツ属性だけではビデオを再生することはできません。再生ボタンも停止ボタンもないからです。ユーザーに対してビデオを制御するためのインターフェースを表示させるためには、controls コンテンツ属性を使います。この属性は論理属性です。このコンテンツ属性をセットしておかないと、JavaScript なしには、ビデオを再生出来ませんので、注意してください。

video 要素のマークアップ例

<video src="vdos/total_solar_eclipse.mp4" controls="controls">
  <p>ご利用のブラウザでは再生出来ません。<a href="vdos/total_solar_eclipse.mp4" title="皆既日食動画">こちら</a>からダウンロードして下さい。</p>
</video>

 この例では、src コンテンツ属性を使って、mp4 形式のビデオ・ファイルを指定し、controls コンテンツ属性をセットしています。

 ここで、video 要素の中に p 要素を入れている点に注目してください。これは、video 要素に対応していないブラウザに対して表示させたいコンテンツをマークアップしたものです。現状では video 要素に対応していないブラウザがありますので、何かしらのコンテンツを入れておくのが良いでしょう。この例では、ビデオ・ファイルをダウンロード出来るよう、a 要素を使ってハイパーリンクを用意しています。

 なお、この仕組みは、video 要素に対応しているものの、ビデオ・ファイルを読み取れなかったり、ビデオ・ファイルの形式をサポートしていないなどの理由で、ビデオが再生されなかった場合のフォールバック・コンテンツとしては機能しません。あくまでも、video 要素を全くサポートしていないブラウザ向けのコンテンツとなることに留意してください。

 再生や停止や音量変更やタイムラインなどのインターフェースは、ブラウザによって異なります。

 なお、controls コンテンツ属性は、デフォルトでは無効になっています。必ず必要なのであれば、デフォルトで有効にして欲しいと思われるでしょう。

 しかし、HTML5 仕様では、ただ単にビデオを再生するためだけに video 要素を導入したのではありません。様々なビデオ制御のための API を提供しているのです。これによって、ただ単にビデオを再生するだけではなく、例えば、独自のユーザー・インターフェースを持ったビデオ・プレーヤーのように表現したり、ビデオと連動したウェブ・アプリケーションが実現できることを視野に入れています。このように JavaScript を通してビデオを扱う場合、ブラウザが表示するボタンなどのコントロールは、かえって不要となるのです。

 このページのサンプルでは、h.264/AAC 方式の mp4 形式のビデオ・ファイルを使用しました。2013年7月11日時点で最新版の Internet Explorer、Chrome、Firefox で再生できることを確認しました。

自動再生

 autoplay コンテンツ属性を使うと、ビデオ再生の準備ができ次第すぐにビデオが再生されます。

autoplay コンテンツ属性のマークアップ例

<video src="vdos/total_solar_eclipse.mp4" controls="controls" autoplay="autoplay">
  <p>ご利用のブラウザでは再生出来ません。<a href="vdos/total_solar_eclipse.mp4" title="皆既日食動画">こちら</a>からダウンロードして下さい。</p>
</video>

 特に理由がない限りは、autoplay コンテンツ属性をセットしないことをお勧めします。

 ビデオ再生の専用ページを別に用意し、元のページからリンクをたどることで再生が開始されるのであれば、自動再生は問題ないでしょう。しかし、例えば、ブログの記事にビデオを貼り付けた場合、いきなりビデオが再生されると、ユーザーによっては迷惑に感じることがあります。そのため、利用シーンを十分考慮して、コンテンツ属性の利用を検討するようにしましょう。

オート・バッファ

 autobuffer コンテンツ属性は、ブラウザに対して「ユーザーによって該当のビデオは最後まで再生されることになるだろう」ということを通知するために使います。これはブラウザ側に、ビデオ・データを事前にバッファすることを期待したものです。ただし、autoplay コンテンツ属性がセットされている場合は、無効になります。

autobuffer コンテンツ属性のマークアップ例

<video src="vdos/total_solar_eclipse.mp4" controls="controls" autobuffer="autobuffer">
  <p>ご利用のブラウザでは再生出来ません。<a href="vdos/total_solar_eclipse.mp4" title="皆既日食動画">こちら</a>からダウンロードして下さい。</p>
</video>

 このコンテンツ属性を指定しておくことで、事前にビデオ・データがダウンロードされます。ユーザーがビデオを再生するときには、ある程度のビデオ・データがロード済みとなっているはずですので、その範囲内であれば、早送りも可能となるでしょう。

 ただ、ユーザーが再生する可能性が高くないビデオに対しては、このコンテンツ属性をセットすることはお勧めできません。ブラウザ側の負担が高くなりますし、それ以上に、ネットワーク帯域や、サーバー側の負担を無駄に高くすることにつながります。ビデオ・データのサイズが大きいほど、大きな懸念材料になります。この辺の事情を考慮した上で、このコンテンツ属性を使うようにしましょう。

 なお、autobuffer コンテンツ属性を指定しなかったとしても、全くサーバーにアクセスしないというわけではありません。このコンテンツ属性が指定されていなくても、通常は、ビデオ再生開始時にもたつくことがないよう、ビデオ再生が開始される前から、ある程度のビデオ・データがダウンロードされます。

ポスター・フレーム

 ポスター・フレームとは、ビデオ生成の準備ができる前に表示させたい画像を表します。ポスター・フレームには、基本的には、該当のビデオを表すようなイメージを使います。

 video 要素には、poster コンテンツ属性が規定されており、このコンテンツ属性に画像ファイルの URL を指定しておくことで、ポスター・フレームをセットすることができます。

poster コンテンツ属性のマークアップ例

<video src="vdos/total_solar_eclipse.mp4" controls="controls" poster="poster.png">
  <p>ご利用のブラウザでは再生出来ません。<a href="vdos/total_solar_eclipse.mp4" title="皆既日食動画">こちら</a>からダウンロードして下さい。</p>
</video>

 通常は、ポスター・フレームは、ビデオ再生の準備が整う直前までしか表示されません。もちろん、poster コンテンツ属性で指定した画像のファイルのロードが完了するまでは何も表示されません。そのため、実際に目にできるのは、さほど長い時間ではありません。

 しかし、video 要素はサポートしているけれども、指定のビデオ・データの形式には対応しておらず、該当のビデオが再生できないブラウザでは、ポスター・フレームが表示されることになります。このようなブラウザを利用しているユーザーのためにも、何かしら意味のあるイメージを用意するのが良いでしょう。

 なお、HTML5 仕様では、ビデオ開始位置で停止している状態でもポスター・フレームを表示しても良いことになっていますが、実際に表示するかどうかは、ブラウザ・ベンダーに任されています。

ループ再生

 loop コンテンツ属性を使うと、自動的にビデオを繰り返し再生します。このコンテンツ属性は論理属性です。

loop コンテンツ属性のマークアップ例

<video src="vdos/total_solar_eclipse.mp4" controls="controls" loop="loop">
  <p>ご利用のブラウザでは再生出来ません。<a href="vdos/total_solar_eclipse.mp4" title="皆既日食動画">こちら</a>からダウンロードして下さい。</p>
</video>

 loop コンテンツ属性が指定された場合、一度ビデオの再生が開始されると、その後は、ビデオが停止されるまで、何度も繰り返しビデオが再生し続けます。

ビデオのサイズ

 width コンテンツ属性と height コンテンツ属性には、それぞれ、video 要素によってレンダリングされる領域の横幅と縦幅を指定することができます。

 ビデオは、この領域の中心にピッタリ収まる形で伸縮されて表示されます。ビデオの実際の縦横比と、width コンテンツ属性と height コンテンツ属性の縦横比が異なっていたとしても、ビデオの縦横比が変更されるわけではありません。したがって縦横比が異なる場合は、上下、もしくは、左右に余白ができることになります。

width, height コンテンツ属性のマークアップ例

<video src="vdos/total_solar_eclipse.mp4" controls="controls" width="100" height="100">
  <p>ご利用のブラウザでは再生出来ません。<a href="vdos/total_solar_eclipse.mp4" title="皆既日食動画">こちら</a>からダウンロードして下さい。</p>
</video>

ビデオの種類

 ビデオの形式には、様々なものがありますが、ブラウザが対応しているビデオ形式でないと再生できません。したがって、実際にビデオ・データを用意するに当たり、ビデオ形式を十分に理解していないと、ブラウザで再生できないデータを作ってしまうことになります。

 よく、ファイルの拡張子を見て、そのファイル形式を判断しますが、映像や音声に関しては、それだけでは完全に区別することができません。例えば、.mp4 という拡張子のファイルなら、すべてのファイルのビデオ形式が同じであるとは限らないのです。

 一般によく使われる MIME タイプも同様です。通常、拡張子 .mp4 に対して video/mp4 が割り当てられますが、この情報だけでは、ビデオ形式を完全に区別することができません。ビデオ形式を完全に区別するためには、映像のコーデック、音声のコーデック、コンテナの情報が必要なのです。

 まず、映像や音声は、コーデックというものが重要な要素となります。コーデックとは、映像や音声を、いかにしてデジタルデータに収めるかを決めた方式のことを指します。コーデックは、場合によっては、ソフトウェアなどを指す場合もありますが、ここでは、方式を指すものとして使います。

 コーデックには、さまざまな種類があります。なぜなら、映像や音声をデータに収めるといっても、映画のフィルムのように1コマずつ静止画像データを集めれば良いというものではないからです。そのようなことをしてしまうと、ビデオデータのサイズが非常に大きくなってしまいます。そのため、いかに人の目に出来る限りわかりにくい所で情報を減らして、できる限り小さいデータで動画を再現できるかが重要なのです。データを小さく、しかし、映像や音声クォリティーを下げないという相反する課題に、多くのソフトウェア・ベンダーやコミュニティーがしのぎを削って取り組み、さまざまなコーデックを開発しています。

 なお、ビデオは、映像と音声の両方を伴います。そのため、このコーデックも、映像用と音声用がそれぞれ必要になります。

 mp4 形式には、映像コーデックなら、H.264 Simple baseline profile、H.264 Extended Profile、MPEG-4 Visual Simple Profile Level 0、MPEG-4 Advanced Simple Profile Level 0 など、さまざまなものがあります。MPEG-4 という規格がありますが、この規格は非常に広範囲な領域を含んでいますので、ビデオの形式を表すには不適切です。例えば、この MPEG-4 という規格には、もともと映像コーデックが規定されています。これも MPEG-4 と呼ばれているため、混乱するのですが、さらに、もうひとつ別の映像コーデックも規定されています。これも MPEG-4 と呼ばれているため、混乱するのですが、さらに、もうひとつ別の映像コーデックも規定されています。それは H.264 です。H.264 はもともとは ITU-T(国際電気通信連合電気通信標準化部門)によって勧告されたものですが、現在は MPEG-4 にも加えられ、MPEG-4 AVC と呼ばれます。

 音声に関しては、皆さんがよくご存知の AAC や MP3 といった方式があります。

 次に、コーデックが決まって、映像と音声をデータ化できたとしても、今度はそれをどのようにファイルとして格納するのかが問題になってきます。このデータを格納するのがコンテナと呼ばれるものです。ビデオ・ファイルの拡張子は、主にコンテナの種類を表しています。.mp4 であれば MP4 というコンテナを表します。それ以外にも、Ogg といったものがあります。

 コンテナの種類によって、映像と音声のコーデックは絞られますが、必ずしも 1 対 1 で結び付けられるわけではありません。MP4 には、映像コーデックに H.264 や MPEG-4 などを使うことができますし、音声コーデックに ACC や MP3 を使うことができます。

 以上の、映像のコーデック、音声のコーデック、コンテナのすべてにブラウザが対応していないと再生できないのです。

ブラウザがサポートするビデオ形式

 すでに、Firefox、Safari、Chrome は video 要素に対応しています。とはいえ、すべてのビデオ形式を再生できるわけではありません。さらに、現状ではブラウザによってサポートするビデオ形式が統一されていないという問題があります。

 そのため、現在のところ、さまざまなブラウザからアクセスされるパソコン向けのサイトで video 要素を使うのは難しいといえるでしょう。しかし、iPhone のような特定のデバイス向けのサイトであれば、ブラウザの差異を考慮する必要がないため、現時点でも利用価値があると言えます。

 当初、HTML5 仕様に、ブラウザがサポートするべきビデオ・コーデックを規定しようという試みがありました。そうすることで、1つのビデオ形式に対応したビデオ・ファイルを用意するだけで、HTML5 に対応したブラウザであれば、どれでも再生可能となるわけです。HTML5 では、映像コーデック、音声コーデック、コンテナの組み合わせとして、H.264 - ACC - MP4 や Theora - Vorbis - Ogg などが候補に挙がっています。

 ところが、各ブラウザ・ベンダーの意見がまとまらず、現在のところは HTML5 仕様からビデオ・コーデックの規定が削除されています。将来的に、ビデオ・コーデックが規定されることが望ましいと言えますが、現在のところ、それはどうなるかわかりません。

 現時点で video 要素に対応しているブラウザがサポートする代表的なビデオ形式は以下のとおりです。

ブラウザの対応ビデオ形式↓
映像 音声 コンテナ Firefox Safari Chrome
H.264 AAC MP4 ×
H.264 MP3 MP4 ×
MPEG-4 AAC MP4 × ×
Theora Vorbis Ogg ×

 映像コーデックとしては、Firefox は Theora のみに、Safari は H.264 と MPEG-4 に、Chrome は Theora、H.264 に対応しています。

source 要素で複数のビデオ形式に対応する

上記のように、現状、ブラウザによって対応するビデオ形式が異なるため、1つのビデオ・データであらゆるブラウザに対応することはできません。しかし、ブラウザごとに対応するビデオ・データをそれぞれ用意すれば、source 要素を使うことで、いずれのブラウザでもビデオを再生できるようになります。

source 要素のマークアップ例

<video controls="controls">
  <source src="theora_vorbis.ogg" type="video/ogg" />
  <source src="h264_aac.mp4" type="video/mp4" />
  <p>ご利用のブラウザでは再生できません。<a href="h264_aac.mp4">こちら</a>からダウンロードして下さい。</p>
</video>

 これまでの例では video 要素の src コンテンツ属性にビデオ・ファイルの URL を指定しましたが、source 要素の src コンテンツ属性で指定することも可能です。

 source 要素は、 video 要素や audio 要素の中でしか使うことができません。type コンテンツ属性には、ビデオ・データの MIME タイプを指定します。この例のように、複数の source 要素を指定することができます。

 この例では、まず、最初の source 要素で指定されている theora_vorbis.ogg の再生が試みられます。もし再生ができなければ、次の source 要素で指定されている h264_aac.mp4 の再生が試みられます。

 したがって、Firefox と Chrome では、theora_vorbis.ogg が再生されることになります。Safari では、theora_vorbis.ogg を再生できませんので、次の h264_aac.mp4 が再生されることになります。video 要素に対応していないブラウザでは、source 要素の後にマークアップされている p 要素のコンテンツが表示されることになります。

 source 要素の type コンテンツ属性は必須ではありませんが、ブラウザがそれを参考にして動作を決定することが期待されていますので、入れておくのが良いでしょう。source 要素の type コンテンツ属性には、コーデックを詳細に記述することも可能です。

スクリプトによるビデオ操作

 video 要素の醍醐味の 1つは、スクリプトから自由にビデオを操作できることです。

 ここでは、ブラウザが用意するビデオ・コントロール・インタフェースを使わずに、独自のインターフェースをスクリプトを使って用意してみましょう。このままでは役に立つサンプルではありませんが、video 要素のスクリプティングを習得するには効果的です。

 このインタフェースには、いくつかの表示欄があります。

 再生ファイル欄では、実際に、どのビデオ・ファイルがブラウザに採用されたのかを表示します。

 状態の欄では、ビデオが再生中なのか停止中なのか、また、エラーがあった場合には、そのメッセージを表示します。

 ボリュームの欄では、ボリューム(音量)のコントロールを用意します。音量を上げ下げするボタンに加え、ミュート(消音)の切り替えボタンも用意します。

 再生位置の欄では、ビデオの総再生時間に加え、現在、どの位置を再生しているのかもリアルタイムで表示します。

 コントロールの欄では、再生と停止のボタンに加え、コマボタンを加えています。コマボタンを押すと、ビデオ再生を一時停止し、ボタンを押すごとに 1秒ずつ表示するコマの位置を進めます。

スクリプトによるビデオ操作のサンプル画像のマークアップ例

<video id="video">
<p>ご利用のブラウザでは再生出来ません。<a href="vdos/total_solar_eclipse.mp4" title="皆既日食動画">こちら</a>からダウンロードして下さい。</p>
</video>
<dl>
  <dt>再生ファイル</dt>
  <dd id="src">-</dd>
  <dt>状態</dt>
  <dd id="state">-</dd>
  <dt>ボリューム</dt>
  <dd>
   <button id="voldn">↓</button>
   <span id="vol">-</span> / 10
   <button id="volup">↑</button>
   <button id="volmt">ミュート</button>
  </dd>
  <dt>再生位置</dt>
  <dd><span id="time">0</span>秒 / <span id="duration">-</span>秒</dd>
  <dt>コントロール</dt>
  <dd>
   <button id="play">再生</button>
   <button id="pause" disabled="disabled">停止</button>
   <button id="step">コマ</button>
  </dd>
</dl>

 video 要素には、controls コンテンツ属性を指定していません。そのため、この例では、ブラウザが実装しているコントロール・インタフェースは表示されません。

 また、video 要素に src コンテンツ属性を指定していません。さらに、video 要素の中に、source 要素を入れていません。つまり、マークアップ上は、ビデオ・ファイルが一切指定されていないことになります。これは、後ほど、スクリプト側で、どのようにして再生可能なファイルを判別できるのかをご覧頂くために、あえて、そうしています。特にスクリプトを使って再生ファイルの選定をする必要がなければ、source 要素を使うのが良いでしょう。

 次に、ここで使ったスクリプトですが、head 要素の中の script 要素の中に直接入れても構いませんし、別ファイルとして用意して、それを script 要素の src コンテンツ属性でロードしても構いません。どちらでも動作するように作られています。

スクリプトによるビデオ操作のサンプル画像のスクリプト例

(function () {

var video = null;

window.addEventListener("load", function() {
  video = document.getElementById("video");
  /* 状態表示 */
  video.addEventListener("loadstart", updateState, false);
  video.addEventListener("loadeddata", updateState, false);
  video.addEventListener("play", updateState, false);
  video.addEventListener("playing", updateState, false);
  video.addEventListener("pause", updateState, false);
  video.addEventListener("ended", updateState, false);
  video.addEventListener("waiting", updateState, false);
  video.addEventListener("error", updateState, false);
  /* 再生ファイル表示 */
  video.addEventListener("loadeddata", showSrc, false);
  /* 音量表示 */
  showVol();
  video.addEventListener("volumechange", showVol, false);
  /* ミュート */
  document.getElementById("volmt").addEventListener("click", volMt, false);
  /* 音量上げ */
  document.getElementById("volup").addEventListener("click", volUp, false);
  /* 音量下げ */
  document.getElementById("voldn").addEventListener("click", volDn, false);
  /* 総再生秒数表示 */
  showDuration();
  video.addEventListener("loadeddata", showDuration, false);
  /* 現在再生秒数表示 */
  video.addEventListener("timeupdate", showTime, false);
  /* 再生 */
  document.getElementById("play").addEventListener("click", playVideo, false);
  /* 停止 */
  document.getElementById("pause").addEventListener("click", pauseVideo, false);
  /* コマ */
  document.getElementById("step").addEventListener("click", stepVideo, false);
  /* ビデオ・ファイルの選定 */
  var files = {
   "video/mp4" : "vdos/total_solar_eclipse.mp4",
   "video/ogg" : "vdos/total_solar_eclipse.ogg"
  };
  for( var type in files ) {
   if( /^(maybe|probably)/.test( video.canPlayType(type) ) ) {
    video.src = files[type];
    break;
   }
  }
  if( ! video.src ) { return; }
  video.load();
}, false);

/* 状態表示 */
function updateState(evt) {
  var msg = "";
  var t = "loadeddata";
  if( evt && evt.type ) {
   t = evt.type;
  }
  if( video.error ) {
   var errs = {
    1: "ユーザー操作によりフェッチを終了しました。",
    2: "ネットワークエラーが発生しました。",
    3: "デコードに失敗しました。",
    4: "指定のビデオは再生することができません。"
   };
   msg = errs[video.error.code];
  } else if( t == "loadstart" ) {
   msg = "ロードを開始しました。";
  } else if( t == "loadeddata" ) {
   msg = "再生の準備ができました。";
  } else if( t == "play" ) {
   msg = "再生を開始しました。";
  } else if( t == "playing" ) {
   msg = "再生しています。";
  } else if( t == "pause" ) {
   msg = "再生を停止しています。";
  } else if( t == "ended" ) {
   msg = "再生が終了しました。";
  } else if( t == "waiting" ) {
   msg = "サーバーからの応答を待っています。";
  }
  document.getElementById("state").innerHTML = msg;
}

/* 再生ファイル表示 */
function showSrc(evt) {
  document.getElementById("src").innerHTML = video.currentSrc;
}

/* 音量表示 */
function showVol(evt) {
  document.getElementById("vol").innerHTML = video.volume.toFixed(1) * 10;
  document.getElementById("volmt").innerHTML = video.muted ? "消音解除" : "消音";
}

/* ミュート */
function volMt(evt) {
  video.muted = video.muted ? false : true;
}

/* 音量上げ */
function volUp(evt) {
  vol = video.volume + 0.1;
  vol = vol.toFixed(1);
  if( vol > 1 ) { vol = 1; }
  video.volume = vol;
}

/* 音量下げ */
function volDn(evt) {
  vol = video.volume - 0.1;
  vol = vol.toFixed(1);
  if( vol < 0 ) { vol = 0; }
  video.volume = vol;
}

/* 総再生秒数表示 */
function showDuration() {
  var el = document.getElementById("duration");
  el.innerHTML = video.duration.toFixed(3);
}

/* 現在再生秒数表示 */
function showTime(evt) {
  var el = document.getElementById("time");
  el.innerHTML = video.currentTime.toFixed(3);
}

/* 再生 */
function playVideo(evt) {
  evt.target.disabled = true;
  document.getElementById("pause").disabled = false;
  video.play();
}

/* 停止 */
function pauseVideo(evt) {
  evt.target.disabled = true;
  document.getElementById("play").disabled = false;
  video.pause();
}

/* コマ */
function stepVideo(evt) {
  video.pause();
  video.currentTime += 1;
}

})();

 このスクリプトで使われている IDL 属性やメソッドを詳しく見て行きましょう。

イベント

 ビデオをスクリプトで扱うためには、イベントが重要です。例では、次のようなコードで、イベント・リスナーをセットしています。

イベント・リスナーのセット

video.addEventListener("pause", updateState, false);

 video 要素や audio 要素には、数多くのイベントが規定されていますが、ここでは、例で使ったイベントに絞って紹介します。

代表的なメディア要素のイベント↓
イベント名 概要
loadstart

このイベントは、ブラウザが、どのメディア・ファイルを採用するのかを選定し始めた時に発生します。この時点では、どのファイルを採用するのか決まっていない状態です。

loadeddata

このイベントは、ブラウザがメディア・ファイルをダウンロードして、最初のフレームを表示できた時点で発生します。この時点で、メディア・ファイルの再生の準備が整ったことになります。ただし、まだ次のフレームの状態をダウンロードできているわけではないため、再生ボタンを押しても、待たされる可能性はあります。

play

このイベントは、メディア・ファイルの再生が開始された時に発生します。このイベントが発生したタイミングで、pause IDL 属性の値が true から false に切り替わります。

playing

このイベントは、メディア・ファイルの再生が開始された時に発生します。play イベントとは違い、このイベントが発生した時には、すでに次のフレームも再生可能な状態になったことを表します。

pause

このイベントは、メディア・ファイルの再生が停止された時に発生します。

ended

このイベントは、メディア・ファイルが最後まで再生された時に発生します。

waiting

このイベントは、次に再生しようとしたフレームがまだ利用可能になっていないときに発生します。このイベントが発生した時には、一時的にメディア・ファイルの再生が停止した状態になります。この状況の例としては、メディア・ファイルのダウンロードが、再生の速度に追いつかない時が挙げられます。

error

このイベントは、メディア・ファイルのダウンロードにおいてエラーに遭遇した時に発生します。

volumechange

このイベントは、音量が変更された時、または、ミュート状態が変更された時に、発生します。具体的には、volume IDL 属性または muted IDL 属性の値が変わった時に、このイベントが発生します。

timeupdate

このイベントは、メディア・ファイルの再生位置が変わっている最中に連続して発生します。つまり、メディア・ファイルが再生されている間は、常にこのイベントが発生します。フレームごとに発生するのではありませんので、注意してください。ブラウザによって、このイベントの発生タイミングは異なります。

ビデオ・ファイルの選定

ブラウザによって、どのようなコーデックのメディア・ファイルを再生できるのかが違うため、スクリプトによって、それを判定する必要が出てくる場合もあるでしょう。その場合、canPlayType() メソッドを使います。

ビデオ・ファイルの選定コード

var files = {
  "video/ogg" : "test.ogg",
  "video/mp4" : "test.mp4"
};
for( var type in files ) {
  if( /^(maybe|probably)/.test( video.canPlayType(type) ) ) {
   video.src = files[type];
   break;
  }
}
if( ! video.src ) { return; }
video.load();

 canPlayType() メソッドは、引数に MIME タイプを指定します。そして、このメソッドは、指定のタイプのメディア・ファイルを再生することができるかどうかをを文字列で返します。もし再生できそうだと判断されれば、maybe または probably を返し、再生できないと判断されれば空文字列が返されます。

 前述のとおり、MIME タイプだけではコーデックが判別できないため、maybe または probably といった曖昧な表現で返されるのです。"video/ogg" や "video/mp4" のような MIME タイプを指定した場合、通常は maybe が返されます。それに対して、"video/mp4; codecs=avc1.42E01E, mp4a.40.2" のように、コーデックまで指定した MIME タイプであれば、probably が返される可能性があります。コーデックを指定した MIME タイプについては、source 要素のページで説明予定です。

 例では、canPlayType() メソッドが maybe または probably のいずれかを返せば、それは再生可能と見なして処理しています。処理可能であれば、そのメディア・ファイルのアドレスを video 要素の src IDL 属性にセットします。

 通常は、src IDL 属性にメディア・ファイルのアドレスをセットした時点で、そのファイルのロードが開始されますが、例では、念のために、明示的に load() メソッドを使ってロードを指示しています。

状態表示

 メディア・要素の再生に関して、その状態を把握するために、例では様々なイベントの発出をトリガーに、その時点の状況をレポートしています。

状態表示のスクリプト

function updateState(evt) {
  var msg = "";
  var t = "loadeddata";
  if( evt && evt.type ) {
   t = evt.type;
  }
  if( video.error ) {
   var errs = {
    1: "ユーザー操作によりフェッチを終了しました。",
    2: "ネットワークエラーが発生しました。",
    3: "デコードに失敗しました。",
    4: "指定のビデオは再生することができません。"
   };
   msg = errs[video.error.code];
  } else if( t == "loadstart" ) {
   msg = "ロードを開始しました。";
  } else if( t == "loadeddata" ) {
   msg = "再生の準備ができました。";
  } else if( t == "play" ) {
   msg = "再生を開始しました。";
  } else if( t == "playing" ) {
   msg = "再生しています。";
  } else if( t == "pause" ) {
   msg = "再生を停止しています。";
  } else if( t == "ended" ) {
   msg = "再生が終了しました。";
  } else if( t == "waiting" ) {
   msg = "サーバーからの応答を待っています。";
  }
  document.getElementById("state").innerHTML = msg;
}

 ここで注目してほしいのは、エラーの把握です。video 要素には error IDL 属性が規定されています。この IDL 属性は、メディア・ファイルのロードにおいて、何かしらエラーが発生した時だけにオブジェクトとして読み取ることができるようになります。もし何もエラーがなければ、null になります。

 もしエラーが発生すると、video.error.code で、そのエラー・コードを取り出すことができます。エラー・コードは 1 から 4 までの整数のいずれかとなり、それぞれの値の意味は下表のとおりです。

コード 意味
1 ユーザーのリクエストによって、メディア・ファイルのロードが中止された
2 ネットワーク・エラー
3 デコード・エラー
4 src IDL 属性の値が不適切

再生ファイル表示

 ブラウザによって、どのメディア・ファイルが選択されて再生されてるのかをスクリプトから把握するには、currentSrc IDL 属性を使います。

再生ファイルを表示するコード

function showSrc(evt) {
  document.getElementById("src").innerHTML = video.currentSrc;
}

 この IDL 属性では、video 要素の src コンテンツ属性の値そのものではなく、http:// から始まる URL に変換された値が返されます。

音量表示

 音量は、volume IDL 属性から把握することができます。ただし、volume IDL 属性から得られる値は、0 から 1 までの浮動小数点数となります。0 は音が聞こえない状態を表し、1 は最大音量を表します。

音量を表示のコード

function showVol(evt) {
  document.getElementById("vol").innerHTML = video.volume.toFixed(1) * 10;
  document.getElementById("volmt").innerHTML = video.muted ? "消音解除" : "消音";
}

 この例では、ミュート(消音)についてもサポートしています。muted IDL 属性から、現在、ミュート中なのか、そうでないのかを把握することができます。この属性は、ミュート中であれば true を、そうでなければ false を返します。

 なお、音量とミュートは連動するものではありませんので注意してください。ミュートが有効になっている場合、たとえ、音量が 1 (最大音量)だとしても、音が聞こえない状態になります。つまり、音量に関わらず、ミュート状態が優先されることになります。

音量の変更

 音量は、volume IDL 属性に値をセットすることで変更することができます。0 から 1 までの数値を指定します。ただし、この範囲外の数値を指定するとエラーになりますので、注意してください。

音量を変更するコード

/* 音量上げ */
function volUp(evt) {
  vol = video.volume + 0.1;
  vol = vol.toFixed(1);
  if( vol > 1 ) { vol = 1; }
  video.volume = vol;
}

/* 音量下げ */
function volDn(evt) {
  vol = video.volume - 0.1;
  vol = vol.toFixed(1);
  if( vol < 0 ) { vol = 0; }
  video.volume = vol;
}

 この例では、ボタンが押されると、volume IDL 属性の値に 0.1 を足す、または 0.1 を引く処理を行なっています。ただし、0 から 1 の範囲を超えてしまった場合は、エラーにならないよう、1 もしくは 0 にセットし直しています。

総再生秒数と現在再生秒数の表示

 再生中のメディア・ファイルの尺(長さ)は duration IDL 属性から、現在の再生位置は currentTime IDL 属性から、いずれも秒数で取得することができます。実際に取得される値は、浮動小数点数です。

再生位置を表示するコード

/* 総再生秒数表示 */
function showDuration() {
  var el = document.getElementById("duration");
  el.innerHTML = video.duration.toFixed(3);
}

/* 現在再生秒数表示 */
function showTime(evt) {
  var el = document.getElementById("time");
  el.innerHTML = video.currentTime.toFixed(3);
}

 この例では、得られた秒数をミリ秒(小数点以下 3桁)となるよう丸めています。

再生と停止

 play() メソッドを呼び出すと再生が開始され、pause() メソッドを呼び出すと停止します。これらのメソッドに引数はありません。

再生と停止のコード

/* 再生 */
function playVideo(evt) {
  evt.target.disabled = true;
  document.getElementById("pause").disabled = false;
  video.play();
}

/* 停止 */
function pauseVideo(evt) {
  evt.target.disabled = true;
  document.getElementById("play").disabled = false;
  video.pause();
}

再生位置の変更

 currentTime IDL 属性に秒数をセットすると、現在再生位置が指定の秒数の位置に変更されます。

再生位置指定のコード

function stepVideo(evt) {
video.pause();
video.currentTime += 1;
}

 この例では、「コマ」ボタンを押すことで、pause() メソッドで一時停止をして、その時点の再生位置から 1秒だけ再生位置を進めています。すでに一時停止状態になっているため、1秒進めた位置のフレームが表示され、そこで停止した状態になります。

より高度な機能

 以上、主要なイベントとメソッドと IDL 属性の使い方を見てきましたが、これらは HTML5 のメディア要素の規定の一部でしかありません。これら以上に、早送りや巻き戻しといった機能も実現することができます。

 これらの詳細については、下記のサイトを参考にしてみてください。