カスタムの YouTube プレイリスト・プレイヤーを作成する

基本的な組み込みプレイヤーを拡張し、YouTube.com のネイティブ・プレイヤーと同じ機能を持たせる

組み込み可能な YouTube プレイリスト・プレイヤーはネイティブ・プレイヤーの機能をすべて備えているわけではありません。この記事では著者の Joseph McCarthy が、YouTube API、jQuery、JsRender、Bootstrap を使用して、より完全な機能を持った、組み込みの YouTube プレイリスト・プレイヤーを作成する方法について説明します。

Joseph P. McCarthy, Java Developer, Consultant

Photo of Joseph McCarthyJoseph McCarthy は、Java™ および JavaScript 開発者であり、フロントエンド・アプリケーションとサーバーサイド・アプリケーションの両方での経験は 10 年を超えます。余暇には、人気のあるサービス (Facebook、Twitter、Google など) のパブリック API を詳しく調べ、ユーザー・エクスペリエンスを強化して楽しんでいます。



2014年 7月 24日 (初版 2014年 7月 17日)

IBM Bluemix™ にサインアップ
無償のサービス、ランタイム、インフラを含むクラウド・プラットフォームが、新たなモバイルやウェブ・アプリのクイックな構築とデプロイを実現します。

2005年に立ち上げられた YouTube は、主要な動画共有 Web サイトへと進化してきました。プレイリストは YouTube で最も広く使用されている機能の 1 つです。ユーザーは自分や他のユーザーがアップロードした動画のプレイリストを作成し、そのプレイリストを YouTube 上で共有することができます。また、Web サイトやブログ、ソーシャル・メディアのページにプレイリストを埋め込むことにより、プレイリストを共有することもできます。しかし、組み込みのプレイリスト・プレイヤーには YouTube.com のネイティブ・プレイヤーのすべての機能が含まれているわけではありません。

図 1 に YouTube.com ネイティブのプレイリスト・プレイヤーを示しています。

図 1. ネイティブのプレイリスト・プレイヤー
YouTube ネイティブのプレイリスト・プレイヤーのスクリーン・ショット

クリックして大きなイメージを見る

図 1. ネイティブのプレイリスト・プレイヤー

YouTube ネイティブのプレイリスト・プレイヤーのスクリーン・ショット

図 2 にデフォルトの組み込みプレイヤーを示します。

図 2. 組み込みのプレイリスト・プレイヤー
デフォルトの組み込み YouTube プレイリスト・プレイヤーのスクリーン・ショット

組み込みプレイヤーには以下のような制約があります。

  • デフォルトでは動画リストが表示されず、表示される場合もオーバーレイとして表示されるにすぎず、YouTube.com のようにプレイヤーの横には表示されません。
  • プレイリストをランダム再生する機能がありません。
  • 作成者がプレイリストに追加した注記は削除されます。

私がこれらの制約に突き当たったのは、2014年 FIFA ワールドカップの予選のベスト・ゴールのプレイリストをブログに埋め込もうとしたときです。YouTube API、jQuery、JsRender テンプレート・エンジン、そして Bootstrap フロントエンド・フレームワークを使用することで、私はデフォルトの組み込みプレイヤーを拡張、改善し、ネイティブ・プレイヤーと同じようなプレイヤーを作成することができました。この記事では、そのプロセスについて順を追って説明します。まず YouTube でプレイリストを作成し、ハイライト (ゴールなど) の時刻についての注記を追加してから、私と同じツールを使用して、省略されていた機能を復元してユーザー・エクスペリエンスを改善した組み込みプレイヤーを作成します。

このプロジェクトの完全なコードは DevOps Services に保存されています。読者がこのアプリケーションの実際の動作を理解できるように、私はこのアプリケーションを IBM Bluemix にデプロイしました。Bluemix を含む任意のホスト・サイトを利用することで、皆さんのコードをデプロイすることができます。

Flash のセキュリティー設定

Flash オブジェクトはセキュリティー・サンドボックスに割り当てられてしまうため、皆さんのシステムのブラウザーで index.html ファイルを開いても YouTube API の呼び出しは動作しません。このアプリケーションは (Bluemix などの) Web サーバー上にホストされている必要があります。

