YouTubeの動画を連続再生させてみる。


YouTubeで好きなアーティストの曲を連続再生させたいって思ったとき、すでに「君のラジオ」だったりYouTube本家にDiscoとしてあるわけですが、Last.FMユーザーとしては自分のTop50のランキングからランダムにいい感じに曲を選んで欲しいと思ったりしています。
なので、そういうものを作ろうかなと思いながら全然形に出来ていないので、ちょびちょびアウトプットしながら作っていこうかと思います。


今回はここまで

ざっくり必要なもの

  • YouTubeの動画を連続再生させる。(←今回ココ)
  • Last.FMのアカウントからランキングを取得して、そのアーティストの集合から曲をランダムに抽出する仕組み
    • 曲は毎回再生するたびにそこそこ変化する。
    • 上位のアーティストの曲は優先度が高い。
  • 他の面白そうな技術に流されない心。

こんなものでしょうか?

YouTubeの動画を連続再生させる

プレーヤーの埋め込み

ドキュメント見る
<head> 
<meta charset="utf-8"> 
<title>YouTubeを連続再生してみるサンプル1</title> 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script> 
</head> 
<body> 
<script type="text/javascript"> 
var video_list = ["cfOa1a8hYP8", "tYm1PDwLrQM"]; 
swfobject.embedSWF("http://www.youtube.com/v/" + video_list[0] + "?enablejsapi=1&autoplay=1&playerapiid=player", 
    "video", "854", "480", "8", null, null, { allowScriptAccess: "always" }, { id: "player" }); 
</script> 
<h1>YouTubeを連続再生してみるサンプル1</h1> 
<div id="video"></div> 
</body> 
</html> 
  • こんな感じになります。
  • swfobject作るときの各パラメータについてはドキュメントに書いてあるので省略しますが、自動再生するために「autoplay」を有効にしたりしています。
  • ここでは、playerapiidとして「player」、divのidとして「video」、idとしてgetElementByIdでプレイヤーを取得するためのIDとして「player」を指定しています。
    • playerapiidの方はおそらく後で説明するイベントなどで引数として渡されてくる値になるのだと思います。
イベントを取得して連続再生
  • 上記でとりあえずvideo_idを渡せば再生出来るようになりましたので次は連続再生出来るようにしたいと思います。
  • YouTubeプレイヤーではプレイヤーの準備が整ったら「onYouTubePlayerReady」という関数を呼ばれます。そのタイミングで、プレイヤーの状態が変わったら投げる「onStateChange」というイベントに、再生が終了した時だったら次のビデオを読み込んで再生するという処理を登録しています。
function onYouTubePlayerReady(playerId) { 
    document.getElementById(playerId).addEventListener("onStateChange", "onytplayerStateChange"); 
} 
function onytplayerStateChange(newState) { 
    if (newState == 0) { 
        document.getElementById("player").loadVideoById(video_list[1]); 
    } 
} 
  • newStateが0の場合が再生が終了した場合のイベントになるので、その時にloadVideoByIdでvideo idを指定することで連続再生することが出来ます。
  • これでとりあえずvideo idのリストさえ取得できれば連続再生出来そうですね。なので次は動画情報を取得してみます。
  • こんな感じになります。

動画情報を取得する

投げるクエリー
  • 今回はJQueryを使って実装しました。
  • (抜粋)
function onytplayerStateChange(newState) { 
    if (newState == 0) { 
        ++index;
        document.getElementById("player").loadVideoById(video_list[index].id); 
    } 
} 
var video_list = []; 
var index = 0; 
var api_offset = 1; 
jQuery(function($) { 
    $("#search").click(function() { 
        var query = $("#query").attr("value"); 
        $.getJSON("http://gdata.youtube.com/feeds/api/videos?", 
            { 
                "q": query, 
                "alt": "jsonc", 
                "v" : 2, 
                "max-results":10, 
                "format": 5, 
                "orderby": "viewCount", 
                "start-index": api_offset 
            }, 
            function(rs) { 
                var query = new RegExp($("#query").attr("value"),"i"); 
                api_offset += 10; 
                var rs_list = rs.data.items; 
                rs_list = rs_list.sort(function(a, b) { 
                    return b.favoriteCount - a.favoriteCount; 
                }); 
                for (var i = 0, max = rs_list.length;  i < max; i++) { 
                    if (rs_list[i].title.match(query)) { 
                        video_list.push(rs_list[i]); 
                    } 
                } 
                swfobject.embedSWF("http://www.youtube.com/v/" + video_list[index].id + "?enablejsapi=1&autoplay=1&playerapiid=player", 
                    "video", "854", "480", "8", null, null, { allowScriptAccess: "always" }, { id: "player" }); 
            } 
        ); 
    }); 
}); 
  • 動画情報を取得してそれを配列に入れて、再生が終了するごとに次のビデオを再生しています。
  • こんな感じ
API
  • 指定しているパラメータは見ての通りですが、qは検索文字列、altはレスポンスデータ型(後述)、vはAPIバージョン、max-resultsは結果の最大数、formatは動画フォーマット(埋め込み可能なものだけ)、orderbyは順番、start-indexはoffsetを指定しています。offsetを指定しているのは後で11-20件目を取ったり出来るようにするためです。
  • alt=jsoncについて
取得したデータを精査
  • 単純にアーティスト名で検索すると全然違う動画も結構引っかかってくるのでかなり残念な感じになります。
  • ですので取得したデータを加工することで少しはマシなデータを取得出来るようにします。
  • 方法としては、jsoncのデータに入っているfavoriteCountというデータでソートをし、検索文字列がタイトルに含まれているかでフィルタリングをしています。ものによっては全然取得出来なくなりますが無関係な動画はあまり引っかかってこなくなると思います。
            var query = new RegExp($("#query").attr("value"),"i");
            api_index += 10;
            var rs_list = rs.data.items;
            rs_list = rs_list.sort(function(a, b) {
                return b.favoriteCount - a.favoriteCount;
            });
            for (var i = 0, max = rs_list.length;  i < max; i++) {
                if (rs_list[i].title.match(query)) {
                    video_list.push(rs_list[i]);
                }
            }
  • 「君のラジオ」のようにLast.FMを使って曲情報を持っている場合は、曲とアーティスト名を組み合わせた検索文字列にすることで精度を高くすることが出来るようです。あの精度はスゴイなぁと思います。いまだとTravisとかで検索すると全然違うtravisさんの動画が引っかかってきて使えないので。。

もう一工夫

  • 上記で検索されたアーティストの動画を連続再生させることが出来るようになりましたが正直まだ使いにくいです。ですので現時点では下記のような機能を追加で実装しています。
    • 動画リスト、現在再生している動画を表示する機能。
    • 残り動画が少なくなってきたらAPI呼んで次の動画を取ってくる機能。
    • 次の曲、前の曲に移動出来る機能。


こんな感じになります。あまり確認していないので動かないところもあるかもしれません。(IEは論外)


ソースはGithubで管理しています。html 1つにまとめて書いているのでhtmlだけあれば動かすことが出来ると思います。

まだまだイマイチですので、少しずつ手を加えていきたいなと思います。Githubみたいにpermalinkを作って検索出来るようにするとか。
Enjoy Youtube !