ニコニコ動画をデュアルディスプレイみたいに見るぐりもん

ニコニコ動画で、複数の動画を並べて同時に鑑賞するためのぐりもんを作ってみました。
動作が不安定すぎて泣きそうです。もう少しがんばりたいです。

スクリーンショット

こんな感じになります。


リズム天国


Hot knows...

使い方

残念なことに、どんなにがんばってもGoogle Chrome以外では動作しませんでした。

Google ChromeGreasemetal をインストールして、上のniconico_multi.user.jsファイルをマイドキュメントの「userjs」フォルダに保存してください。

Greasemetalを起動して、URL欄に「http://www.nicovideo.jp/multi/[動画1のID]/[動画2のID]」と入力すると、指定したIDの動画を見ることができます。

例:

ソースコード

// ==UserScript==
// @name           ニコニコマルチ
// @namespace      http://d.hatena.ne.jp/syttru/
// @description    ニコニコ動画で複数の動画を並べて見るぐりもん
// @include        http://www.nicovideo.jp/multi/*
// @version        0.1
// ==/UserScript==

(function(){

try{
    
var vids = parse_query( location.href );
validate_vids( vids );
each( vids, function( vid ) { validate_vid( vid ); });

remove_all_children( document.body );
document.body.style.width = '1024px';

var buttons = createElement('div', {id:'buttons'});
document.body.appendChild( buttons );

var players = createElement('div', {id:'players'}, {width:'100%',padding:'0',margin:'0'});
document.body.appendChild( players );

var swfjs = createElement('script', {type:'text/javascript',src:'http://res.nicovideo.jp/js/swfobject.js?4'});
document.body.appendChild( swfjs );

var idx = 0;
each( vids, function( vid ) {
    var i = idx;
    setTimeout( function(){
        rendar_player( vid, i );
        appendButton( '再生' + i, function() {
            $('flvplayer' + i).ext_play(1);
        });
        appendButton( '停止' + i, function() {
            for( var i=0; i<idx; i++ ){
                $('flvplayer' + i).ext_play(0);
            }
        });
    }, idx * 5000 );
    idx++;
});

var clear = createElement('div', {}, {clear:'both'});
document.body.appendChild( clear );

appendButton( '全部再生', function() {
    var players = [];
    for( var i=0; i<idx; i++ ){
        players.push($('flvplayer' + i));
    }
    for( var i=0; i<idx; i++ ){
        players[i].ext_play(1);
    }
});
appendButton( '全部停止', function() {
    var players = [];
    for( var i=0; i<idx; i++ ){
        players.push($('flvplayer' + i));
    }
    for( var i=0; i<idx; i++ ){
        players[i].ext_play(0);
    }
});

}catch(e){
    alert(e);
}

// ボタンを作ってDOMに追加する。
function appendButton( caption, f ){
    var button = createElement('input', {type:'button',id:'play',value:caption }, {width:'80px', margin:'10px'});
    observe( button, 'click', f );
    $('buttons').appendChild( button );
}



// プレイヤーを書く
function rendar_player( vid, num ) {
    var div = createElement( 'div', {id:'flvplayer_container' + num}, {width:'512px', height:'384px', padding:'0', float: 'left', overflow:'hidden'} );
    $('players').appendChild( div );
    var so = new SWFObject("http://www.nicovideo.jp/swf/nicoplayer.swf?ts=" + ( new Date().getTime() ), "flvplayer" + num, "952", "540", 9, "#FFFFFF");
    so.addVariable("v",  vid);
    so.write("flvplayer_container" + num);
    div.scrollTop = 65;
    div.scrollLeft = 22;
}



// 子ども達を全て削除する。
function remove_all_children( element ) {
    while( element.childNodes.length > 0 ) {
        element.removeChild( element.firstChild );
    }
}



// URLから動画IDを複数取り出す
function parse_query( url ) {
    var query = url.replace(/^http\:\/\/www\.nicovideo\.jp\/multi\//, '' );
    return query.split('/');
}



// パラメータを検証する
function validate_vids( vids ) {
    if( vids.length < 2 ) {
        throw new Error();
    }
    if( vids.length > 4 ) {
        throw new Error();
    }
}

function validate_vid( vid ) {
    if( vid.match(/^[a-z]{2}[0-9]+$/) == null ) {
        throw new Error();
    }
}


// エレメント作る
function createElement( tagName, attrs, styles ) {
  var elem = document.createElement( tagName );
  attrs = attrs || {};
  styles = styles || {};
  for( var key in attrs ) {
    elem.setAttribute( key, attrs[key] );
  }
  for( var key in styles ) {
    elem.style[key] = styles[key];
  }
  return elem;
}

// ヒドン作る
function createHidden( name, value ) {
  return createElement( 'input', { type: 'hidden', name: name, value: value } );
}

// 配列の各要素に対して関数を実行する関数
function each( array, f ) {
  for( var i=0; i<array.length; i++ ) {
    f( array[i] );
  }
}

function $( id ){ return document.getElementById( id ); }
function observe(target, type, listener) {
  if   (target.addEventListener) target.addEventListener(type, listener, false);
  else target.attachEvent('on' + type, function() { listener.call(target, window.event); });
}

})();