注: この記事のプロジェクトをフォークするには、右上隅の「EDIT CODE (コードを編集)」ボタンをクリックし (まだログインしていない場合には DevOps Services 資格情報を入力してください)、メニューの「FORK (フォーク)」ボタンをクリックして新しいプロジェクトを作成します。

最初のステップは YouTube API にアクセスするためのキーを取得することです。

YouTube API のキーを取得する

YouTube を含め、Google のサービスの API にアクセスするには、まずプロジェクトを Google Developers Console に登録し、API キーを作成する必要があります。さまざまな API へのアクセスは 1 日一定回数まで無料ですが、無料でアクセスできる回数はサービスごとに異なります。また Google アカウントを持っている人は誰でも API にアクセスすることができます。

皆さんの Google 資格情報で Google Developers Console にサインインし、「Create Project (プロジェクトを作成)」をクリックします。デフォルトで、プロジェクト名とプロジェクト ID のテキスト・ボックスにはランダムな値が入力されています。それらの代わりに皆さんのプロジェクト名とプロジェクト ID を入力し、「Create (作成)」をクリックします。

図 3. 新しい Google API プロジェクトを作成する
Google Developer Console の「New Project (新しいプロジェクト)」ダイアログ・ボックスのスクリーン・ショット

プロジェクトのダッシュボードで「APIS & AUTH (API と認証)」をクリックして、使用可能な API のリストを開きます。「YouTube Data API v3」まで下にスクロールし、この API に関連付けられた「OFF」というラベルのボタンをクリックし、皆さんのプロジェクトからアクセスできるようにします。「APIS & AUTH (API と認証)」 > 「Credentials (資格情報)」の順にクリックし、「Public API access (公開 API へのアクセス)」の下にある「Create New Key (新しいキーを作成)」をクリックした後、表示されるウィンドウで「Browser key (ブラウザー キー)」を選択します。

「Create a browser key and configure allowed referers (ブラウザー キーを作成し、許可されるリファラーを構成)」ダイアログで、API キーへのアクセスを特定ドメイン (皆さん自身のサイトや Bluemix など) からのリクエストのみに制限することができます。アクセスを制限しないと、誰もがアプリケーションの HTML ソースで皆さんの API キーを見ることができてしまいます。開発中はそれでも問題はないため、このダイアログ・ボックスを空白のままにして「Create (作成)」をクリックします。しかしプロジェクトがデプロイされたら、このステップに戻り、皆さんのアプリケーションのドメインからのリクエストのみを受け付けるようにアクセスを制限し、第三者がそのキーを他のアプリケーションに使うことはできないようにする必要があります。

DevOps Services からプロジェクトをコピーした場合には、ここで index.html ファイルの指示された場所にキーを挿入すると、コードが適切に実行されるようになります。


YouTube API にアクセスできるように Google JavaScript クライアント・ライブラリーを構成する

Google は JavaScript を含むさまざまな言語のためのクライアント・ライブラリーを提供しています。HTML 文書に JavaScript クライアントをインポートするには、HTML 文書の <body> タグ (<head> タグではありません) に以下の HTML タグを含めます。

<script src="https://apis.google.com/js/client.js?onload=function"></script>

推奨されるベスト・プラクティスは、この <script> タグを <body> タグの最後に配置することです。

クライアント・ライブラリーをロードすると、ページのウィンドウ・スコープで gapi (Google API) オブジェクトを利用できるようになります。上記で追加した <script> タグの onload パラメーターは、クライアント・ライブラリーをロードした直後に呼び出されるコールバック関数を参照します。この関数の定義はクライアントをロードする <script> タグよりも前になければなりません。この関数は gapi.client.load(<API 名>, <バージョン>, <コールバック関数>) メソッドを呼び出し、クライアントが使用する API をロードします。ここでは gapi.client.load('youtube', 'v3', onYouTubeApiLoad) を呼び出して YouTube API をロードします。onYouTubeApiLoadsetAPIKey メソッドを呼び出す 1 行の関数です。setAPIKeyでは、皆さんの Google ブラウザー・キーの値にキーを設定します。

