ActionScript3.0でユーザーニコ割をダウンロードするよ!

ユーザーニコ割

ニコニコ動画の上の広告部分に表示される、ユーザーニコ割。あれ、運営に割り込まれるとイラっとしますけど、動画を投稿した人(=ユーザー)が割り込ませるニコ割は、作品の一部として我々をニコニコさせてくれます。

そんなニコ割をダウンロードする方法。まあNNDDでは以前から実装していたのですが、久々にソースコードなブログを書きたくなったので書きます。

ニコ割をダウンロードするために必要なもの
  • ニコ割が再生される動画のURL
  • ニコ割のビデオID(nm****っていうやつ)
    • このビデオIDは投稿者コメントを見ると分かります。「@CM」命令の後のnm****がニコ割のビデオIDです。
  • (もちろんのことですが、)ニコ動のアカウント
ニコ割をダウンロードする手順
  • ニコ動にログイン
  • ニコ割が再生される動画にアクセス(見てるフリ処理)
  • 動画へのアクセスを維持したまま、ニコ動のAPI(http://www.nicovideo.jp/api/getflv?v=nm****)にアクセス
  • APIから得られたデータの"&url="にあるURLを探す
  • 探したURLにアクセス

これでダウンロードできますよ。

上の流れをまとめて言いますと、ニコ動から普通にビデオをダウンロードする流れの、APIアクセスに使うビデオIDをユーザーニコ割SWFのビデオIDにかえればいいだけなのです。
ね?簡単でしょ?


その他、APIから得られた値の形式とかつきましては以下もご参照くださいませ。
Adobe AIRでニコニコ動画にアクセスして、FLVをダウンロードしてみる- MineAPの(開発)日記
ActionScript3.0でニコニコ動画からコメントをダウンロードする。- MineAPの(開発)日記
ニコニコ動画の投稿者コメント取得に関する覚え書き - MineAPの(開発)日記
激しく自分のエントリの宣伝だw


以下、NNDDのソースコード(Access2Nico.as)から引用。全体の流れを見たい方はソースコードダウンロードしてみてね。

/**
 * 見てるフリ処理を実施する。<br>
 * デフォルトではムービーを取りにいきます。
 * @param mUrl "見てるフリ"をする対象のムービーのURL
 * @return "見てるフリ"をしているURLLoader。
 * 
 */
private function watchVideo(mUrl:String, type:int = VIDEO_DOWNLOAD):URLLoader
{
	
	this.videoID = mUrl.substring(mUrl.lastIndexOf("/")+1);
	
	//trace("videoID:"+this.videoID);
		
	var loader:URLLoader = new URLLoader();	
	
	//そのページを見ているフリをする為のリクエストを準備する。
	var watchURL:URLRequest = new URLRequest(mUrl);
	watchURL.method = "GET";
			
	loader = new URLLoader();
	if(type == VIDEO_DOWNLOAD){
		loader.addEventListener(Event.COMPLETE, accessWatchSuccessForVideo);
	}else if(type == COMMENT_DOWNLOAD){
		loader.addEventListener(Event.COMPLETE, accessWatchSuccessForComment);
	}else if(type == NICOWARI_DOWNLOAD){
		/* 今回はニコ割をダウンロードしたいのでaccessWatchSuccessForNicowari()へ! */
		loader.addEventListener(Event.COMPLETE, accessWatchSuccessForNicowari);
	}
	
	loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
	loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);            
	
	//HTTPリクエストを実行。
	loader.load(watchURL);
	
	return loader;
}

/**
 * ニコ割用
 * 見てるフリ処理が終わったら呼ばれる。 
 * @param evt
 * 
 */
private function accessWatchSuccessForNicowari(evt:Event):void
{
	trace("アクセス成功" + evt);
	videoTitle = this.getVideoName(watchLoader, false);
	videoTitle = videoTitle + "[Nicowari]["+ nicowariID +"]";
	trace(videoTitle);
	
	//指定されたアドレスのニコ割を取得する処理を実行
	downLoader = this.getAPIResult(nicowariID, NICOWARI_DOWNLOAD);
}

/**
 * FLVのURLを取得する為のAPIへのアクセスを行う
 * @param videoID 英数字2文字+数字 で表されるビデオのID
 * @param type ダウンロード対象がVideoか、Commentか。
 * @return APIへのリクエストを行うURLLoader
 * 
 */
private function getAPIResult(videoID:String, type:int = VIDEO_DOWNLOAD):URLLoader
{
	var loader:URLLoader = new URLLoader();
			
	//FLVのURLを取得する為にニコニコ動画のAPIにアクセスする
	var getAPIResult:URLRequest;
	getAPIResult = new URLRequest("http://www.nicovideo.jp/api/getflv?v=" + videoID);
	getAPIResult.method = "GET";
	
	if(type == VIDEO_DOWNLOAD){
		loader.addEventListener(Event.COMPLETE, accessAPISuccessForVideo);
	}else if(type == COMMENT_DOWNLOAD){
		loader.addEventListener(Event.COMPLETE, accessAPISuccessForComment);
	}else if(type == NICOWARI_DOWNLOAD){
		/* APIにアクセスします。今回はニコ割の流れなのでaccessAPISuccessForNicowariへ! */
		loader.addEventListener(Event.COMPLETE, accessAPISuccessForNicowari);
	}
	loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
	loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);   
	
	loader.load(getAPIResult);
	return loader;
}

/**
 * ニコ割用
 * APIアクセスが成功したら呼ばれる
 * @param evt
 *
 */
private function accessAPISuccessForNicowari(evt:Event):void{
	trace("アドレスの取得に成功" + evt);
	videoLoader = this.getVideo(downLoader);
}

/**
 * APIから得られたデータを元に動画をダウンロードする
 * @param getApiResultLoader アクセスさせたいURLLoader
 * @return アクセスさせたURLLoader
 * 
 */
private function getVideo(getApiResultLoader:URLLoader):URLLoader
{
	var loader:URLLoader = new URLLoader();
	//APIから得られたデータの"&url="にあるURLを探す
	var videoURL:String = new String();
	//trace(getApiResultLoader.data);
	videoURL = getApiResultLoader.data.substring(getApiResultLoader.data.indexOf("&url=")+5, 
			getApiResultLoader.data.indexOf("&", getApiResultLoader.data.indexOf("&url")+1));
	videoURL = unescape(videoURL);
	
	trace(unescape(getApiResultLoader.data));
	
	if(videoURL.indexOf("smile?m=")!=-1){
		videoType = ".mp4";
	}else if(videoURL.indexOf("smile?v=")!=-1){
		videoType = ".flv";
	}else if(videoURL.indexOf("smile?s=")!=-1){
		/* ニコ割なのでこれ! */
		videoType = ".swf";
	}
	
	trace(videoURL);
	
	if(this.isStreamingPlay){
		/*ストリーミング再生。今回は関係ないので省略。*/
	}else{
		//探したURLを使ってFLVのダウンロードを行う。
		var getVideo:URLRequest = new URLRequest(videoURL)
		loader.dataFormat=URLLoaderDataFormat.BINARY;
		loader.addEventListener(Event.COMPLETE, videoLoadSuccess);
		loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
		loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
		loader.load(getVideo);
	}
	
	return loader;
}

/**
 * ビデオのダウンロードが完了したら呼ばれる
 * @param evt
 * 
 */
private function videoLoadSuccess(evt:Event):void
{
	/*保存処理。getVideo()の戻り値のloader.dataを保存すればいい。*/
}


別に、クリスマス的な話とかそういうものは何も無い。