レベル: 中級 Jack D Herrington (jherr@pobox.com), Senior Software Engineer, Leverage Software Inc.
2007年 10月 23日 幅広く利用可能なブロードバンド・メディアの出現により、ムービー、画像、そして音声が Web 2.0 革命の原動力となっています。この記事で、メディアに PHP や Ajax (Asynchronous JavaScript™ + XML) などの技術を組み合わせてカスタマーに魅力的なエクスペリエンスを提供する方法を学んでください。
Web 上のアプリケーションの新たな潮流をもっとも顕著に表わすサイトは何かと尋ねたら、ほとんどの人が YouTube と答えるでしょう。YouTube は新しい技術を魅力的な方法で採り入れていただけでなく、私たちのメディアに対する考え方、そしてメディアとの関わり方を一変したサイトです。大きな話題は従来のメディアで報道されるよりかなり前に YouTube で先取りできることがあります。そのような話題がないとしても、YouTube は世界に向けた 1 つの大掛かりな TiVo (訳注: 米国で高いシェアを誇るデジタル・ビデオ・レコーダー) のように機能します。
今やメディア共有が世界を変えていますが、これは技術の点からすれば難しいことではありません。この記事では、単純な Web ビデオ・ホスティング・アプリケーションに Ajax フロントエンドを装備する方法を紹介します。
単純なビデオ選択
まず取り掛かるのは、ムービー・リストを保持し、そのリストを使って複数のムービーのうちの 1 つを選択するという Web サイトです。このサイトでは、ページ間を移動しなくてもムービーを変更することができます。リスト 1 に、このページのコードを記載します。
リスト 1. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<div id="movieHost">
</div>
<div id="movieList">
</div>
<script>
function setMovie( url )
{
$('movieHost').innerHTML = '';
var elEmbed = document.createElement( 'embed' );
elEmbed.src = url;
$('movieHost').appendChild( elEmbed );
}
new Ajax.Request( 'movies.xml', {
method: 'get',
onSuccess: function( transport ) {
var movieTags = transport.responseXML.getElementsByTagName( 'movie' );
$('movieList').innerHTML = '';
var bFirst = true;
for( var b = 0; b < movieTags.length; b++ ) {
var url = movieTags[b].getAttribute('url');
var title = movieTags[b].getAttribute('title');
if ( bFirst )
{
setMovie( url );
bFirst = false;
}
var html = '<a href="javascript:void setMovie(\''+url+'\');">';
html += title+'</a><br/>';
$('movieList').innerHTML += html;
}
}
} );
</script>
</body>
</html>
|
このページでは優れた JavaScript ライブラリー、Prototype.jsを利用して movies.xml データ・ソースの Ajax リクエストを行います。データが返されると、コードは getElementsByTagName() メソッドを使ってすべてのムービー・タグを検出し、ムービー・タグごとに URL と タイトルの両方を取得します。取得したタグがリストの先頭のムービーに対応する場合は、スクリプトが早速そのムービーを再生します。そうでない場合には、movieList <div> タグにムービー・セレクターとして機能するアンカー・タグを追加します。
このムービー・セレクター・アンカーは、setMovie() 関数を呼び出して特定のムービーを開始します。ムービーを開始する方法としては、movieHost <div> タグの中身を空に設定することで以前に再生したムービーを除去し、それからこのコンテンツをムービー・リストで指定された URL を持つ <embed> タグに設定しているだけです。
<embed> タグはムービーをページに配置するのにもっとも簡単な手段ですが、ブラウザー間で問題が生じる可能性があります。代わりに、<object> タグと <embed> タグを併せて使用するというオプションもあります (さらにもう 1 つの手段は、Macromedia Flash Player を使用することです。これについてはもう少し後で説明します)。
上記の単純な例で使用している movies.xml ファイルは単なるフラット・ファイルで、私が撮った短いムービーへの参照がいくつかあるだけです。リスト 2 にこのファイルを記載します。
リスト 2. movies.xml
<movies>
<movie url="spider.mov" title="Spider" />
<movie url="swing.mov" title="Swing Set" />
<movie url="water.mov" title="Water Splash" />
</movies>
|
このページにナビゲートすると、図 1 のようなページが表示されます。
図 1. 単純なムービー・リスト・ページ
<embed> タグによって再生中のムービーはページの先頭に配置され、その下に選択可能なムービーのリストが表示されます。いずれかのリンクをクリックすると、クリックしたムービーが代わりに再生されます。
このシステムを大規模なビデオ・リポジトリーに拡張するには明らかに無理があります。そこで必要になってくるのが、ムービー・リストで検索を行うための手段です。
検索可能なムービー・リスト
リスト 3 を見るとわかるように、検索機能を追加するには検索ボックスを追加する必要があります。ここでは q という名前の検索入力フィールドも追加しています。
リスト 3. 検索機能の追加
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<table><tr><td valign="top">
<input type="text" id="q" onkeyup="search()">
<div id="movieList">
</div>
</td><td valign="top">
<div id="movieHost">
</div>
</td>
</tr></table>
<script>
function setMovie( url )
{
$('movieHost').innerHTML = '';
var elEmbed = document.createElement( 'embed' );
elEmbed.src = url;
$('movieHost').appendChild( elEmbed );
}
function search()
{
new Ajax.Request( 'search.php?q='+escape($('q').value), {
method: 'get',
onSuccess: function( transport ) {
var movieTags = transport.responseXML.getElementsByTagName( 'movie' );
$('movieList').innerHTML = '';
var bFirst = true;
for( var b = 0; b < movieTags.length; b++ ) {
var url = movieTags[b].getAttribute('url');
var title = movieTags[b].getAttribute('title');
if ( bFirst )
{
setMovie( url );
bFirst = false;
}
var html = '<a href="javascript:void setMovie(\''+url+'\');">';
html += title+'</a><br/>';
$('movieList').innerHTML += html;
}
}
} );
}
</script>
</body>
</html>
|
キー・アップ・イベントで呼び出すメソッドには、search() を指定しました。この search() メソッドは Ajax.Request 呼び出しと似ていますが、この場合は search.php というページにクエリー・ストリングを渡すようになっています。search.php スクリプトが返す XML フォーマットは元のフォーマットと同じなので、XML 構文解析を行うコードを変更する必要はありません。
正直なところ、私の好みからするとキー・アップと同時に search() 関数を呼び出すのは応答が良すぎる感があります。それよりも、システムが検索を実行するまで 1 秒くらい待機し、その間に検索テキストを入力し終えることができれば理想的です。そうすれば、入力中にリストの表示が度々変わることもありません。このような振る舞いは、window.setTimeout() メソッドを使用すれば簡単に実装することができます。
リスト 4 は、修正後の search.php スクリプトです。
リスト 4. search.php
<?php
header( 'content-type: text/xml' );
$movies = array();
$movies['spider.mov'] = 'Spider';
$movies['swing.mov'] = 'Swing Set';
$movies['water.mov'] = 'Water Splash';
?>
<movies>
<?php
foreach( $movies as $k => $v ) {
if ( strlen( $_GET['q'] ) > 0 &&
preg_match( '/'.$_GET['q'].'/i', $v ) ) {
?>
<movie url="<?php echo($k) ?>" title="<?php echo($v) ?>" />
<?php
} }
?>
</movies>
|
スクリプトの先頭に配列を作成し、そこにすべてのムービーが保持されるようにしています。簡単のためムービーはハードコーディングしましたが、実際には、これらの要素はムービー・リストのデーターベースから取得されることになるはずです。
次にコードはリスト内で繰り返し処理を行って、各ムービー・タイトルに検索クエリーの正規表現を適用します。タイトルと正規表現が一致すると、URL と名前が指定された <movie> タグが出力されます。
ページを開始して s と入力すると、図 2 のページが表示されます。
図 2. 単純なクエリーによるムービー・クエリー・ページ
Delete キーを押して今度は water と入力すると、図 3 のページが表示されます。
図 3. 「water」ムービーを検索するムービー・クエリー・ページ
この記事の主な目的は DHTML (Dynamic HTML) と Ajax を使ってフロントエンドを作成する方法を説明することですが、ビデオ共有サイトを作成するにはその他にも多くのことが関わってきます。
ビデオ共有の基本
ここで少し、実際の作業から理論上の話に話題を変えて、ビデオ共有の厄介な問題に対処する方法について説明させてください。対処しなければならない主な問題としては、以下の 3 つがあります。
- ビデオの保管方法と配信方法
- さまざまなビデオ・フォーマットを処理する方法
- アップロードされたファイルからサムネール画像とビデオに関する情報を取得する方法
ビデオの保管は、特に小さなアプリケーションにとっては深刻な問題です。ビデオ・ファイルはサイズが大きいため、ビデオを保管するには高価なハードウェアが必要になります。さらに、カスタマーにビデオを配信するには帯域幅の使用料がかかります。これに対処するには、機器を購入してホスティング設備に組み込むという方法が考えられます。あるいは Amazon の S3 のようなサービスを利用すれば、あらゆる素材 (データベース・バックアップ、画像、ムービーなど) を Amazon データ・センターにアップロードして、そこから手頃な費用で配信することができます。データ・センターの展開に資金を投入する前に、このようなサービスのいずれかを調べてみる価値はあるはずです。
次の問題はビデオ・フォーマットで、これは興味深い課題となります。ビデオ・フォーマットはさまざまにありますが、すべてのプレイヤーがすべてのビデオ・フォーマットを処理するわけではないからです。実のところ、ほとんどのプレイヤーはそれぞれが選択するビデオ・フォーマットだけを処理するにすぎません。カスタマーの負担を軽くするには、特定のフォーマットを標準として、プレイヤーに入力するビデオをすべてそのフォーマットに変換するのが最善の策でしょう。この方法を実践するのにとりわけ重宝なツールは、FFmpeg というコマンドライン・アプリケーションです。このツールはビデオ・フォーマットを変換するだけでなく、フレームのスナップショットを取ることもできるので、カスタマーがビデオを見る前にサムネールを表示することができます。
どのビデオ・フォーマットを標準とするかは、厄介な選択になり得ます。現時点では明らかに Flash ビデオがもっとも有力な候補ですが、Windows Media® (特に Microsoft Silverlight (以前の WPF/Everywhere) のリリース) も着実に支持を広げています。FFmpeg はほとんどすべてのムービーを Flash ビデオ・フォーマットにエクスポートできるという点では、Flash ビデオが優勢です。また、サイトに簡単に組み込める無料のオープン・ソース Flash ムービー・プレイヤーも複数あります。これらのプレイヤーを上記のコードと組み合わせれば、Ajax フロントエンドで完全なエンド・ツー・エンドのビデオ共有ソリューションを実現できます。
その一方、Web で扱われているのはビデオだけではありません。画像共有も同じく重要です。
スライドショー
リスト 5 に、単純な DHTML ベースのスライドショーを示します。このスライドショーがデータ・ソースとしているのは XML ファイルです。
リスト 5. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body bgcolor="black">
<div style="text-align:center;">
<img id="imgItem" src="" style="display:none;"><br>
<div id="imgTitle" style="color:white;font-family:arial;font-size:24pt;">
</div>
</div>
<script>
var g_images = [];
var g_slideIndex = 0;
function showSlide()
{
$('imgTitle').hide();
$('imgItem').hide();
var height = 600;
var width = ( height / g_images[ g_slideIndex ].height ) *
g_images[ g_slideIndex ].width;
$('imgItem').src = g_images[ g_slideIndex ].src;
$('imgItem').width = width;
$('imgItem').height = height;
$('imgTitle').innerHTML = g_images[ g_slideIndex ].title;
$('imgTitle').show();
$('imgItem').show();
g_slideIndex++;
if ( g_slideIndex >= g_images.length )
g_slideIndex = 0;
}
new Ajax.Request( 'images.xml', {
method: 'get',
onSuccess: function( transport ) {
var imageTags = transport.responseXML.getElementsByTagName( 'image' );
for( var b = 0; b < imageTags.length; b++ ) {
g_images.push( {
src: imageTags[b].getAttribute('src'),
title: imageTags[b].getAttribute('title'),
width: imageTags[b].getAttribute('width'),
height: imageTags[b].getAttribute('height')
} );
}
showSlide();
window.setInterval( showSlide, 5000 );
}
} );
</script>
</body>
</html>
|
Prototype.js JavaScript ライブラリーをベースとしたこのコードは、Ajax.Request オブジェクトを使って表示する画像のリストを取得します。XML コードが返されると、そのコードを構文解析して各画像の URL ならびに幅、高さ、タイトルを取得し、続いて showSlide() 関数を呼び出してスライドショーを開始します。タイマーは、5 秒間隔で次のスライドに進むように設定されています。
このスライドショーは、現行の画像に 1 つの <image> タグ、タイトルに 1 つの <div> タグを使って実装されます。スライドショーは単純に、現行の画像とタイトルを非表示にし、画像のソースおよびタイトルのテキストを新しいスライドのコンテンツに設定することによって次々にスライドを表示します。フェード・イン、フェード・アウトする項目が必要な場合は、Scriptaculous ライブラリーにある Effects クラスを使用することをお勧めします。このライブラリーも Prototype.js をベースに作成されています。
リスト 6 にデータ画像ファイルを記載します。
リスト 6. images.xml
<images>
<image src="images/megan1_875_700.jpg" title="Megan" width="875" height="700" />
<image src="images/oso1_875_700.jpg" title="Oso 1" width="875" height="700" />
<image src="images/oso2_873_700.jpg" title="Oso 2" width="873" height="700" />
</images>
|
上記はハードコーディングされていますが、PHP スクリプトを使えば簡単にこの XML コードを生成することができます。図 4 に、実演中のスライドショーを示します。
図 4. 単純なスライドショー
注: 私が以前に公開したスライドショーはこれよりも遥かに手の込んだバージョンです (「参考文献」にリンクを記載)。今回のスライドショーは Prototype.js ライブラリーを使用しているという点で異なり、スライドの遷移に関してずっと単純になっています。
まとめ
Flikr や YouTube のようなサイトは、Web 上のメディアに潜む可能性のほんのひとかけらを示しているにすぎません。この記事が提供するビデオおよび画像ブラウズの簡単な実装は、みなさん独自のプロジェクトで使用することができます。プロジェクトの役に立ったら、developerWorks Ajax フォーラム (「参考文献」をl参照) に参加してその成功例を報告してください。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| Sample code | x-ajaxxml7-media.zip | 1090KB | HTTP |
|---|
参考文献 学ぶために
議論するために
著者について
記事の評価
|