このクライアントには、Google サービスの各種 API 呼び出しにアクセスするためのさまざまなメソッドがあります。プレイリストのアイテム・リストを取得するには、YouTube API の playlistItems.list メソッドから返されるレスポンスを非同期関数の中で構文解析し、関連する属性を、YouTubePlayList という JavaScript オブジェクトのインスタンスに保存します。この記事では YouTubePlaylist オブジェクトを作成します。このオブジェクトのコンストラクターは、以下の JavaScript 関数の中で定義されます。

リスト 1. YouTubePlaylist.js
function YouTubePlaylist(id, entries) {
   this.id = id;
   this.entries = entries;
   this.currently_playing = 0;
   this.randomizer = false;
}
  • id はプレイリストの ID です。
  • entries は、プレイリストの動画で構成される JSON 配列です。
  • currently_playing は、entries 配列の動画のうち、現在再生中の動画のインデックスです。
  • randomizer は、再生がランダムかどうかを示します。

レスポンスのパラメーターを使用して JSON オブジェクトを作成する

今度は、レスポンスに必要なパラメーターを含む JSON オブジェクトを作成します。使用可能なパラメーターの全リストの中で必要なのは一部にすぎません。

part パラメーターは、呼び出しによって返される属性の CSV (Comma-Separated Value) リストです。使用する属性は contentDetailssnippet です。snippet 属性には各動画の基本的な情報が含まれています。contentDetails 属性には、動画の ID と、プレイリストの作成者が注記を追加した場合はその注記が含まれています。後で動画のハイライトを特定する際に contentDetails が重要になります。playListId パラメーターは、使用するプレイリストの ID です。この記事では、ハイライト付きのプレイリストを設定しており、その ID は PLLzJfby7cTLTbusOgXca-yIpVOImC1mWe です。このプレイリストには、注記としてゴールの時刻が追加されていることに注目してください。これらにより、JSON オブジェクト requestOptions は以下のようになります。

var requestOptions = {
   playlistId: playlist_id,
   part: 'contentDetails,snippet'
};

この JSON オブジェクトを引数として gapi.client.youtube.playlistItems.list() メソッドを呼び出すと、executesubscribe という 2 つのメソッドを持つオブジェクトが返されます。そのレスポンスを引数として、非同期関数で execute メソッドを呼び出します。

request.execute(function(response) {});

レスポンスに含まれる items 配列には、プレイリストの動画リストが含まれています。これらのアイテムに対し、jQuery の each() メソッドを使用して繰り返し処理を行います。動画の ID、動画のサムネイル (中サイズ)、タイトル、JSON オブジェクトに含まれる注記を保存し、それらを配列に追加します。

リスト 2. JSON オブジェクトを entries 配列に追加する
var entries = [];
$.each( response.items, function( key, val ) {

   var entry = {};
   entry.video_id = val.snippet.resourceId.videoId;
   entry.image_src = val.snippet.thumbnails.medium.url;
   entry.title = val.snippet.title;
   entry.note = val.contentDetails.note;
   entries.push(entry);

});

YouTubePlaylist オブジェクトを作成する

プレイリスト ID と entries 配列を使用してコンストラクター (リスト 1 を参照) を呼び出し、新しい YouTubePlaylist オブジェクトを作成します。そして、そのプレイリスト ID を名前とする新しい変数として、そのオブジェクトをウィンドウ・スコープに保存します。

window[playlist_id] = new YouTubePlaylist(playlistId, entries);

これで、window[playlist_id] を使用して YouTubePlaylist オブジェクトにアクセスできるようになります。後ほど、window[playlist_id] を使用して YouTubePlaylist オブジェクトの別の機能を呼び出します。


テンプレートと JsRender を使用してプレイヤーのフォーマットを設定する

このプレイヤーの外観は図 4 のようなもので、右側にはプレイリストのエントリーで構成される、サムネイル (Thumbnail)、タイトル (Title)、注記 (Note) のリストがあります。

図 4. 新しいプレイヤーの外観
新しいプレイリスト・プレイヤーの構成を示す図

クリックして大きなイメージを見る

図 4. 新しいプレイヤーの外観

新しいプレイリスト・プレイヤーの構成を示す図

デフォルトで、HTML の文字セットにはネイティブ YouTube プレイヤーの「次の動画」アイコン、「前の動画」アイコン、「シャッフル」アイコンのようなアイコンはありません。ここでは Bootstrap フロントエンド・フレームワークに用意されているアイコンを使用します。Bootstrap スタイルシートをインポートするには、以下のスニペットを <head> タグに追加します。

