Kentaro Kuribayashi's blog

Software Engineering, Management, Books, and Daily Journal.

livedoor Reader + YouTube + はてなブックマークで最速動画ウォッチング

YouTube のタグによる検索結果の feed アイコンを表示する Greasemonkey スクリプト」で述べた通り、YouTube の検索結果による feed を利用できることがわかったので、早速 livedoor Reader に登録してみました。それはそれでまぁいいんだけど、「これはよさげ?」という動画をいちいちタブを開いて観るのめんどくさい!feed のチェックから視聴、はたまた気に入った動画のブックマークまでの全てを、LDR 内で完結させたい!!!という思いがむくむくと湧き起こってきました。
というわけで、上記要求を満たすのに必要なもののうち、欠けていた LDR 内で YouTube の動画を観られるようにする greasemonkey スクリプトを書いた(詳細は後述)ので、なかなか快適な YouTube ヲチ生活を送れそうです。百聞は一見に如かずというわけで、とりあえずデモンストレーション動画をご覧ください。
YouTube - Mashup livedoor Reader, YouTube and Hatena::Bookmark
http://ktr.s101.xrea.com/pg6mxOCCxnM.flv
つか、初めて YouTube に動画をうpってみたのですが、画質が激しく劣化するんですな。。。↑のプレイヤじゃぁ小さ過ぎて、なにをやってるのかよくわかんないかも。詳しくは、リンク先の YouTube にてご覧ください(それでもなんかばっちい画質になっちゃってるけど……)。
見ればおおむねわかると思うけど、デモ動画の流れを順を追って説明します。

  1. YouTube で「中川翔子」を検索
  2. 中川翔子の検索結果が表示される
  3. 検索語入力欄の左に feed アイコンが表示されているのが確認できる
  4. feed をブラウザで表示、ブックマークレットにより、その feed を LDR に登録
  5. LDR に画面が遷移
  6. とりあえずデモなので、上で登録した feed だけ表示されるように、条件絞り込み欄に「中川翔子」と入力
  7. YouTube :: Tag // 中川翔子」が表示される
  8. ショートカット "y" キー押下により、ブーンをやっている映像がその場で YouTube のプレイヤーにより表示される
  9. ブーン閉じる
  10. 次のエントリへ移動
  11. 「Brilliant Dream PV (試聴バージョン)」を開く
  12. 気に入ったので、動画を観ながらショートカット "b" キーを押下し、はてなブックマークにぶくまする
  13. PV 閉じる
  14. 終了

ここでは YouTube の feed を見ている時にその場で動画を観るデモを見せましたが、エントリの URL が YouTube のものでありさえすればいいので、たとえばはてなブックマーク等でブックマークした YouTube 動画等も観ることができます。
なんか緊張してとちったりしてるところがあって、いまいち速い感じを演出できなかったのですが、まぁなかなか快適です。LDR 内で feed をチェックしながら YouTube のプレイヤを表示、動画を観られるようにする greasemonkey スクリプトは以下からインストールできます。使い方は、フォーカスされているエントリが YouTube の動画である時に、ショートカット "y" キーを押すだけです。どうぞご利用ください。

追記。
このスクリプトは「antipop - Update: LDR で最速動画ウォッチング + YouTube Anywhere」で更新されています。そちらのエントリも合せてご覧ください。

インストール: ldr_youtube_player.user.js

// ==UserScript==
// @name          YouTube Player on LDR
// @namespace     http://antipop.gs/ns/greasemonkey/ldr_youtube_player
// @include       http://reader.livedoor.com/reader*
// ==/UserScript==

(function(){
    var w       = unsafeWindow;
    var _onload = w.onload;
    var onload  = function(){
        with (w) {
            var playerId = 'GM_youtube_player';

            Keybind.add('y', function () {
                            if ($('overlay')) {
                                hidePlayer();
                            }
                            else {
                                showPlayer();
                            }
                        });

            function showPlayer () {
                var item = get_active_item(true);
                if (item) {
                    var regexp = new RegExp('^http://(?:www\\.)?youtube\\.com/(?:watch)?\\?.*v=([^&]+).*$', 'i');
                    if (item.link.match(regexp)) {
                        var overlay = $N("div", {id : 'overlay'});
                        var player  = createPlayer(RegExp.$1);
                        [overlay, player].forEach(function(e){document.body.appendChild(e)});
                        centering(player.id, 0, 50);
                    }
                }
            }

            function hidePlayer () {
                [playerId, 'overlay'].forEach(function(id){DOM.remove(id);});
            }

            function createPlayer (videoId) {
                var videoSrc = ['http://www.youtube.com/v/', videoId].join('');

                var object = $N('object', {
                                    id     : playerId,
                                    width  : 425,
                                    height : 350,
                                    style  : {position : 'absolute'}
                                });
                var param  = $N('param',  {
                                    name   : 'movie',
                                    value  : videoSrc
                                });
                var embed  = $N('embed',  {
                                    width  : 425,
                                    height : 350,
                                    type   : 'application/x-shockwave-flash',
                                    src    : videoSrc
                                });

                [param, embed].forEach(function(e){object.appendChild(e);});
                return object;
            }
        }
    };

    w.onload = function(){
        _onload();
        onload();
    };
})();