R&Dトレンドレポート

第25回マッシュアップ開発のススメその11:モバイル版アプリケーションを作ろう⑤]

今回は、マッシュアップというテーマでの最終回となります。肝心カナメの動画再生画面の作成と動画上にコメントを流してみましょう。

動画再生の方法

動画は2つのパスから再生させることになります。1つは常に最初からの再生で、2つめはグラフのサムネイルからの途中からの再生です。

画面レイアウトの構築

動画再生画面に関しては、画面レイアウトを構築する部分はほとんどありません。ナビバーの左上にクローズボタンがある以外はすべてVideoPlayerのUIそのものとなります。

リスト1 クローズボタンとプレイヤーの作成
var b = Titanium.UI.createButton({
  title:'Close',
});
win.setLeftNavButton(b);
b.addEventListener('click',function()
{
  win.close();
});


var activeMovie = Titanium.Media.createVideoPlayer({
  contentURL:media_url,
  backgroundColor:'#111',
  movieControlMode:Titanium.Media.VIDEO_CONTROL_DEFAULT,
  scalingMode:Titanium.Media.VIDEO_SCALING_ASPECT_FIT,
  fullscreen: false,
  top: 0,
});


if (parseFloat(Titanium.Platform.version) >= 3.2)
{
  activeMovie.movieControlStyle = Titanium.Media.VIDEO_CONTROL_EMBEDDED;
  win.add(activeMovie);
}

以上でUIの構築は終わりです。createVideoPlayerで作成したactiveMovieオブジェクトに対して、イベントハンドリングやコメントの付与を行っていきます。

動画再生機能の実装

動画再生機能としての実装はほとんど無く、プレイヤーのUIはすでに組み込み済みです。スタート、ストップなどのイベントのハンドリングができますので、それらを利用しましょう。videoPlayerで使用できるイベントは以下のようなものが用意されています。

表1 VideoPlayerのイベント
dblclickdoubletap
durationAvailable
error
fullscreen
load
loadstate
mediaTypesAvailable
naturalSizeAvailable
playbackState
playing
preload
resize
singletap
sourceChange
swipe
thumbnail
touchcancel
touchend
touchmove
touchstart
twofingertap

動画再生の開始位置は、VideoPlayerのinitialPlaybackTimeプロパティで指定します。この値に秒数を指定することで、自動的にその位置から再生を行うことができます。

動画詳細画面からのサムネイルのクリック時にその再生位置(秒)を渡すようにしましょう。再生位置を指定しない場合は頭からの再生となります。

コメント表示の実装

さて、これでコメントを追加して…、と考えました。コメント追加のためのシーケンスは以下のようになります。

図1 コメント取得のシーケンス概要
図1 コメント取得のシーケンス概要

ところがVideoPlayerには現在の再生位置を知るAPIが用意されていないことがわかりました。ネイティブのAPIでも公式には公開されておらず、隠しAPIでその動きをハンドリングするという方法もあるようですが、iTunes Storeでは流通できないようです。

いろいろ考えてみたのですが、妙案浮かばず、一度再生したら早送りや巻き戻しは一切しない、という前提でとりあえずコメントを画面上に流すというやり方を紹介します(あるいは動画詳細画面に戻ってサムネイルから再生させるか…⁠⁠。

最初コメントの取得については、再生時間が指定されている場合はその時間をキーに取得に行きます。指定されていない場合は0秒として扱います。その後はコメントの逐次取得が必要ですが、その部分はsetTimeout関数を用いて、取得後都度次のコメントを取得するようにします。

リスト2 動画の再生からコメント読み込みまで
activeMovie.initialPlaybackTime = win.seektime; //seektimeというパラメータで開始時間を渡しておく

//コメント取得のクラス動画のID、更新間隔(秒)でイニシャライズする。
var r = new ResData(win.vid, duration); 

//URLから読み込んでいるため、その読み込みが完了したタイミングでコメントデータを取得しに行く
activeMovie.addEventListener("loadstate", function(ev){
  if ( ev.loadState == 3 )
  {
    r.getNextList(win.seektime);
  }
});

//ResData.getNext()でコメントデータ取得後、コールバックされる。
Ti.App.addEventListener("showRes", function(e){
  setTimeout(function(){
    r.getNextList();
  }, duration); //duration秒後に次のコメントを取得する
  // 取得したデータを表示する。
  showScreen(e.data);
});

コメント取得はコメント取得クラスとして独立させておき、getNextList()で次のリストを取得するようにします。取得後は、コメント取得クラス側からshowRes()関数をコールするようにしています。

動画へのコメントの貼り付けは以下のように実装します。

リスト3 コメントの表示
function showScreen( data )
{
  var cnt = data.length;
  var t = Math.floor(duration / cnt); //1コメントあたりの表示時間

  for ( i = 0; i < cnt; i++ )
  {
    var __f = _func(data[i][0]);
    setTimeout( __f, i * t); //コメントを均等割で時間をずらして表示させる。
  }
}


function _func(d)
{
  return function()
  {
        // テキストラベルを生成
    var movieLabel = Titanium.UI.createLabel({
      width:'auto',
      top:Math.random() * 300, //表示位置はランダム
      left: 330, //画面外から
      color:'white', 
      font:{fontSize:14,fontFamily:'Helvetica Neue'}
    });
    movieLabel.text = d;

    activeMovie.add(movieLabel);
    var dur = Math.random() * 3000 + duration; //文字が流れる速度を多少変化させる。

    movieLabel.animate({left:-1000,duration: dur}, function(){
      activeMovie.remove(movieLabel);
      //Ti.API.info("remove Label");
    });
  };
}

以上で動的にコメントデータの取得、画面への表示、データの取得… という風に動作はするようになりました。しかし動画再生時間がとれないため、データ取得に失敗した場合や、データ取得に時間がかかった場合など、コメントと動画が合わなくなっていくことがありました。

実際の動作はこのようになります。

図2 コメントが流れるところ
図2 コメントが流れるところ

画面がちょっと見にくいですが、コメントが右から左に流れています。

まとめ

今回、長きにわたってマッシュアップというキーワードでサーバサイドからクライアントまで構築を行ってきましたが、プログラミングというよりもサービスの開発という視点が非常に重要だと感じました。1つ1つのパーツはそれほど大きなウェイトを占めることはありませんが、複数組み合わせることで効果的なサービスを構築することが可能です。

ちょっとやってみるか、という軽い感じで始められるわりにはできあがったモノはなかなか楽しい。そんなサービスがこれからもどんどん世の中に出てくると思います。個人的には、⁠モノを作っていく」という感覚と、⁠サービスを作る」という両局面が体感できたため、非常に楽しく進めることができました。

みなさまの一助になればと思います。ありがとうございました。

おすすめ記事

記事・ニュース一覧