<link rel="stylesheet" 
      type="text/css" 
      href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">

YouTubePlaylist オブジェクトの描画には JsRender テンプレート・エンジンを使用します。JsRender テンプレートの定義は <script> タグ内で行い、type 属性を text/x-jsrender に設定します。そのオブジェクトを描画対象として x-jsrender テンプレートの render() メソッドを呼び出すことで、HTML を生成します。テンプレートの変数を描画するためには二重波括弧表記 {{:}} を使用します。例えば {{:id}} はテンプレートに渡されたオブジェクトの id 属性を描画します。

リスト 3 のテンプレートは Web ページに YouTube プレイヤーを組み込みます。

リスト 3. YouTube プレイヤーを組み込むためのテンプレート
<object width="640" 
        height="360" 
data="http://www.youtube.com/v/video id?version=3&amp;enablejsapi=1&amp;playerapiid=id"
        id="player id" 
        type="application/x-shockwave-flash">
   <param value="always" name="allowScriptAccess">
   <param value="true" name="allowFullScreen">
</object>

リスト 3 で、video id は再生される動画の ID であり、player id はプレイヤー・オブジェクト自体の ID です。初期化の際には entries 配列の最初の動画をキューイングするので、組み込みプレイヤー・テンプレートの動画 ID として {{:entries[0].video_id}} を入力します。プレイヤー ID については、プレイリスト ID、つまり {{:id}} を使用します。

YouTube プレイヤー・オブジェクトの初期化時に、プレイヤーは、プレイヤーの ID を引数として onYouTubePlayerReady() 関数を自動的に呼び出すことで、プレイヤーの状態が変化したときのプレイヤーの動作をカスタマイズします。プレイヤーの状態には、unstarted (開始前)、ended (終了)、playing (再生中)、paused (一時停止中)、buffering (バッファー中)、video cued (動画キューイング完了) があり、これらは -1、0、1、2、3、4 という値として列挙されます。API の現在のバージョンでは、コールバック関数をカスタマイズすることはできないため、ここでは、プレイリストに含まれる次の動画をウィンドウ・スコープでロードする関数を定義し (後ほど、この関数を YouTubePlaylist オブジェクトの中で定義します)、その関数をイベント・リスナーとしてプレイヤーに追加します。

リスト 4. プレイリストに含まれる次の動画をロードする関数
function onYouTubePlayerReady(playerApiId) {
   var player = document.getElementById(playerApiId);
   window["onStateChange" + playerApiId] = function(state) {   
      switch(state) {
         case 0:                         
var video_player = document.getElementById(player_id);
video_player.loadVideoById(window[player_id].getNextVideo(), 0, "large"); 
break; } }; player.addEventListener("onStateChange", "onStateChange" + playerApiId); }

動画の配列を繰り返し処理するには JsRender {{for}} タグを使用します。図 4 の右側にあるプレイリストの各エントリーを作成するにはリスト 5 のテンプレートを使用します。

リスト 5. プレイヤーのリスト内の各プレイリスト・エントリーを作成するためのテンプレート
{{for entries}}
<div class="playListEntry {{if #index == 0}}nowPlaying{{/if}}" id="{{:video_id}}">
   <div class="playListEntryThumbnail">
      <img src="{{:image_src}}"/>
   </div>
   <div class="playListEntryDescription">
      <div class="playListEntryTitle">{{:title}}</div>
      <div class="playListEntryNote">{{:note}}</div>
   </div>
</div>
{{/for}}

リスト 5 で、entriesYouTubePlaylist オブジェクトの entries 属性です。動画の配列におけるこのオブジェクトのインデックスは、#index 変数に保存されています。プレイヤーのリスト内の最初のエントリーは、プレイヤーの作成時にプレイヤーにロードされる動画なので、for ループ内で {{if}} タグを使用して最初の playListEntry クラスを特定し、nowPlaying という CSS クラスをこのクラスに適用します。

プレイヤーの一番下にあるコントロールは、Bootstrap の glyphicon クラスを span に適用することで作成し、各アイコンに対して glyphicon-backwardglyphicon-forwardglyphicon-random クラスを使用します。

