Hatena::ブログ(Diary)

サバニFRP

2007-01-10

[]Youtube FLV ダウンロード for userChrome.js

  • 修正 2007/09/17 : コンテキストメニューが表示されなかったのを修正
  • 修正 2007/06/23 : コンテキストメニューが表示されなかったのを修正
  • 修正 2007/06/23 : Youtube の仕様変更に対応した。

Youtube の FLV ファイルをダウンロードする userChrome.js スクリプトを作った。

使い方は、Youtube を開いて、タイトル部分を右クリック。「Download FLV」を選択したらダウンロードが始まります。

f:id:fls:20070110183945p:image

f:id:fls:20070110183955p:image

ページ上のプレイヤが読み込み中のときは、読み込みが終了した時点でキャッシュからダウンロードします。

youtubeDownloader.uc.js

function ucjsYoutubeFlvDownloader(){
	this.SKIP_SELECT_PROMPT = true;
}

ucjsYoutubeFlvDownloader.prototype = {
	download: function(aTitle, aVideoID){
		this._title = aTitle;

		this._state = 0;

		this._ioService = Components.classes["@mozilla.org/network/io-service;1"]
				.getService(Components.interfaces.nsIIOService);
		this.wrappedJSObject = this;

		var youtubeURLSpec = "http://www.youtube.com/watch_video?v=" + aVideoID;
		var youtubeURL = this._ioService.newURI(youtubeURLSpec, null, null);
		var httpChannel = this._ioService.newChannelFromURI(youtubeURL)
				.QueryInterface(Components.interfaces.nsIHttpChannel);
		httpChannel.requestMethod = "HEAD";
		httpChannel.redirectionLimit = 0;
		httpChannel.asyncOpen(this.getListener(), this);
	},

	onStopRequest: function(aRequest, aContext, aStatus){
		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
		if(aRequest.responseStatus != 303){
			alert("ERROR: ucjsYoutubeFlvDownloader");
			return;
		}

		if(this._state == 0){
			var location = aRequest.getResponseHeader("Location");
			this._state = 1;

			var queryHash = this.getQueryHash(location);
			location = "http://youtube.com/get_video?video_id=" + queryHash["video_id"] + "&t=" + queryHash["t"];
			var youtubeURL = this._ioService.newURI(location, null, null);
			var httpChannel = this._ioService.newChannelFromURI(youtubeURL)
					.QueryInterface(Components.interfaces.nsIHttpChannel);
			httpChannel.requestMethod = "HEAD";
			httpChannel.redirectionLimit = 0;
			httpChannel.asyncOpen(this.getListener(), this);
		}else if(this._state == 1){
			this._state = 2;
			var location = aRequest.getResponseHeader("Location");
			this.saveFLV(this._title, location);
		}
	},

	getQueryHash: function(aURLSpec){
		aURLSpec.match(/\?/);
		aURLSpec = RegExp.rightContext;
		var queryHash = new Array();
		var queryArray = aURLSpec.split("&");
		for(var i=0; i<queryArray.length; i++){
			var query = queryArray[i].split("=");
			if(query.length == 2) queryHash[query[0]] = query[1];
		}
		return queryHash;
	},

	getListener: function(){
		var listener = {
			onStartRequest: function(){},
			onDataAvailable: function (){},
			onStopRequest: function(aRequest, aContext, aStatus){
				aContext.wrappedJSObject.onStopRequest(aRequest, aContext, aStatus);
			}
		}
		return listener;
	},

	saveFLV: function(aTitle, aFlvURLSpec){
		const FLV_EXTENSION = "flv";
		var FLV_CONTENT_TYPE = "video/flv";

		var flvName = aTitle + "." + FLV_EXTENSION;
		var flvURL = this._ioService.newURI(aFlvURLSpec, null, null)
				.QueryInterface(Components.interfaces.nsIURL);
		var fileInfo = new FileInfo(flvName, flvName, aTitle, FLV_EXTENSION, flvURL);

	    var fpParams = {
			fpTitleKey: "",
			isDocument: false,
			fileInfo: fileInfo,
			contentType: FLV_CONTENT_TYPE,
			saveMode: GetSaveModeForContentType(FLV_CONTENT_TYPE),
			saveAsType: 0,
			file: null,
			fileURL: null
		};
		if(!getTargetFile(fpParams, this.SKIP_SELECT_PROMPT)){
			return;
		}

		var fileURL = fpParams.fileURL || makeFileURI(fpParams.file);

		var persist = makeWebBrowserPersist();
		persist.persistFlags = Components.interfaces.nsIWebBrowserPersist
									.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
		var transfer = Components.classes["@mozilla.org/transfer;1"]
						.createInstance(Components.interfaces.nsITransfer);
		transfer.init(fileInfo.uri, fileURL, "", null, null, null, persist);
		persist.progressListener = transfer;
	    persist.saveURI(fileInfo.uri, null, null, null, null, fileURL);
	}
};

var ucjsYoutubeFlvDownloaderContextMenu = {
	init: function(){
		var contentAreaContextMenu = document.getElementById("contentAreaContextMenu");

		this._menuItem  = document.createElement("menuitem");
		this._menuItem.setAttribute("label", "Download Flv");
		contentAreaContextMenu.appendChild(this._menuItem);

		contentAreaContextMenu.addEventListener("popupshowing",
			function(){ ucjsYoutubeFlvDownloaderContextMenu.onPopupShowing(this); }, false);
	},

	onPopupShowing: function(aPopup){
		this._menuItem.hidden = true;

		if(gContextMenu.target.id != "vidTitle") return;
		var location = gContextMenu.target.ownerDocument.location;
		if(location.host.indexOf("youtube.com") == -1) return;
		var search = gContextMenu.target.ownerDocument.location.search;
		if(!search.match("v=([^&]+)")) return;
		var videoID = RegExp.$1;
		var videoTitle = gContextMenu.target.textContent;
		this._menuItem.setAttribute("oncommand", "ucjsYoutubeFlvDownloaderContextMenu.download('"+ videoTitle +"','"+ videoID +"')");
		this._menuItem.hidden = false;
	},

	download: function(aTitle, aVideoID){
		var d = new ucjsYoutubeFlvDownloader();
		d.download(aTitle, aVideoID);
	}
};

ucjsYoutubeFlvDownloaderContextMenu.init();

ARIANAARIANA 2007/11/04 16:32 Diamond in the rough<a href= http://info.iifree.net/vaigra-on-line/site_map.html >best price vaigra</a> <a href= http://info.iifree.net/vaigra/site_map.html >canada vaigra</a> <a href= http://info.iifree.net/vigra-uk/site_map.html >erection vigra</a> <a href= http://info.iifree.net/cheap-online-vigra/site_map.html >purchase vigra online</a> <a href= http://info.iifree.net/buy-vigra/site_map.html >buy cheap generic vigra</a>