MediaElement.jsを使った複数の動画を順番に再生させる【jQuery】

ちょいと動画に関してクロスブラウザに対応させなければならないことがありまして、MediaElement.jsを使うと便利だったという話です。HTML5のvideo要素を使うことが前提です。

MediaElement.js

MediaElement.jsの説明ですが、動画をクロスブラウザに対応させることができるJavaScriptライブラリです。

動画となると各ブラウザごとにサポートしている動画フォーマットはバラバラです。かといって対応しているブラウザごとに動画ファイルを用意するのもメンドーです。>今回用いた動画フォーマットはMP4だけです。MP4だとFirefoxとOperaとIE8以下がサポートしていません。当然ながら、何もしなければこれらのブラウザでは動画が再生されません。

しかし、MediaElement.jsを使うことで、MP4をサポートしていないブラウザでもMP4を再生してくれるようになります。(これはFlashを通してMP4を再生してくれます。)

使用方法

MediaElement.jsにアクセスして、最新版をダウンロードします(2012年11月30日の時点で最新バージョンは、2.10.0です。)。

CSSとJSファイルの設置

zipを解凍して、mediaelementplayer.cssとmediaelement-and-player.min.jsを指定します。今回はjQueryを使う想定なので、jQueryも指定しています。

<link rel="stylesheet" href="css/mediaelementplayer.css">
<script src="js/jquery.js"></script>
<script src="js/mediaelement-and-player.min.js"></script>

画像ファイルとSVGファイルとswfファイル

zipを解凍すると「build」フォルダの中に以下のファイルがあります。これらのファイルも必要なので、任意のフォルダに移動します。

pngとsvgは、CSSと同ディレクトリの記述がされているので、パスの変更のためmediaelementplayer.cssを修正しなければいけないので、めんどくさがりの私のような人は、CSSと同ディレクトリにおいとくとよいです。swfファイルは、どこでもよいですが、私はJSディレクトリにおいています。

  • flashmediaelement.swf
  • background.png
  • bigplay.png
  • bigplay.svg
  • controls.png
  • controls.svg
  • controls-ted.png
  • controls-wmp.png
  • controls-wmp-bg.png

HTML

HTMLは以下のように、4つの動画になります。これら順に再生していくというものです。

<video id="player1" width="640" height="320">
    <source type="video/mp4" src="video/movie1.mp4">
</video>


<video id="player2" width="640" height="320">
    <source type="video/mp4" src="video/movie2.mp4">
</video>


<video id="player3" width="640" height="320">
    <source type="video/mp4" src="video/movie3.mp4">
</video>

<video id="player4" width="640" height="320">
    <source type="video/mp4" src="video/movie4.mp4">
</video>

jQuery

まず、MP4に対応していないブラウザ向けに、MP4を再生できるようにする記述をします。今回はjQueryを使うので、以下のような記述になります。

$('video').mediaelementplayer({
	flashName: 'flashmediaelement.swf'
});

さきほどのswfファイルを指定します。たったこれだけで、MP4に対応していないブラウザでもMP4を再生できるようになります。

オプション等は、本サイトのほうにありますので、参考ください。

最初の動画以外を非表示

それでは、順番に動画を再生していくようにスクリプトを書いていきます。最初の動画以外を非表示にするところから始めます。ちなみに、Flashで再生されるブラウザには、以下のことは動きませんのでご了承ください。

MediaElement.jsを使うと以下のようなHTMLが生成されます。

<div id="mep_0" class="mejs-container svg mejs-video" style="width: 640px; height: 320px; display: block;">
<div class="mejs-inner">
<div class="mejs-mediaelement">
<video id="player1" width="640" height="320" src="video/movie1.mp4">
    <source type="video/mp4" src="video/movie1.mp4">
</video>
</div>
<div class="mejs-layers">
<div class="mejs-poster mejs-layer" style="display: none; width: 640px; height: 320px;">
</div>
・
・
・
あと省略

そのため、以下のような記述をします。

$(".mejs-video:not(:first)").css("display", "none");

id属性の値を取得

今回は、動画が4つでしたが、運用次第では、3つになるかもしれませんし、5つになるかもしれません。そのため汎用的にできるように、id属性の値を取得します。

var id_values = [];

for(var i = 0; i < $(".mejs-video").length; i++) {
	id_values.push($(".mejs-video video").eq(i).attr("id"));
}

ページがロードしたときに、一番目の動画を再生

正確にいうと動画が再生可能になったときに、一番目の動画が自動的に再生するようにします。その状態を取得できるイベントが loadeddataですので、これを用います。

$("video#" + id_values[0]).on("loadeddata", function(){
	$(this).get(0).play()
})

video要素のイベント一覧は、video要素、audio要素をJavaScriptから操作する-HTML5のAPI、および、関連仕様が参考になります。

動画の再生が終えたら、次の動画を表示して再生するようにする

一番めの動画の再生が終えたら、一番めの動画が非表示になり、ニ番めの動画が表示され、自動で再生され、再生が終えたら、非表示になって、三番目の動画が表示され、自動で再生され、再生が終えたら、非表示になって、最後の動画までいったら、最初に戻るというループ処理を行います。

動画の再生が終えたということの取得できるendedというイベントを使います。

var duration = 'normal';
$.each(id_values, function(i, value){
	$("video#" + id_values[i]).on('ended', function(){
		if($(".mejs-video:last").css("display") !== "block") {
			$(".mejs-video").eq(i).fadeOut(duration, function(){
				$(this).next().fadeIn(duration, function(){
					$("video#" + id_values[i+1]).get(0).play();
				})
			});
		} else {
			$(".mejs-video:last").fadeOut(duration, function(){
				$(".mejs-video:first").fadeIn(duration, function(){
					$("video#" + id_values[0]).get(0).play()
				})
			});
		}
	});
})

デモも用意せず、非常に不親切ですが(動画素材を公開することができないので)、最後に全スクリプトを残します。

(function($) {
	var id_values = [];
	var duration = 'normal';

	$('video').mediaelementplayer({
		flashName: 'flashmediaelement.swf'
	});

	$('.mejs-video:not(:first)').css('display', 'none');

	for(var i = 0; i < $('.mejs-video').length; i++) {
		id_values.push($('.mejs-video video').eq(i).attr('id'));
	}

	$('video#' + id_values[0]).on('loadeddata', function(){
		$(this).get(0).play();
	});


	$.each(id_values, function(i, value){
		$('video#' + id_values[i]).on('ended', function(){
			if($('.mejs-video:last').css('display') !== 'block') {
				$('.mejs-video').eq(i).fadeOut(duration, function(){
					$(this).next().fadeIn(duration, function(){
						$('video#' + id_values[i+1]).get(0).play();
					})
				});
			} else {
				$('.mejs-video:last').fadeOut(duration, function(){
					$('.mejs-video:first').fadeIn(duration, function(){
						$('video#' + id_values[0]).get(0).play()
					})
				});
			}
		});
	});


})(jQuery);