<div class="playListControls">
   <span class="playListControl disabled glyphicon glyphicon-backward"/>
   <span class="playListControl glyphicon glyphicon-forward"/>
   <span class="playListControl glyphicon glyphicon-random"/>
</div>

初期状態では、「前の動画」アイコンが無効になっていることに注意してください。これは、プレイヤーが初めてロードされたときには、デフォルトでプレイリストの最初のエントリーが選択されるため、再生すべき「前の動画」がないことによります。

描画される HTML を、以下のコード・スニペットを使用してページ上の空の div (ID は playlist) に追加します (window[player_id] が、「YouTubePlaylist オブジェクトを作成する」セクションで作成したオブジェクトであることに注意してください)。

$('#' + player_id).html($('#playListPlayerTemplate').render(window[player_id]));

このコードを再利用できるようにするために、addPlaylistToElement(playlist_id, element_id) というシグニチャーの関数にこのコードを移動します。すると、このコードを addPlaylistToElement('PLLzJfby7cTLTbusOgXca-yIpVOImC1mWe', 'playlist') で呼び出せるようになります。


コントロールを追加する

YouTubePlaylist オブジェクトに戻り、機能を追加することにします。後ほど、このオブジェクトの機能強化版を使用して Web ページのプレイヤーを完全なものにします。

このオブジェクトに 6 つの関数、つまり previous()next()getCurrentlyPlaying()setCurrentlyPlaying()randomize()isRandomized() を追加します。previous 関数と next 関数はそれぞれプレイリストの前の動画、次の動画に移動し、そのアクションが成功すると true を返し、アクションが成功しないと (つまり、ユーザーがプレイリストの最初のエントリーで「前の動画」をクリックした場合、または最後のエントリーで「次の動画」をクリックした場合には) false を返します。getCurrentlyPlaying() はプレイリストの現在再生中の動画の ID を返します。randomize()YouTubePlaylist オブジェクトの random 属性を設定または設定解除し、isRandomizer()random 属性の値を返します。

リスト 6 は Next() 関数を示しています。

