BBC iPlayer video download

This script allows to save videos from BBC iPlayer.

目前為 2015-02-22 提交的版本,檢視 最新版本

// ==UserScript==
// @name        BBC iPlayer video download
// @namespace   http://andrealazzarotto.com/
// @include     http://www.bbc.co.uk/iplayer/episode/*
// @version     1.0.1
// @description This script allows to save videos from BBC iPlayer.
// @copyright   2015+, Andrea Lazzarotto - GPLv3 License
// @require     http://code.jquery.com/jquery-latest.min.js
// @grant       GM_xmlhttpRequest
// @license     GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// ==/UserScript==

get_title = function() {
	var title = $('meta[property="og:title"]').attr('content') || 'output';
	return title.replace(/\W+/g, '_');
}

appendURL = function(element, url) {
	element.after('<div id="direct-link"></div>');
	$('#direct-link').css({
		'padding': '.75em',
		'margin': '25px auto',
		'width': $('#player-outer-outer').width(),
		'border': '1px solid #444',
		'color': 'white',
		'font-family': 'sans-serif',
		'box-sizing': 'border-box'
	}).append('<p>To record the video, use <code>avconv</code> with the following command line:</p>' + 
			  '<pre>avconv -i "' + url + '" -codec copy -qscale 0 ' + get_title() + '.mp4</pre>' +
			  '<p>Alternatively, you may also try to record the M3U8 stream URL with VLC.</p>');
	$('#direct-link pre, #direct-link code').css({
		'white-space': 'normal',
		'word-break': 'break-word',
		'font-size': '1.15em',
		'margin': '.75em 0',
		'padding': '.75em',
		'background-color': '#444'
	});
	$('#direct-link code').css('padding','.25em');
}

get_biggest = function(dict) {
	var s = 0;
	var o = null;
	for(var key in dict) {
		key = parseInt(key) || 0;
		if (key > s) {
			s = key;
			o = dict[key];
		}
	}
	return {'size': s, 'object': o};
}

$(document).ready(function(){
	var button = $('button[data-download-sd^="bbc-ipd:download/"]');
	var spid = $('script:contains("mediator.bind")').html();
	var vpid = spid.split('vpid')[1].split('"')[2];
	var config_url = 'http://www.bbc.co.uk/iplayer/config/windows-phone';
	// figure out the mediaselector URL
	$.getJSON(config_url, function(data) {
		var selector_mobile = data['mediaselector'].replace('{vpid}', vpid);
		var selector_pc = selector_mobile.replace(/mobile-.*vpid/, 'pc/vpid');
		
		// get mobile data
		GM_xmlhttpRequest({
			method: 'GET',
			url: selector_mobile,
			onload: function(responseDetails) {
				var r = responseDetails.responseText;
				var doc = $.parseXML(r);
				var $xml = $(doc);
				
				var media = {};
				$xml.find('media[kind^="video"]').each(function() {
					var bitrate = $(this).attr('bitrate');
					var href = $(this).find('connection').attr('href');
					media[bitrate] = href;
				});
				var m3u8_url = get_biggest(media);
				
				// get desktop data for higher quality
				GM_xmlhttpRequest({
					method: 'GET',
					url: selector_pc,
					onload: function(responseDetails) {
						var r = responseDetails.responseText;
						var doc = $.parseXML(r);
						var $xml = $(doc);
						
						var media = {};
						$xml.find('media[kind^="video"]').each(function() {
							var bitrate = $(this).attr('bitrate');
							var identifier = $(this).find('connection[application="ondemand"]').attr('identifier');
							if(identifier)
								media[bitrate] = identifier;
						});
						var high_quality = get_biggest(media);
						
						// compose the M3U8 stream URL
						GM_xmlhttpRequest({
							method: 'GET',
							url: m3u8_url['object'],
							onload: function(responseDetails) {
								var r = responseDetails.responseText;
								
								var urls = r.split('\n').slice(1);
								var final_url = urls[1];
								
								// fix the final url
								var old_pieces = final_url.split(',');
								var pieces = [old_pieces[0], old_pieces[1], old_pieces[old_pieces.length-1]];
								var p = 1;
								var high_quality_piece = high_quality['object'].replace('.mp4','').split('/').slice(1).join('/');
								var new_p = pieces[p].split('/').slice(0,2).join('/') + '/' + high_quality_piece;
								pieces[p] = new_p;
								final_url = pieces.join(',');
								
								// output the M3U8 URL
								appendURL($('#player-outer-outer'), final_url);
							}
						});
					}
				});
			}
		});
	}); // getJSON
}); // $(document).ready.ready