HTML

A simple tag to put a video on your page with built-in controls, plus easy options for muted autoplay, a poster image, and captions.

video 要素

Webページに動画を置いて再生ボタンを出すためのタグで、静音の自動再生やサムネ表示(poster)、字幕(track)などもシンプルな記述で扱える。

video要素の基本的な使い方

video要素の基本的な使い方は以下の通りです。このコードは、Webページ上に動画を埋め込み、再生、停止、音量調整などのコントロールを提供します。

HTML

<div class="videoPlace">
	<video controls>
		<source src="sample.mp4" type="video/mp4">
		<p>お使いのブラウザはvideoタグに対応していません。</p>
	</video>
</div>

CSS

div.videoPlace {
	text-align: center;
}
video {
	max-width: 96%;
	height: auto;
	margin-top: 1em;
}
<video controls></video>
video要素を定義し、コントロール(再生、停止、音量調整など)を有効にします。
<source src="sample.mp4" type="video/mp4">
動画ファイルのソースを指定します。この例では、MP4形式の動画ファイルを指定しています。
<p></p>
ブラウザが video要素をサポートしていない場合に表示されるメッセージです。
a要素を使って、動画をダウンロードできるようにしておくのもいいかもしれません。
なお、この仕組みは、video要素に対応しているものの、ビデオファイルを読み取れなかったり、ビデオファイルの形式をサポートしていないなどの理由で、ビデオが再生されなかった場合のフォールバックコンテンツとしては機能しません。あくまでも、video要素を全くサポートしていないブラウザ向けのコンテンツとなることに留意してください。

動画の指定方法について

video要素で動画(sample.mp4)を指定する場合、src属性を使う方法とsource要素を使う方法があります。それぞれの違いとメリット、デメリットについて説明します。

src属性を使う方法

HTML

<video src="sample.mp4" controls>
	<p>お使いのブラウザはvideoタグに対応していません。</p>
</video>

メリット

シンプルで直感的
コードが短く、初心者でも理解しやすい。
迅速な実装
1つの動画ファイルを指定するだけなので、すぐに実装できる。

デメリット

互換性の問題
異なるブラウザがサポートする動画フォーマットが異なるため、互換性が低い。例えば、MP4をサポートしないブラウザでは動画が再生されない可能性がある。
フォールバックの欠如
src属性のみでは複数のフォーマットを指定できず、ブラウザ間での互換性が確保しにくい。

source要素を使う方法

HTML

<video controls>
	<source src="sample.mp4" type="video/mp4">
	<source src="sample.webm" type="video/webm">
	<p>お使いのブラウザはvideoタグに対応していません。</p>
</video>

メリット

ブラウザ互換性の向上
複数のフォーマットを指定できるため、異なるブラウザでの再生互換性が高まる。例えば、MP4と WebMの両方を指定することで、ほとんどのブラウザで再生可能になる。
柔軟なフォールバック
一つのフォーマットがサポートされていない場合でも、他のフォーマットで再生できるため、ユーザー体験が向上する。

デメリット

コードが複雑になる
複数の source要素を追加するため、コードが長くなり、初心者には少し理解しづらいかもしれない。
管理が煩雑
複数の動画ファイルを準備し、管理する必要があるため、制作と管理の手間が増える。

まとめ

選択する方法は、使用するプロジェクトの要件や対象とするユーザーのブラウザ環境に応じて判断すると良いでしょう。

controls

controls属性は、ユーザーに動画の再生、停止、音量調整、シーク(時間を移動する)などの基本的な操作を可能にするためのコントロールを表示するために使用されます。video要素にこの属性を追加することで、ブラウザが自動的に標準のコントロールインターフェースを表示します。

HTML

<video src="sample.mp4" controls>
	<p>お使いのブラウザはvideoタグに対応していません。</p>
</video>

この例では、controls属性が指定されているため、動画再生のコントロールが表示されます。

上記の「video要素の基本的な使い方」でも controls属性を指定しています。もし、controls属性がなかった場合は動画を再生することができなくなってしまいます。

HTML

<video src="sample.mp4">
	<p>お使いのブラウザはvideoタグに対応していません。</p>
</video>

controls属性の詳細

表示されるコントロール

controls属性を指定すると、ブラウザは以下のようなコントロールを表示します。

再生/一時停止ボタン
動画の再生と一時停止を切り替えるボタン。
シークバー
動画の再生位置を示し、ユーザーが特定の位置に移動できるバー。
音量コントロール
音量を調整するためのスライダーやボタン。
ミュートボタン
音を消すためのボタン。
全画面表示ボタン
動画を全画面表示に切り替えるボタン。

属性の有無による違い

controls を付けると、再生ボタンや音量スライダーなどの操作パネルが表示されます。

つまりこれは「動画を再生できるようにする」ためではなく、「ユーザーが操作できるようにする」ためのスイッチです。

実は controls がなくても、JavaScriptのコードで video.play() を実行すれば再生できます。

ただしユーザーが自由に操作できるUIが表示されないため、「再生ボタンが見えない=再生できない」と感じることがあります。

初心者の方は「controls は“ボタンを出すため”の設定」と覚えるのが一番わかりやすいです。

HTML

<!-- controls あり:ブラウザの操作バーが出る -->
<video controls width="640" height="360">
    <source src="movie.mp4" type="video/mp4">
</video>

<!-- controls なし:自動再生やJavaScript操作向け -->
<video autoplay muted playsinline width="640" height="360" id="v1">
    <source src="movie.mp4" type="video/mp4">
</video>