リスト 6. Next() 関数
next: function() {
   var retVal = false;
   if(this.randomizer) {
      retVal = true;
      this.currently_playing = Math.floor((Math.random() * this.entries.length));
   }
   else if(this.currently_playing <= this.entries.length) {
      retVal = true;
      this.currently_playing++;
   } 
   return retVal;

Next() 関数では、random 属性が設定されているかどうかを最初に確認し、設定されている場合には currently_playing インデックスを entries 配列内のランダムな値に設定します。random 属性が設定されておらず、なおかつ currently_playing インデックスが entries 配列内の動画の数よりも小さい (つまり、まだプレイリストの最後の動画を再生していない) 場合には、インデックスの値を 1 ずつインクリメントして次の動画に移動し、処理の成功を示すために true を返します。処理が成功しなかった場合は false を返します。

リスト 7 は previous() 関数を示しています。currently_playing インデックスがゼロよりも大きい (つまりユーザーがプレイリストの最初の動画以外の任意の動画を見ている) 場合には、インデックスを 1 つ減らし、処理が成功したことを示すために true を返します。処理が成功しなかった場合は false を返します。

リスト 7. previous() 関数
previous: function() {
   var retVal = false;
   if(this.currently_playing > 0) {
      retVal = true;
      this.currently_playing--;
   } 
   return retVal;
}

getCurrentlyPlaying() 関数では、entries 配列のうち、現在再生中のインデックスで指定される動画の ID を返します。

getCurrentlyPlaying: function() {
   return this.entries[this.currently_playing].video_id;
}

リスト 8 は setCurrentlyPlaying() 関数を示しています。現在のプレイリストの video_id が指定されると、entries 配列内でその値を持つ要素のインデックスを currently_playing に設定します。

リスト 8. setCurrentlyPlaying() 関数
setCurrentlyPlaying: function(video_id) {
   for(var index = 0; index < this.entries.length; index++) {
      if (this.entries[index].video_id === video_id) {
         this.currently_playing = index;
         break;
      }
   }
}

randomize() 関数では、randomizer 属性の値を逆に、つまり true を false に、またはその逆を行い、その新しい値を返します。

randomize: function() {
   this.randomizer = !(this.randomizer);
   return this.randomizer;
}

isRandomized() 関数はプレイリストの randomizer 属性の値、つまりプレイリストがランダム再生状態かどうかを返します。

isRandomized: function() {
   return this.randomizer;
}

追加機能を使用する

今度は、JavaScript オブジェクトの追加機能を使用する関数を追加します。

まず、プレイリストのコントロールを配置するヘルパー関数を追加します。プレイヤーがランダム再生状態の場合には以下のようになります。

  • 「シャッフル」アイコンが強調表示されます。
  • 「前の動画」アイコンは常に無効になっています。前に再生した動画をどこかに記録しているわけではないからです。
  • 「次の動画」アイコンは常に有効になっています。ランダム再生される動画がプレイリストの「最後」ということはないからです (ランダム再生状態の MP3 プレイヤーが再生を停止することがあるかどうか、考えてみてください)。

プレイリストがランダム再生状態ではない場合には、以下のようになります。

  • 「前の動画」アイコンは、プレイリストの最初のエントリーが再生されている場合にのみ無効になります。
  • 「次の動画」アイコンは、プレイリストの最後のエントリーが再生されている場合にのみ無効になります。
  • 「シャッフル」アイコンは、このアイコンが再度クリックされるまで無効になります。

リスト 9 に、このヘルパー関数を示します。

リスト 9. プレイリストのコントロールを配置するヘルパー関数
function arrangePlayerControls(player_id) {
   var playListPlayer = $('#' + player_id + 'playListPlayer');
   if(window[player_id].isRandomized()) {
      $('#' + player_id + 'Backward').addClass('disabled');
      $('#' + player_id + 'Forward').removeClass('disabled');
      $('#' + player_id + 'Random').addClass('randomizeActive');
   }
   else {
      $('#' + player_id + 'Random').removeClass('randomizeActive');
      var playListEntries = $('#' + player_id + 'playListEntries');
      if(playListEntries.children(":first").hasClass('nowPlaying')) {
         $('#' + player_id + 'Backward').addClass('disabled');
      }
      else {
         $('#' + player_id + 'Backward').removeClass('disabled');
      }
      if(playListEntries.children(":last").hasClass('nowPlaying')) {
         $('#' + player_id + 'Forward').addClass('disabled');
      }
      else {
         $('#' + player_id + 'Forward').removeClass('disabled');
      }
   }
}

次に、プレイリスト ID と、動画の再生を開始する時刻インデックスを指定して、プレイヤーに動画をロードする関数を追加します。現在再生中の動画の div から nowPlaying クラスを削除し、新しい動画の div に追加することを忘れないでください。次に、プレイリストのアイコンを配置するための、リスト 9 のヘルパー関数を呼び出します。リスト 10 は動画をロードする関数を示しています。

リスト 10. プレイヤーに動画をロードする関数
function loadVideoForPlayer(currently_playing_video_id, player_id, time) {
   time = time || 0;
   var video_id = window[player_id].getCurrentlyPlaying();
   $('#' + currently_playing_video_id).removeClass('nowPlaying')
   $('#' + video_id).addClass('nowPlaying');
   $('#' + player_id + 'playListEntries').scrollTop($('#' + video_id).index() * 80);
   document.getElementById(player_id).loadVideoById(video_id, time, "large");
   arrangePlayerControls(player_id);
}

最後に、指定されたプレイリスト内の次の動画をロードする関数を追加します。ただし動画をロードするのは、そのプレイリスト内に別の動画がある場合 (つまり、ランダム再生状態ではなく、その上、現在の動画が最後の動画ではない場合) のみです。

リスト 11. 次の動画が存在する場合に動画をロードする関数
function loadNextVideo(player_id) {
   var currently_playing_video_id = window[player_id].getCurrentlyPlaying();
   if(window[player_id].next()) {
      loadVideoForPlayer(currently_playing_video_id, player_id);
   }
}

この関数は onYouTubePlayerReady() 内で宣言した匿名関数に似ています (リスト 4 を参照)。そこで、onYouTubePlayerReady()case 0 ブロックをリファクタリングし、代わりに loadNextVideo() を呼び出すようにします。

私がプレイリストの各動画にゴールの時刻を追加したことに気付いた人がいるかもしれません。これらの新しい関数により、動画のゴール部分に直接ジャンプするためのリンク・ホットスポットとしてゴール時刻を使用することができ、動画全体を見る必要がなくなります。addPlaylistToElement()$.each() ループの中で、各 playlistItem オブジェクトに対する注記の値をローカル変数に保存し、注記に含まれる時刻の配列を JavaScript の match() 関数を使用して返します。この場合、各ゴールの時刻を検索するために正規表現 /[0-9]*:[0-5][0-9]/g を使用します。次に、この配列に対して繰り返し処理を行い、ローカル変数の中にある各時刻の値をリンクで置き換えます。このリンクでは、プレイヤー ID、再生される動画、開始時刻のインデックスを使用して cueThisVideo() 関数を呼び出します。YouTube API の loadVideoById() 呼び出しが秒単位の時刻を引数にとることを思い出してください。そこで、文字列内のコロンを区切り文字として使用し、時刻を配列に分割します。最初のインデックス (分) の値を 60 倍して秒に変換し、それを 2 番目のインデックスの秒に加算すると合計秒数が得られます。例えば、1:30 は [1, 30] という配列になり、(1 * 60) + 30 = 90 秒となります。最後に、注記内の時刻を新しいリンクで置き換えます。注記内の各時刻を処理した後、完成した文字列をエントリーへの注記として entries 配列に保存します。これを示したものがリスト 12 です。

リスト 12. 注記内の時刻をリンクで置き換える
var note = val.contentDetails.note;
var times = note.match(/[0-9]*:[0-5][0-9]/g);
times.forEach(function(value, index, array) {
   var time = value.split(":");
   var seconds = parseInt(time[0]) * 60;
   seconds += parseInt(time[1]);
   note = note.replace(value, 
     "<span class='timeLink' onclick='cueThisVideo(\"" 
     + player_id + "\", \"" 
     + video_id + "\", " 
     + seconds + ");'>" 
     + value + "</span>");
});
entry.note = note;

残された作業は、テンプレートに戻って、これらの新しい関数の呼び出しを追加することです。ユーザーが、タイトルまたはサムネイルをクリックして動画をキューに入れることや、プレイリスト内の前の動画または次の動画をキューに入れること、さらにはコントロール・パネルの該当するボタンでプレイリストをランダム再生することを可能にする必要があります。リスト 13 に、追加された機能を使用できるように変更したテンプレートが完成した状態を示します。

リスト 13. リファクタリングされたテンプレート・コード
<div onclick="cueThisVideo('{{:~player_id}}', '{{:video_id}}');" 
     class="playListEntryThumbnail">
          <img src="{{:image_src}}"/>
</div>
<div onclick="cueThisVideo('{{:~player_id}}', '{{:video_id}}');" 
     class="playListEntryTitle">
     {{:title}}
</div>

<span id="{{:id}}Backward" 
     class="playListControl disabled glyphicon glyphicon-backward" 
     onclick="if(!$(this).hasClass('disabled'))	{   loadPreviousVideo('{{:id}}')   }">
</span>
<span id="{{:id}}Forward" 
     class="playListControl glyphicon glyphicon-forward" 
     onclick="if(!$(this).hasClass('disabled')) {   loadNextVideo('{{:id}}')   }">
</span>
<span id="{{:id}}Random" 
     class="playListControl glyphicon glyphicon-random" 
     onclick="window['{{:id}}'].randomize();arrangePlayerControls('{{:id}}');">
</span>

これでカスタム・プレイヤーが完成しました。


まとめ

この記事では、YouTube API、そして単純な JavaScript とスタイル設定を使用して、YouTube.com のネイティブ・プレイリストと同じ機能を持つ組み込みの YouTube プレイリストを描画する方法について説明しました。このプロジェクトに関する私の DevOps Services ページにある README ファイルを参照し、このプレイヤーをさらに機能強化するための助言を読んでください。このプロジェクトのコードを自由にフォークし、そうした助言のいずれか、またはすべてを実装してみてください。

参考文献

学ぶために

議論するために

  • developerWorks コミュニティーに参加してください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者によるブログ、フォーラム、グループ、Wiki を調べることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development, Cloud computing
ArticleID=977498
ArticleTitle=カスタムの YouTube プレイリスト・プレイヤーを作成する
publish-date=07242014