日記はScrapboxに移動しました。

  • RimoCh – Rimoのユーザチャンネルを管理・共有するサービス

    , ,

    f:id:antipop:20070325205555p:image
    みんなが大好きRimoが、チャンネルを作って公開できるようになったってんで、かなりと強まりまくり、大興奮!DARAOにも同様の機能があったりするのだけど
    しかしいまんとこ、両者ともにチャンネルを作りっぱなしにするだけで、自分の作ったチャンネルを管理・共有するのがめんどいので、RimoChというサービスを作りました。

    RimoChは、はてなが提供しているRimoのチャンネル機能を拡張するサービスです。現在のところRimoでは、チャンネルを作ることはできますが、そのチャンネルを管理したり、簡単に共有したりすることができません。RimoChを使うと、はてなIDがある方なら誰でも、Rimoチャンネルを管理・共有できます。

    404 ERROR – Page Not Found

    YouTubeのビデオへのリンクがたくさんあるようなページ(各種まとめサイトや、自分のブックマークやブログ等)からブックマークレットでもってチャンネルを作成します。より多くのひとが作ったチャンネルは、トップページに「人気チャンネル」として表示されます。あと、一応Wiiにも対応してたりします。つってもまぁ、UA名がWiiのものっぽかったら、文字をちょっとでかくしてるだけですが。
    Rimo(リィモ)開発日記 – ユーザーチャンネルの改善について」にもアナウンスされている通り、人気・新着チャンネルのみなら、すでに大元のRimoにて提供されていたりします(Rimo – ユーザーチャンネル」)。ユーザ単位でのチャンネル管理機能にもそのうち対応するだろうと期待していますが、まぁそれまでのつなぎってことで(「ウェブサービス作りたい期」なので><)。
    どうぞご利用ください。

  • SPANK HAPPY 讃

    ,


    僕は SPANK HAPPY が好き過ぎる(岩澤瞳さん在籍の第 2 期です。念為)。
    CDを聴き始めると、その日は延々彼らの音楽にうっとりするだけで終わってしまうのだし、こうしてたまたまYouTubeに上がってる映像をちょっと観たりするだけでも、あまりの美しさに思わず落涙しちゃう。こんなに素晴しい音楽が既に失われてしまっており、その状態で今後数十年の人生を送らなければならないという事実に、それに気付くたびに本当に愕然とする。喪失と甘美。とってつけたような、しかしこれ以上なく美しい組み合わせ。いや、嘘。悲しさに、胸がキリキリする……。
    つか、DVD なりなんなりで映像リソースが公式にリリースされていれば、別に YouTube でなんて観たくないわけです。こういう映像リソースって、多分たくさんあるわけですよね、商品化されてないだけで。しかしたとえば「SPANK HAPPYライブ映像全集DVD全6巻」とか出したところで、ぶっちゃけまったく売れなさそうではある。いくらぐらいならペイするんだろう……。僕には、数十万円程度しか出せませんが……。
    なんかさー、もうこういうのこそウェブ進化論なすごい話が解決すべき問題なのです。ネットが我々の人生/生活に本当に決定的な影響をもたらすって、それをやるのが Google でも Apple/iTS なんでもいいけど、たとえば SPANK HAPPY の現存する映像リソース全てが商品化され、いつでもアクセスできるってことなんだよね。だからウェブとか、いくら偉い先生方が進化だとか 2.0 だとかゆっても、いまんとこ、無意味な存在。だって、僕にとって人生/生活とは、そういうことなんだもん。
    もうなんでもいいからとにかく SPANK HAPPY 映像を観まくりたい!全部観たい!あと、’90 年代後半は宮台先生、’00 年代前半は菊地成孔氏に私淑しまくってこの 10 年を過ごしてきて、もちろん菊地氏の今後の活動にもほんと期待しまくりだけど、なんかもう ’04 年から時間が止まっている感じがしてる。この気分と、近時の宮台文庫本・まとめ本ラッシュとは、個人的にはリンクしまくりなのだけど、誰にも理解され得ない話だと思うので、割愛。

    インターナショナル・クライン・ブルー

    ANGELIC

  • Wii ブラウザ用 YouTube プレイヤを作った

    ,

    Wii がリリースされた直後から、Wii ブラウザに最適化された YouTube 観賞用のサービスはたくさん公開されてきたのですが、いずれにもちょっと不満なところがあったので、自分用に作りました。

    • WiiPoP (名前募集中! ykskさんに名前つけてもらいました!ありがとうございます!)

    パソコンから見ると、特に IE だと崩れてたりしますが、まぁ一応動きます。が、是非 Wii でご覧ください。

    1. ページ上部から、ビデオを検索する。
    2. 検索結果が表示されたら、観たい動画をクリックして選択すると背景色が変わり、プレイリストに入る。
    3. プレイリストは複数の検索結果から作ることができる。
    4. 動画を選んだら、プレイリストを編集する。ドラッグ & ドロップで順番を変えたり、いらないものを削除したり。
    5. 動画を再生する。プレイリストに入っている順番で、自動的に次々再生される。

    他サービスと比較した場合の優位点は、プレイリストを作って、動画を自動で次々再生していくところ。
    最近、Wii で YouTube の動画を観ながら、エアロバイクをこいでエキササイズ、というか、ダイエットに励んでいたりします。楽しく動画を観ながらだと、いつの間にか時間がどんどん過ぎていくし、あんまり辛くも感じないので、なかなかいい運動になってるんじゃないかと思ったりしてます。
    で、その際、YouTube の動画を探すのに、上述したような既存の Wii ブラウザ用サービスを使っていたのですが、運動をしながらだと、Wii リモコンを細かく操作して、狭いポイントでクリックしたりする作業って、難しいんですよね。何度も失敗してイライラします。それが、ビデオをひとつ見終わるごとにくりかえされる。だんだん、ビデオを観るのもつらくなるし、そうなると運動もしたくなくなります。これではダイエットもままなりません!!!
    というわけで、Wii Player を作りました。上記した手順でもって、あらかじめプレイリストを作っておいて、あとはそれを再生するだけ。なかなか快適です。
    ただまぁ、ちと問題もあって、自動再生は、YouTube API から返された動画の再生時間を元に、JavaScript の setTimeout 関数を用いて実現しているのですが、YouTube の動画が回線状況等で途中でプツプツとまったりすると、動画の時間と JavaScript が保持している時間とがあわなくなってきます。とりあえず、次の動画を再生するインターバルを 15 秒とか置いてみているのですが、微妙な感じ。このへんはおいおい考えていきたいところです。

    メモ

    Wii Player のソースと、利用したライブラリ等を、以下に挙げておきます。
    ソース:

    バックエンド:

    クライアントサイド:

    あと、とりあえず、TODO を以下にメモ。

    • gettext で国際化(現在は、とりあえず怪しげな英語のみ)。
    • pagination がダサいのをどうにかする。
    • トップページに、人気検索語の一覧を表示する 対応済。
    • プレイヤ画面で、いま流れている動画をスキップするボタンをつける 対応したー。
    • インターバルをユーザが設定できるようにする 対応した。
    • 名前をどうにかする(ネーミングセンスがない><) ykskさんに名前つけてもらいました!ありがとうございます!
    Wii
    • 任天堂
    • 2006-12-02
    • ¥ 24,999
    • Video Games

    YouTube革命 テレビ業界を震撼させる「動画共有」ビジネスのゆくえ
    • 神田 敏晶
    • ソフトバンククリエイティブ
    • 2006-12-16
    • ¥ 735
    • Book

  • "SOMEDAY OVER THE WINDOW" / 抵抗すること / かわいい女の子

    , , , ,

    イルコモンズさんによる、キース・ジャレットの「虹の彼方に」と、今年 7 月から 8 月にかけてのレバノン侵攻におけるベイルート空爆の映像とのマッシュアップに、なんというか、揺れた。

    A REQUIEM for the late Lebanese citizenz. Tele-Sympathetic Mash-Up of Two Vidz on YouTube (i.e.”War on Lebanon, July 16, 2006″ & “Keith Jarrett – Over the Rainbow”). It’s an experiment of the Ghost Tele-Vision (inspired by Jacques Derrida‘s “Echographies dela television) on the real alternative tv; YouTube, against the LEBANON WAR.

    思わず「美しい」といってしまいそうになるのをこらえながら。あらゆる感情が湧き起こり、そしてそれら全ての感情について「いや、そういうことじゃないのだ」とつぶやきながら、ただただ揺れた。

    そう、そういうことじゃないんです、これは。これが何なのかはイルコモンズにだって、わかりません。うつくしいのかおぞましいのか、リアリズムなのかファンタジーなのか、人道的なのか残酷なのか、レクイエムなのかプロパガンダなのか、よくわかりません。わからないけど、ほとんど偶然にできてしまったこの映像と音楽には、人の心を揺さぶる「何か」があるのを感じ、それは、文化や言語や世代や国家を越えて共有可能なものだと思ったし、そうあってほしいと思ったからこそ、批判や反論や違和感はあるとしても、いつか必ずそれを飛び越えて、その彼方にいる誰かに届くはずだと思って YouTube にアップしました。

    そして、この映像に揺れた次の瞬間には、9/30 に BS で放送された「Hello! Project 2006 Summer – ワンダフルハーツランド -」の録画を観て感動を覚えているのだし、また、いまもそれを観ながらこのエントリを書いているのだ。

    モーニング娘。”をはじめとする“つんく♂”がプロデュースしたアイドルが一堂に会する音楽イベント『ハロープロジェクト2006』。子どもたちから親の世代まで幅広い支持を集めているこのコンサートは今年で8年目になる。恒例のシャッフルユニットを含め、元気あふれる彼女達のステージショーの模様をたっぷりと紹介する。
    今回、“モーニング娘。”のメンバー“紺野あさ美”と“小川麻琴”がこのコンサートをもって卒業。番組では、二人を贈る他のメンバーたちのスペシャルインタビューを交え、感動的なライブの模様をたっぷりと贈る。
    (収録 7 月 23 日・国立代々木競技場第一体育館)

    だって、それこそがリアルなのだし。

  • http 記法拡張テスト

    ,

    はてなダイアリー日記 – 日記で簡単に動画を紹介できる http記法の拡張について」とのこと。
    スペジェネ on YouTube
    http://youtube.com/watch?v=4g-2zxbqfvA
    スペジェネ on Google Video
    http://video.google.com/videoplay?docid=-9219772437705180899
    スペジェネ on Google Video の URL に “#1m20” をくっつけてみた(Google Video の新機能? [ SEOに疲れたら読むブログ ]あたり参照)。
    http://video.google.com/videoplay?docid=-9219772437705180899#1m20
    外部からの swf 貼り付け時のビデオ開始時間指定はやっぱだめぽ。これははてなではなく、Google Video 側の仕様のせいだけど。

  • Update: LDR で最速動画ウォッチング + YouTube Anywhere

    , ,

    “どこでも YouTube” を実現する Greasemonkey スクリプト YouTube Anywhere」で公開したスクリプトを、せっかくなので、LDR にも対応してみました。「livedoor Reader + YouTube + はてなブックマークで最速動画ウォッチング」と「“どこでも YouTube” を実現する Greasemonkey スクリプト YouTube Anywhere」を足して 2 で割らない感じ。つってもまぁ、最低限 LDR 上で動くようにしただけなのがアレ。それなりに動くので、まぁいいや。あと、ついでにnirvashの日記に触発されて、Qooqle Video Clippers!HATENA-TUBE のフィードにも対応。
    使いかたを再度説明。
    LDR 上では、YouTube, Qooqle, HATENA-TUBE の動画エントリを見てる時に、ショートカットキー “y” を押すとプレイヤ表示、さらに “y” を押すとプレイヤを隠します。その他のサイト(デフォルトでは del.icio.usはてなブックマーク)では、YouTube の動画ページのリンクの脇にアイコンが表示されるので、クリックするとプレイヤが表示されます。
    プレイヤに表示されているアイコンをあれこれ押してみればわかりますが、動画ダウンロードや、各種クリッピングサービスへのリンク等が配置されています。
    インストールは以下に示すリンクから。このスクリプトをインストールしたら、以前「livedoor Reader + YouTube + はてなブックマークで最速動画ウォッチング」で公開した YouTube Player on LDR は必要ありませんので、そっはアンインストールしちゃってください。
    インストール: youtube_anywhere.user.js

    // ==UserScript==
    //
    // @name          YouTube Anywhere
    // @namespace     http://antipop.gs/ns/greasemonkey/youtube_anywhere
    // @include       http://reader.livedoor.com/reader*
    // @include       http://b.hatena.ne.jp/*
    // @include       http://del.icio.us/*
    //
    // ==/UserScript==
    //
    // ==Configuration==
    //
    // add other domains to @include for more use
    //
    // - include YouTube.
    // @include       *youtube.com/*
    //
    // - include whole the web
    // @include       *
    //
    //==/Configuration==
    //
    //==Acknowledgments==
    //
    // Bitcons >> SOME RANDOM DUDE
    //  - http://somerandomdude.net/srd-projects/bitcons/
    //
    //==/Acknowledgments==
    //
    // ==Copyright==
    //
    // Copyright (C) 2006 by Kentaro Kuribayashi
    //
    // This script is distributed under the CCPL by-sa
    //  - See: http://creativecommons.org/licenses/by-sa/2.5/
    //
    (function(){
    var playerContainerId = 'GM_youtube_player';
    var playerWidth  = 425;
    var playerHeight = 350;
    var overlayId    = 'GM_overlay';
    var regexp = [
    new RegExp('^http://(?:www\\.)?youtube\\.com/(?:watch)?\\?.*v=([^&]+).*$', 'i'),
    new RegExp('^http://clippers\\.qooqle\\.jp/video/([^/]+).*$', 'i'),
    new RegExp('^http://www\\.fladdict\\.net/app/hatenatube/#v=([^&]+).*$', 'i'),
    ];
    if (location.href.match('^http://reader\\.livedoor\\.com/reader.*$', 'i')) {
    var w = unsafeWindow;
    var _onload = w.onload;
    var onload  = function(){with (w) {
    Keybind.add('y', function () {
    if ($(playerContainerId)) {
    hidePlayer();
    }
    else {
    var item = get_active_item(true);
    if (item) {
    regexp.forEach(function (r) {
    if (item.link.match(r)) {
    showPlayer(RegExp.$1, item.title);
    }
    });
    }
    }
    });
    }};
    w.onload = function(){
    _onload();
    onload();
    };
    }
    else {
    $A(document.links).forEach(function (link) {
    if (link.href.match(regexp[0])) {
    var videoId    = RegExp.$1;
    var videoTitle = link.innerHTML.replace(/<.+?>/g, '');
    var icon = $C('img', {
    'src'   : 'http://www.youtube.com/favicon.ico',
    'alt'   : 'YouTube',
    'title' : 'watch this movie',
    'style' : {
    'marginRight' : '0.5em',
    'cursor'      : 'pointer',
    },
    'event' : [{
    'name'     : 'click',
    'callback' : function () { showPlayer(videoId, videoTitle); },
    'flag'     : false,
    }],
    });
    link.parentNode.insertBefore(icon, link);
    }
    });
    }
    function $ (id) { return document.getElementById(id); };
    function $A (arg) {
    var array = [];
    for (var i = 0; i < arg.length; i++) {
    array.push(arg[i]);
    }
    return array;
    }
    function $C (tag, prop) {
    var element = document.createElement(tag);
    for (var i in prop) {
    if (i == 'style') {
    for (var p in prop[i]) {
    element.style[p] = prop[i][p];
    }
    }
    else if (i == 'event') {
    prop[i].forEach(function (e) {
    element.addEventListener(e.name, e.callback, e.flag);
    });
    }
    else {
    element[i] = prop[i];
    }
    }
    return element;
    };
    function createPlayerContainer (videoId, videoTitle) {
    var playerContainer = $C('div', {
    'id'     : playerContainerId,
    'style'  : {
    'position'        : 'fixed',
    'zIndex'          : '100',
    'backgroundColor' : '#ffffff',
    'padding'         : '0.5em 1.5em',
    },
    });
    var playerHeader = createPlayerHeader(videoTitle);
    var player       = createPlayer(videoId);
    var playerFooter = createPlayerFooter(videoId, videoTitle, player);
    [playerHeader, player, playerFooter].forEach(function (e) {
    playerContainer.appendChild(e);
    });
    return playerContainer;
    }
    function createPlayerHeader (videoTitle) {
    var playerHeader = $C('p', {
    'style' : {
    'fontWeight' : 'bold',
    'margin'     : '0.5em 2em 0.5em 0',
    }
    });
    var closeButton = $C('img', {
    'id'    : 'GM_close_utton',
    'src'   : getImageUrl('close'),
    'title' : 'Hide this player',
    'style' : {
    'display'         : 'block',
    'position'        : 'absolute',
    'top'             : '5px',
    'right'           : '5px',
    'cursor'          : 'pointer',
    'backgroundColor' : '#00cc00',
    },
    'event' : [
    {
    'name'     : 'click',
    'callback' : function () { hidePlayer(); },
    'flag'     : false,
    },
    {
    'name'     : 'mouseover',
    'callback' : function () { $('GM_close_utton').style.backgroundColor = '#ffd700'; },
    'flag'     : false,
    },
    {
    'name'     : 'mouseout',
    'callback' : function () { $('GM_close_utton').style.backgroundColor = '#00cc00'; },
    'flag'     : false,
    },
    ],
    });
    [document.createTextNode(videoTitle), closeButton,].forEach(function (e) {
    playerHeader.appendChild(e);
    });
    return playerHeader;
    }
    function createPlayerFooter (videoId, videoTitle, player) {
    var playerFooter = $C('div', {
    'style' : {
    'padding' : '0.5em 0',
    }
    });
    var linkContainer = $C('p', {style : { 'textAlign' : 'center', 'margin' : '0', }});
    var youtubeUri    = ['http://www.youtube.com/watch?v=', videoId].join('');
    [
    {
    'id'       : 'GM_download',
    'title'    : 'download this video',
    'getUri'   : ['http://youtubech.com/test/read.cgi?dl=', videoId].join(''),
    'label'    : 'Download',
    'image'    : 'download',
    },
    {
    'id'       : 'GM_post_to_hatena',
    'title'    : 'post to Hatena::Bookmark',
    'getUri'   : ['http://b.hatena.ne.jp/add?mode=confirm&url=', encodeURIComponent(youtubeUri)].join(''),
    'label'    : 'Hatena',
    'image'    : 'arrow',
    },
    {
    'id'       : 'GM_post_to_delicious',
    'title'    : 'post to del.icio.us',
    'getUri'   : ['http://del.icio.us/post?v=4;url=', encodeURIComponent(youtubeUri), ';title=', encodeURIComponent(videoTitle)].join(''),
    'label'    : 'del.icio.us',
    'image'    : 'arrow',
    },
    {
    'id'       : 'GM_post_to_qooqle',
    'title'    : 'post to qooqle',
    'getUri'   : ['http://clippers.qooqle.jp/post?url=', encodeURIComponent(youtubeUri)].join(''),
    'label'    : 'Qooqle',
    'image'    : 'arrow',
    },
    ].forEach(function (i) {
    var link = $C('span', {
    'id'    : i.id,
    'title' : i.title,
    'style' : {
    'color'         : '#00cc00',
    'textIndent'    : '20px',
    'verticalAlign' : 'middle',
    'marginRight'   : '0.5em',
    'cursor'        : 'pointer',
    },
    'event' : [
    {
    'name'     : 'click',
    'callback' : function () { window.open(i.getUri); },
    'flag'     : false,
    },
    {
    'name'     : 'mouseover',
    'callback' : function () { $(i.id).style.color = '#ffc125'; },
    'flag'     : false,
    },
    {
    'name'     : 'mouseout',
    'callback' : function () { $(i.id).style.color = '#00cc00'; },
    'flag'     : false,
    },
    ],
    });
    var icon = $C('img', {
    'src'   : getImageUrl(i.image),
    'style' : {
    'marginRight'     : '0.5em',
    'backgroundColor' : '#00cc00',
    },
    });
    [icon, document.createTextNode(i.label)].forEach(function (e) {
    link.appendChild(e);
    });
    linkContainer.appendChild(link);
    });
    playerFooter.appendChild(linkContainer);
    [
    {
    'label' : 'URI:',
    'id'    : 'youtube_uri',
    'value' : ['http://www.youtube.com/watch?v=', videoId].join(''),
    },
    {
    'label' : 'Player:',
    'id'    : 'youtube_embed',
    'value' : player.innerHTML,
    },
    {
    'label' : 'Hatena:',
    'id'    : 'hatena_notation',
    'value' : ['[http://youtubech.com/test/read.cgi', encodeURIComponent(['?dl=', videoId, '&.flv'].join('')), ':movie]'].join(''),
    },
    ].forEach(function (i) {
    var inputContainer = $C('p', { 'style' : { 'margin': '0.2em 0 0 0'} });
    var label = $C('label', {
    'for'   : i.id,
    });
    label.innerHTML = i.label;
    var input = $C('input', {
    'id'    : i.id,
    'style' : {
    'border'   : 'solid 1px #333333',
    'width'    : '80%',
    'position' : 'absolute',
    'right'    : '1.5em',
    },
    'event'   : [
    {
    'name'     : 'focus',
    'callback' : function () { $(i.id).select(); },
    'flag'     : false,
    },
    {
    'name'     : 'click',
    'callback' : function () { $(i.id).select(); },
    'flag'     : false,
    },
    ]
    });
    input.value = i.value;
    [label, input].forEach(function (e) {
    inputContainer.appendChild(e);
    });
    playerFooter.appendChild(inputContainer);
    });
    return playerFooter;
    }
    function createPlayer (videoId) {
    var videoSrc = ['http://www.youtube.com/v/', videoId].join('');
    var div    = $C('div', {});
    var object = $C('object', {
    'width'  : playerWidth,
    'height' : playerHeight,
    });
    var param  = $C('param',  {
    'name'   : 'movie',
    'value'  : videoSrc,
    });
    var embed  = $C('embed',  {
    'width'  : playerWidth,
    'height' : playerHeight,
    'type'   : 'application/x-shockwave-flash',
    'src'    : videoSrc,
    });
    [param, embed].forEach(function (e) { object.appendChild(e); });
    div.appendChild(object);
    return div;
    }
    function showPlayer (videoId, videoTitle) {
    var playerContainer  = createPlayerContainer(videoId, videoTitle);
    var overlay = $C('div', {
    id     : overlayId,
    style  : {
    'position'        : 'fixed',
    'top'             : '0%',
    'left'            : '0%',
    'width'           : '100%',
    'height'          : '100%',
    'zIndex'          : '99',
    'backgroundImage' : ['url("', getImageUrl('overlay'), '")'].join(''),
    },
    event  : [{
    'name'     : 'click',
    'callback' : function () { hidePlayer(); },
    'flag'     : false,
    }]
    });
    [overlay, playerContainer].forEach(function (e) {
    document.body.appendChild(e);
    });
    centering($(playerContainerId), 0, 0);
    }
    function hidePlayer () {
    [$(playerContainerId), $(overlayId)].forEach(function (e) {
    e.parentNode.removeChild(e);
    });
    }
    function centering (element, x, y) {
    with (element.style) {
    left = ((window.innerWidth  - element.offsetWidth)  / 2 + (x)) + 'px';
    top  = ((window.innerHeight - element.offsetHeight) / 2 + (y)) + 'px';
    }
    }
    function getImageUrl (name) {
    var images = {
    'close'    : "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%01%03%00%00%00%25%3Dm%22%00%00%00%03sBIT%08%08%08%DB%E1O%E0%00%00%00%06PLTE%FF%FF%FF%FF%FF%FFU%7C%F5l%00%00%00%02tRNS%FF%00%E5%B70J%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00!tEXtSoftware%00Macromedia%20Fireworks%204.0%EA%26'u%00%00%00%16tEXtCreation%20Time%0006%2F02%2F06%3Eg%BF%E4%00%00%00%22IDATx%9Cc%F8%FF%9F%01%8E%3E%9Fg%F8%D8%CF%F0C%9E%E1%8F%3D%08%01%19%40.P%10I%0D%00%8C%AA%1B%19%A3%7D%C5%A0%00%00%00%00IEND%AEB%60%82",
    'download' : "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%01%03%00%00%00%25%3Dm%22%00%00%00%03sBIT%08%08%08%DB%E1O%E0%00%00%00%06PLTE%FF%FF%FF%FF%FF%FFU%7C%F5l%00%00%00%02tRNS%FF%00%E5%B70J%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00!tEXtSoftware%00Macromedia%20Fireworks%204.0%EA%26'u%00%00%00%16tEXtCreation%20Time%0006%2F02%2F06%3Eg%BF%E4%00%00%00'IDATx%9Cc%F8%FF%9F%01%82%FE%D5C%D1%07~%86%1F%F2%0C%7F%EC%19%BE%E53%FC%BE%CF%F0w%3FH%10%A6%0C%00p%88%1A5%81%FD%3F%D0%00%00%00%00IEND%AEB%60%82",
    'arrow'    : "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%01%03%00%00%00%25%3Dm%22%00%00%00%03sBIT%08%08%08%DB%E1O%E0%00%00%00%06PLTE%FF%FF%FF%FF%FF%FFU%7C%F5l%00%00%00%02tRNS%FF%00%E5%B70J%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00!tEXtSoftware%00Macromedia%20Fireworks%204.0%EA%26'u%00%00%00%16tEXtCreation%20Time%0006%2F02%2F06%3Eg%BF%E4%00%00%00%26IDATx%9Cc%F8%FF%9F%01%8E%3E%F0%83%D0%7F~%86%7F%FC%0C%7F%FC%19~%9Cg%F8x%9E%E1%F3y%06%245%00p%20%1A%9E%26%CAE%0A%00%00%00%00IEND%AEB%60%82",
    'overlay'  : "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%01%00%00%00%01%01%03%00%00%00%25%DBV%CA%00%00%00%03sBIT%08%08%08%DB%E1O%E0%00%00%00%06PLTE%FF%FF%FF%00%00%00U%C2%D3~%00%00%00%02tRNS%00%BB*%20%A7%3C%00%00%00%09pHYs%00%00%1B%BC%00%00%1B%BC%01%BA%B7%A0%BB%00%00%00!tEXtSoftware%00Macromedia%20Fireworks%204.0%EA%26'u%00%00%00%0AIDATx%9Cch%00%00%00%82%00%81w%CDr%B6%00%00%00%00IEND%AEB%60%82",
    };
    return images[name];
    }
    })();
  • "どこでも YouTube" を実現する Greasemonkey スクリプト YouTube Anywhere

    ,

    YouTube の動画を鑑賞・収集する上で便利で素敵なサービスがいろいろと登場しています。

    ただまぁ僕の Web ブラウズのやり方は「livedoor Reader + YouTube + はてなブックマークで最速動画ウォッチング」で紹介したように、厳選したサービスを使い込む感じで、それ以外はまぁひと様のリンクとか、自分とこのブックマークに蓄積したもの経由でしか YouTube の動画を見ないだろうな、とか思うわけです。
    そんな折り、かせいさんとこ – del.icio.us上のYouTubeへのリンクを直接見たりダウンロードできるGreasemonkey にて公開されていたスクリプトに触発されて、僕も似たようなものを作ってみました。YouTube の動画へのリンクがあると、そのリンクの脇に YouTube アイコンを表示、アイコンをクリックすると HATENA-TUBE ライクなプレイヤが現われるってなもの。
    YouTube player on Hatena::Bookmark
    デフォルトでは del.icio.usはてなブックマーク上のみで動作するよう設定してありますが、「ツール -> Manage UserScripts」から include するドメインを増やすよう設定すれば、いろんなところで使えます。
    まぁ、サイトによってはスタイルとかがかなりと悲惨なことにもなりかねませんが、そのへんは見なかったことにして、あまり気にしないでください。

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

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

    // ==UserScript==
    //
    // @name          YouTube Anywhere
    // @namespace     http://antipop.gs/ns/greasemonkey/youtube_anywhere
    // @include       http://b.hatena.ne.jp/*
    // @include       http://del.icio.us/*
    //
    // ==/UserScript==
    //
    // ==Configuration==
    //
    // add other domains to @include for more use
    //
    // - include YouTube.
    // @include       *youtube.com/*
    //
    // - include whole the web
    // @include       *
    //
    //==/Configuration==
    //
    //==Acknowledgments==
    //
    // Bitcons >> SOME RANDOM DUDE
    //  - http://somerandomdude.net/srd-projects/bitcons/
    //
    //==/Acknowledgments==
    //
    // ==Copyright==
    //
    // Copyright (C) 2006 by Kentaro Kuribayashi
    //
    // This script is distributed under the CCPL by-sa
    //  - See: http://creativecommons.org/licenses/by-sa/2.5/
    //
    // ==/Copyright==
    //
    (function(){
    var playerContainerId = 'GM_youtube_player';
    var playerWidth  = 425;
    var playerHeight = 350;
    var overlayId    = 'GM_overlay';
    var regexp       = new RegExp('^http://(?:www\\.)?youtube\\.com/(?:watch)?\\?.*v=([^&]+).*$', 'i');
    $A(document.links).forEach(function (link) {
    if (link.href.match(regexp)) {
    var videoId    = RegExp.$1;
    var videoTitle = link.innerHTML.replace(/<.+?>/g, '');
    var icon = $C('img', {
    'src'   : 'http://www.youtube.com/favicon.ico',
    'alt'   : 'YouTube',
    'title' : 'watch this movie',
    'style' : {
    'marginRight' : '0.5em',
    'cursor'      : 'pointer',
    },
    'event' : [{
    'name'     : 'click',
    'callback' : function () { showPlayer(videoId, videoTitle); },
    'flag'     : false,
    }],
    });
    link.parentNode.insertBefore(icon, link);
    }
    });
    function $ (id) { return document.getElementById(id); };
    function $A (arg) {
    var array = [];
    for (var i = 0; i < arg.length; i++) {
    array.push(arg[i]);
    }
    return array;
    }
    function $C (tag, prop) {
    var element = document.createElement(tag);
    for (var i in prop) {
    if (i == 'style') {
    for (var p in prop[i]) {
    element.style[p] = prop[i][p];
    }
    }
    else if (i == 'event') {
    prop[i].forEach(function (e) {
    element.addEventListener(e.name, e.callback, e.flag);
    });
    }
    else {
    element[i] = prop[i];
    }
    }
    return element;
    };
    function createPlayerContainer (videoId, videoTitle) {
    var playerContainer = $C('div', {
    'id'     : playerContainerId,
    'style'  : {
    'position'        : 'fixed',
    'zIndex'          : '100',
    'backgroundColor' : '#ffffff',
    'padding'         : '0.5em 1.5em',
    },
    });
    var playerHeader = createPlayerHeader(videoTitle);
    var player       = createPlayer(videoId);
    var playerFooter = createPlayerFooter(videoId, videoTitle, player);
    [playerHeader, player, playerFooter].forEach(function (e) {
    playerContainer.appendChild(e);
    });
    return playerContainer;
    }
    function createPlayerHeader (videoTitle) {
    var playerHeader = $C('p', {
    'style' : {
    'fontWeight' : 'bold',
    'margin'     : '0.5em 2em 0.5em 0',
    }
    });
    var closeButton = $C('img', {
    'id'    : 'GM_close_utton',
    'src'   : getImageUrl('close'),
    'title' : 'Hide this player',
    'style' : {
    'display'         : 'block',
    'position'        : 'absolute',
    'top'             : '5px',
    'right'           : '5px',
    'cursor'          : 'pointer',
    'backgroundColor' : '#00cc00',
    },
    'event' : [
    {
    'name'     : 'click',
    'callback' : function () { hidePlayer(); },
    'flag'     : false,
    },
    {
    'name'     : 'mouseover',
    'callback' : function () { $('GM_close_utton').style.backgroundColor = '#ffd700'; },
    'flag'     : false,
    },
    {
    'name'     : 'mouseout',
    'callback' : function () { $('GM_close_utton').style.backgroundColor = '#00cc00'; },
    'flag'     : false,
    },
    ],
    });
    [document.createTextNode(videoTitle), closeButton,].forEach(function (e) {
    playerHeader.appendChild(e);
    });
    return playerHeader;
    }
    function createPlayerFooter (videoId, videoTitle, player) {
    var playerFooter = $C('div', {
    'style' : {
    'padding' : '0.5em 0',
    }
    });
    var linkContainer = $C('p', {style : { 'textAlign' : 'center', 'margin' : '0', }});
    var youtubeUri    = ['http://www.youtube.com/watch?v=', videoId].join('');
    [
    {
    'id'       : 'GM_download',
    'title'    : 'download this video',
    'getUri'   : ['http://youtubech.com/test/read.cgi?dl=', videoId].join(''),
    'label'    : 'Download',
    'image'    : 'download',
    },
    {
    'id'       : 'GM_post_to_hatena',
    'title'    : 'post to Hatena::Bookmark',
    'getUri'   : ['http://b.hatena.ne.jp/add?mode=confirm&url=', encodeURIComponent(youtubeUri)].join(''),
    'label'    : 'Hatena',
    'image'    : 'arrow',
    },
    {
    'id'       : 'GM_post_to_delicious',
    'title'    : 'post to del.icio.us',
    'getUri'   : ['http://del.icio.us/post?v=4;url=', encodeURIComponent(youtubeUri), ';title=', encodeURIComponent(videoTitle)].join(''),
    'label'    : 'del.icio.us',
    'image'    : 'arrow',
    },
    {
    'id'       : 'GM_post_to_qooqle',
    'title'    : 'post to qooqle',
    'getUri'   : ['http://clippers.qooqle.jp/post?url=', encodeURIComponent(youtubeUri)].join(''),
    'label'    : 'Qooqle',
    'image'    : 'arrow',
    },
    ].forEach(function (i) {
    var link = $C('span', {
    'id'    : i.id,
    'title' : i.title,
    'style' : {
    'color'         : '#00cc00',
    'textIndent'    : '20px',
    'verticalAlign' : 'middle',
    'marginRight'   : '0.5em',
    'cursor'        : 'pointer',
    },
    'event' : [
    {
    'name'     : 'click',
    'callback' : function () { window.open(i.getUri); },
    'flag'     : false,
    },
    {
    'name'     : 'mouseover',
    'callback' : function () { $(i.id).style.color = '#ffc125'; },
    'flag'     : false,
    },
    {
    'name'     : 'mouseout',
    'callback' : function () { $(i.id).style.color = '#00cc00'; },
    'flag'     : false,
    },
    ],
    });
    var icon = $C('img', {
    'src'   : getImageUrl(i.image),
    'style' : {
    'marginRight'     : '0.5em',
    'backgroundColor' : '#00cc00',
    },
    });
    [icon, document.createTextNode(i.label)].forEach(function (e) {
    link.appendChild(e);
    });
    linkContainer.appendChild(link);
    });
    playerFooter.appendChild(linkContainer);
    [
    {
    'label' : 'URI:',
    'id'    : 'youtube_uri',
    'value' : ['http://www.youtube.com/watch?v=', videoId].join(''),
    },
    {
    'label' : 'Player:',
    'id'    : 'youtube_embed',
    'value' : player.innerHTML,
    },
    {
    'label' : 'Hatena:',
    'id'    : 'hatena_notation',
    'value' : ['[http://youtubech.com/test/read.cgi', encodeURIComponent(['?dl=', videoId, '&.flv'].join('')), ':movie]'].join(''),
    },
    ].forEach(function (i) {
    var inputContainer = $C('p', { 'style' : { 'margin': '0.2em 0 0 0'} });
    var label = $C('label', {
    'for'   : i.id,
    });
    label.innerHTML = i.label;
    var input = $C('input', {
    'id'    : i.id,
    'style' : {
    'border'   : 'solid 1px #333333',
    'width'    : '80%',
    'position' : 'absolute',
    'right'    : '1.5em',
    },
    'event'   : [
    {
    'name'     : 'focus',
    'callback' : function () { $(i.id).select(); },
    'flag'     : false,
    },
    {
    'name'     : 'click',
    'callback' : function () { $(i.id).select(); },
    'flag'     : false,
    },
    ]
    });
    input.value = i.value;
    [label, input].forEach(function (e) {
    inputContainer.appendChild(e);
    });
    playerFooter.appendChild(inputContainer);
    });
    return playerFooter;
    }
    function createPlayer (videoId) {
    var videoSrc = ['http://www.youtube.com/v/', videoId].join('');
    var div    = $C('div', {});
    var object = $C('object', {
    'width'  : playerWidth,
    'height' : playerHeight,
    });
    var param  = $C('param',  {
    'name'   : 'movie',
    'value'  : videoSrc,
    });
    var embed  = $C('embed',  {
    'width'  : playerWidth,
    'height' : playerHeight,
    'type'   : 'application/x-shockwave-flash',
    'src'    : videoSrc,
    });
    [param, embed].forEach(function (e) { object.appendChild(e); });
    div.appendChild(object);
    return div;
    }
    function showPlayer (videoId, videoTitle) {
    var playerContainer  = createPlayerContainer(videoId, videoTitle);
    var overlay = $C('div', {
    id     : overlayId,
    style  : {
    'position'        : 'fixed',
    'top'             : '0%',
    'left'            : '0%',
    'width'           : '100%',
    'height'          : '100%',
    'zIndex'          : '99',
    'backgroundImage' : ['url("', getImageUrl('overlay'), '")'].join(''),
    },
    event  : [{
    'name'     : 'click',
    'callback' : function () { hidePlayer(); },
    'flag'     : false,
    }]
    });
    [overlay, playerContainer].forEach(function (e) {
    document.body.appendChild(e);
    });
    centering($(playerContainerId), 0, -10);
    }
    function hidePlayer () {
    [$(playerContainerId), $(overlayId)].forEach(function (e) {
    e.parentNode.removeChild(e);
    });
    }
    function centering (element, x, y) {
    with (element.style) {
    left = ((window.innerWidth  - element.offsetWidth)  / 2 + (x)) + 'px';
    top  = ((window.innerHeight - element.offsetHeight) / 2 + (y)) + 'px';
    }
    }
    function getImageUrl (name) {
    var images = {
    'close'    : "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%01%03%00%00%00%25%3Dm%22%00%00%00%03sBIT%08%08%08%DB%E1O%E0%00%00%00%06PLTE%FF%FF%FF%FF%FF%FFU%7C%F5l%00%00%00%02tRNS%FF%00%E5%B70J%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00!tEXtSoftware%00Macromedia%20Fireworks%204.0%EA%26'u%00%00%00%16tEXtCreation%20Time%0006%2F02%2F06%3Eg%BF%E4%00%00%00%22IDATx%9Cc%F8%FF%9F%01%8E%3E%9Fg%F8%D8%CF%F0C%9E%E1%8F%3D%08%01%19%40.P%10I%0D%00%8C%AA%1B%19%A3%7D%C5%A0%00%00%00%00IEND%AEB%60%82",
    'download' : "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%01%03%00%00%00%25%3Dm%22%00%00%00%03sBIT%08%08%08%DB%E1O%E0%00%00%00%06PLTE%FF%FF%FF%FF%FF%FFU%7C%F5l%00%00%00%02tRNS%FF%00%E5%B70J%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00!tEXtSoftware%00Macromedia%20Fireworks%204.0%EA%26'u%00%00%00%16tEXtCreation%20Time%0006%2F02%2F06%3Eg%BF%E4%00%00%00'IDATx%9Cc%F8%FF%9F%01%82%FE%D5C%D1%07~%86%1F%F2%0C%7F%EC%19%BE%E53%FC%BE%CF%F0w%3FH%10%A6%0C%00p%88%1A5%81%FD%3F%D0%00%00%00%00IEND%AEB%60%82",
    'arrow'    : "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%01%03%00%00%00%25%3Dm%22%00%00%00%03sBIT%08%08%08%DB%E1O%E0%00%00%00%06PLTE%FF%FF%FF%FF%FF%FFU%7C%F5l%00%00%00%02tRNS%FF%00%E5%B70J%00%00%00%09pHYs%00%00%0B%12%00%00%0B%12%01%D2%DD~%FC%00%00%00!tEXtSoftware%00Macromedia%20Fireworks%204.0%EA%26'u%00%00%00%16tEXtCreation%20Time%0006%2F02%2F06%3Eg%BF%E4%00%00%00%26IDATx%9Cc%F8%FF%9F%01%8E%3E%F0%83%D0%7F~%86%7F%FC%0C%7F%FC%19~%9Cg%F8x%9E%E1%F3y%06%245%00p%20%1A%9E%26%CAE%0A%00%00%00%00IEND%AEB%60%82",
    'overlay'  : "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%01%00%00%00%01%01%03%00%00%00%25%DBV%CA%00%00%00%03sBIT%08%08%08%DB%E1O%E0%00%00%00%06PLTE%FF%FF%FF%00%00%00U%C2%D3~%00%00%00%02tRNS%00%BB*%20%A7%3C%00%00%00%09pHYs%00%00%1B%BC%00%00%1B%BC%01%BA%B7%A0%BB%00%00%00!tEXtSoftware%00Macromedia%20Fireworks%204.0%EA%26'u%00%00%00%0AIDATx%9Cch%00%00%00%82%00%81w%CDr%B6%00%00%00%00IEND%AEB%60%82",
    };
    return images[name];
    }
    })();
  • 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();
    };
    })();
  • http 記法により YouTube の動画をはてなダイアリーに貼りつける方法

    ,

    以下のような記法を使って、URLのあとに:movieとつけるだけです。

    [http://www.youtube.com/watch?v=YrtQjBT3PXg:movie]

  • YouTube のタグによる検索結果の feed アイコンを表示する Greasemonkey スクリプト

    ,

    YouTube てば最高なんだけど、検索結果の feed ないの?なんで!とか思ってた。ページのいちばん下にある RSS アイコンをクリックしても説明ページが出てくるだけだし。「[戯] YouTube でタグによる RSS フィードを取得するには」を読んでそれが早とちりであることを知った。。

    YouTube では最近人気の動画の RSS フィードを配信していますが,タグによる RSS フィードも取得できることが分かりました.

    つわけで、以下のようなフォーマットになってるとのこと。

    (feed|http)://www.youtube.com/rss/tag/tag1+tag2+tag3.rss

    YouTube の説明には書かれてなかったけど、タグを複数指定する場合は “+ (%2B)” でタグをつないでやればいいみたい。以上、説明はちゃんと読みましょうね!というお話でした!!!
    ……ってんでは面白くもなんともないので、YouTube のタグによる検索結果の feed アイコンを表示する Greasemonkey スクリプトを書いてみました。日本語のタグもいけます。
    インストール: youtube_add_feed_icon.user.js

    // ==UserScript==
    // @name          Add Feed Icon for YouTube Search Result
    // @namespace     http://antipop.gs/ns/greasemonkey/youtube_add_feed_icon
    // @include       *youtube.com/results*
    // @include       *youtube.com/watch*
    // ==/UserScript==
    (function(){
    var $  = function (id)  { return document.getElementById(id); };
    var $C = function (tag) { return document.createElement(tag); };
    var input    = $('searchField');
    var keywords = encodeURIComponent(input.value.split(' ').join('+'));
    if (keywords == '') return;
    var feed = $C('a');
    with (feed) {
    id   = 'feed';
    href = ['http://www.youtube.com/rss/tag/', keywords, '.rss'].join('');
    }
    var feedIcon = $C('img');
    with (feedIcon) {
    id  = 'feed_icon';
    src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAANbY1E9YMgAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFWUExURfSRNut%2FMvudOvqcOfiZOf%2F58%2FKNNfaUN%2BZ%2FM%2BmFNeZ0L%2B6FNOh5MfCJNO6FM%2BNuLv748uiCNOiDNN9xMOyKNuF4MdxhK%2BeBM%2BF0MOp9MeqHNd5lLN1uL%2BN5MvmdQf3atf738umINud4L%2F3x5uBqLd5wMNpeKuJ2MeuJNeyBMv7y5uiFNeN5MeV0Lt5vL%2BV8MuV9MuR7MvzChPKTQvq%2Bg%2FuvXvSygPnXv%2B6aZPivafqsXv7mzu%2BdZOJwNvSmZ%2FrOp%2FOkZ%2F7s2u%2BNQfG3l%2FmfRfi0dfabROB1RfzjzfWpaPS9mPrDj%2B6ylf3fwe6rifi%2FjvehUPzZteiJVfnIm%2BR8R%2Fu5d%2FKjZvrTs%2FieRPupUuyWY%2FqiRvXAmOaLYP3lzeqJSe6RTPvm2PmlUvfDmfetafSsc%2FqzavfUvul%2BOfW%2Fmf7x5vGLNfeXOPmaOfWSN%2Bqsg%2F%2F%2F%2F%2F%2F%2F%2F8YnVFIAAABydFJOU%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAHzXy%2BgAAAD1SURBVHjaLM5Fm4JgFAXgCw4KiILdnWPrdHd3d%2FegfIf%2FvxnwmeW7OEEmCzW6HTHil%2BLVYI6ZxL6b%2Bdio1%2BMkV3%2FgSDMKNZ927y%2F%2FzY%2FUqZGfB6CdbQ5tSNSNPb9dFQDhwrbuo84wP7MC9Cy7RRK9i9r23vUgA2zobq5NEc%2BO1SFM8CfQVjklRX4nHY%2FXIMwaBfwocoUke%2B8ug9%2BxD2RlNUpxV%2F9grrdewySXxWkxQNX%2BJ%2FBoHGFK%2BcJhokXBwY2AJX0ZL%2FIa9sNJyjn413drb%2FpWPX%2FYKpeIpe0%2FnCKrxUS4vMDIZHXJJ7ZTlWiglSwx80%2BAAQCPUTbYfKCEOAAAAABJRU5ErkJggg%3D%3D';
    with (style) {
    marginRight   = '0.5em';
    verticalAlign = 'middle';
    border        = 'none';
    }
    }
    feed.appendChild(feedIcon);
    $('searchForm').insertBefore(feed, input);
    })();