<script>
    // controls がなくても再生できる例
    document.getElementById("v1").play();
</script>

※ controls を外すと、ユーザーが一時停止や音量変更をできなくなります。自動再生や装飾デザインを優先したい場合だけ使いましょう。

メリット

使いやすさ
ユーザーが直感的に動画を操作できる。
即時性
コーディングの手間をかけずに、動画に基本的なコントロールを追加できる。
互換性
ブラウザが提供する標準のコントロールは、ほとんどのデバイスで一貫して動作する。

デメリット

カスタマイズの制限
ブラウザ標準のコントロールはデザインや機能のカスタマイズが難しい。
一貫性の欠如
ブラウザによってコントロールの外観や操作感が異なる場合がある。

autoplay 属性

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

HTML

<video src="sample.mp4" controls autoplay>
	<p>ご利用のブラウザでは再生出来ません。</p>
</video>

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

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

autoplay 属性の現実的な動作

いまのブラウザでは、「音が出る自動再生」はほとんどの環境で止められます。

そのため、ただ autoplay を付けただけでは再生が始まらないことが多いです。

自動再生を確実に動かしたい場合は、音を消す(muted) と インライン再生(playsinline) を合わせて使います。

特に iPhone や iPad では、playsinline がないと全画面再生になってしまうことがあります。

つまり、自動再生したいときの基本セットは次の3つです:

これらをまとめて指定するのがいまの標準的な書き方です。

HTML

<video autoplay muted playsinline loop poster="thumb.jpg" width="640" height="360">
    <source src="movie.mp4" type="video/mp4">
    <p>お使いの環境では動画を再生できません。<a href="movie.mp4">動画をダウンロード</a></p>
</video>

※ 音声付きで再生したい場合は、自動再生をあきらめてユーザー操作(クリックなど)で再生するのが安全です。

ポスター・フレーム

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

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

HTML

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

字幕(captions)の付け方

HTML

<video controls width="640" height="360" crossorigin="anonymous">
    <source src="movie.mp4" type="video/mp4">
    <track kind="captions" src="subs/ja.vtt" srclang="ja" label="日本語" default>
    <p>お使いの環境では再生できません。<a href="movie.mp4">動画をダウンロード</a></p>
</video>

ループ再生

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

HTML

<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 属性は、動画を表示する「領域のサイズ」を指定します。

このとき、動画の実際の縦横比と異なる数値を同時に指定すると、動画が歪んで表示されます。

たとえば、横長の動画に対して width="100" height="100" のように正方形を指定すると、その枠に合わせて無理に引き伸ばされます。余白はできません。

歪ませたくない場合は、次のような方法が一般的です:

例:黒帯を付けて元の比率を保つ

CSS

video {
    width: 100%;
    height: 360px;
    object-fit: contain; /* 歪めずに黒帯で調整 */
    background: #000;
}

ビデオの種類

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

よく、ファイルの拡張子を見て、そのファイル形式を判断しますが、映像や音声に関しては、それだけでは完全に区別することができません。例えば、.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 を使うことができます。

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

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

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

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

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

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

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

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

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

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

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

HTML

<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 コンテンツ属性でロードしても構いません。どちらでも動作するように作られています。

JavaScript

(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 属性やメソッドを詳しく見て行きましょう。

イベント

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

JavaScript

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() メソッドを使います。

JavaScript

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() メソッドを使ってロードを指示しています。

状態表示

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

JavaScript

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 属性を使います。

JavaScript

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

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

音量表示

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

JavaScript

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 までの数値を指定します。ただし、この範囲外の数値を指定するとエラーになりますので、注意してください。

JavaScript

/* 音量上げ */
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 属性から、いずれも秒数で取得することができます。実際に取得される値は、浮動小数点数です。

JavaScript

/* 総再生秒数表示 */
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() メソッドを呼び出すと停止します。これらのメソッドに引数はありません。

JavaScript

/* 再生 */
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 属性に秒数をセットすると、現在再生位置が指定の秒数の位置に変更されます。

JavaScript

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

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

FAQ

Q1. 音が出る自動再生が動きません。
A. ほとんどのブラウザが音あり自動再生を止めます。autoplay muted playsinline を使うと静音で自動再生されやすくなります。
Q2. iPhoneで勝手に全画面になるのはなぜ?
A. playsinline がないと全画面に移行することがあります。playsinline を付けて回避します。
Q3. 動画が縦につぶれたり横に伸びます。
A. widthheight を無理やり指定すると歪みます。どちらか片方のみ指定か、CSSの object-fit: contain を使ってください。
Q4. MP4なのに再生できません。
A. 拡張子だけでは中身(コーデック)が一致しないことがあります。H.264(映像)+AAC(音声) で作り直すと解決することが多いです。
Q5. 通信量を抑えたい。
A. preload="metadata" または none を使います。自動再生するなら結局データを取りに行く点に注意。

よくあるエラー早見表

MediaError 1: ABORTED
ユーザー操作などで読み込みが中断。→ リロード/再試行。
MediaError 2: NETWORK
ネットワーク障害。→ 回線・URL・CORSヘッダーを確認。
MediaError 3: DECODE
コーデック不一致や壊れたファイル。→ H.264/AACで再エンコード。
MediaError 4: SRC_NOT_SUPPORTED
ファイル形式やMIMEが不適切。→ <source type> と実体を見直し。
AutoplayPolicyError
自動再生がポリシーで拒否。→ muted playsinline を追加。
CORSエラー
別ドメイン配信で許可不足。→ crossorigin="anonymous" とサーバ側CORS設定。