--- get_iplayer-2.41.orig 2009-10-02 13:04:23.000000000 +0100
+++ get_iplayer-2.41 2010-02-27 17:27:26.000000000 +0000
@@ -2494,6 +2494,87 @@
+sub get_playlist_url {
+ my $ua = shift;
+ my $url = shift;
+ my $filter = shift;
+ # Don't recurse more than 5 times
+ my $depth = 5;
+
+ # Resolve the MMS url if it is an http ref
+ while ( $url =~ /^http/i && $depth ) {
+ my $content = main::request_url_retry($ua, $url, 2, '', '');
+ # Reference list
+ if ( $content =~ m{\[reference\]}i ) {
+ my @urls;
+ # [Reference]
+ # Ref1=http://wm.bbc.co.uk/wms/england/radioberkshire/aod/andrewpeach_thu.wma?MSWMExt=.asf
+ # Ref2=http://wm.bbc.co.uk/wms/england/radioberkshire/aod/andrewpeach_thu.wma?MSWMExt=.asf
+ for ( split /ref\d*=/i, $content ) {
+ #main::logger "DEBUG: LINE: $_\n" if $opt->{debug};
+ s/[\s]//g;
+ # Rename http:// to mms:// - don't really know why but this seems to be necessary with such playlists
+ s|http://|mms://|g;
+ push @urls, $_ if m{^(http|mms|rtsp)://};
+ main::logger "DEBUG: Got Reference URL: $_\n" if $opt->{debug};
+ }
+ # use first URL for now??
+ $url = $urls[0];
+
+ # ASX XML based playlist
+ } elsif ( $content =~ m{
+ # http://www.bbc.co.uk/
+ # BBC support
+ # BBC
+ # (c) British Broadcasting Corporation
+ #
+ #
+ #
+ #
+ #
+ #
+ #
+ # BBC
+ #
+ #
+ for ( split /{debug};
+ # Ignore anything except mms or http from this playlist
+ push @urls, $1 if m{ref\s+href=\"((http|$filter)://.+?)\"}i;
+ }
+ for ( @urls ) {
+ main::logger "DEBUG: Got ASX URL: $_\n" if $opt->{debug};
+ }
+ # use first URL for now??
+ $url = $urls[0];
+
+ # RAM format urls
+ } elsif ( $content =~ m{rtsp://}i ) {
+ my @urls;
+ for ( split /[\n\r\s]/i, $content ) {
+ main::logger "DEBUG: LINE: $_\n" if $opt->{debug};
+ # Ignore anything except $filter or http from this playlist
+ push @urls, $1 if m{((http|$filter)://.+?)[\n\r\s]?$}i;
+ }
+ for ( @urls ) {
+ main::logger "DEBUG: Got RAM URL: $_\n" if $opt->{debug};
+ }
+ # use first URL for now??
+ $url = $urls[0];
+
+ } else {
+ chomp( $url = $content );
+ }
+ $depth--;
+ }
+
+ return $url;
+}
+
+
+
############## OO ################
############## Options default class ################
@@ -3539,7 +3620,7 @@
my $retcode;
# Use different number of retries for flash modes
- $retries = $opt->{attempts} || 20 if $mode =~ /^flash/;
+ $retries = $opt->{attempts} || 50 if $mode =~ /^flash/;
# Retry loop
for ($count = 1; $count <= $retries; $count++) {
@@ -4772,7 +4853,7 @@
# Common attributes
# swfurl = Default iPlayer swf version
my $conn = {
- swfurl => "http://www.bbc.co.uk/emp/9player.swf?revision=10344_10753",
+ swfurl => "http://www.bbc.co.uk/emp/10player.swf?revision=15501_15796",
ext => $ext,
streamer => $streamer,
bitrate => $mattribs->{bitrate},
@@ -4823,15 +4904,15 @@
# Level3 CDN
} elsif ( $cattribs->{kind} eq 'level3' ) {
$conn->{playpath} = $cattribs->{identifier};
- $conn->{application} = "$cattribs->{application}?$cattribs->{authstring}";
+ $conn->{application} = "$cattribs->{application}?$cattribs->{authString}";
$conn->{tcurl} = "rtmp://$cattribs->{server}:1935/$conn->{application}";
$conn->{streamurl} = "rtmp://$cattribs->{server}:1935/ondemand?_fcs_vhost=$cattribs->{server}&auth=$cattribs->{authstring}&aifp=v001&slist=$cattribs->{identifier}";
# iplayertok CDN
} elsif ( $cattribs->{kind} eq 'iplayertok' ) {
$conn->{application} = $cattribs->{application};
- decode_entities($cattribs->{authstring});
- $conn->{playpath} = "$cattribs->{identifier}?$cattribs->{authstring}";
+ decode_entities($cattribs->{authString});
+ $conn->{playpath} = "$cattribs->{identifier}?$cattribs->{authString}";
$conn->{playpath} =~ s/^mp[34]://g;
$conn->{streamurl} = "rtmp://$cattribs->{server}:1935/ondemand?_fcs_vhost=$cattribs->{server}&auth=$cattribs->{authstring}&aifp=v001&slist=$cattribs->{identifier}";
$conn->{tcurl} = "rtmp://$cattribs->{server}:1935/$conn->{application}";
@@ -5035,15 +5116,26 @@
# flashaac modes
} elsif ( $mattribs->{kind} eq 'audio' &&
- $mattribs->{type} eq 'audio/mp4' &&
- $mattribs->{encoding} eq 'aac'
+ $mattribs->{type} eq 'audio/mp4'
+ # This also catches worldservice who happen not to set the encoding type
+ # && $mattribs->{encoding} eq 'aac'
) {
- get_stream_data_cdn( \%data, $mattribs, 'flashaac', 'rtmp', 'aac' );
+ # flashaachigh
+ if ( $mattribs->{bitrate} >= 192 ) {
+ get_stream_data_cdn( \%data, $mattribs, 'flashaachigh', 'rtmp', 'aac' );
+
+ # flashaacstd
+ } elsif ( $mattribs->{bitrate} >= 96 ) {
+ get_stream_data_cdn( \%data, $mattribs, 'flashaacstd', 'rtmp', 'aac' );
+
+ # flashaaclow
+ } else {
+ get_stream_data_cdn( \%data, $mattribs, 'flashaaclow', 'rtmp', 'aac' );
+ }
# flashaudio modes
} elsif ( $mattribs->{kind} eq 'audio' &&
- $mattribs->{type} eq 'audio/mpeg' &&
- $mattribs->{encoding} eq 'mp3'
+ ( $mattribs->{type} eq 'audio/mpeg' || $mattribs->{type} eq 'audio/mp3' )
) {
get_stream_data_cdn( \%data, $mattribs, 'flashaudio', 'rtmp', 'mp3' );
@@ -5082,10 +5174,16 @@
# Do iphone redirect check regardless of an xml entry for iphone (except for EMP/Live) - sometimes the iphone streams exist regardless
# Skip check if the modelist selected excludes iphone
- if ( $prog->{pid} !~ /^http/i && $verpid !~ /^\?/ && grep /^iphone/, split ',', $prog->modelist() ) {
- if ( my $streamurl = Streamer::iphone->get_url($ua, $verpid) ) {
+ if ( $prog->{pid} !~ /^http/i && $verpid !~ /^\?/ && $verpid !~ /^http:/ && grep /^iphone/, split ',', $prog->modelist() ) {
+ if ( my $streamurl = Streamer::iphone->get_url($ua, $prog->{pid}) ) {
my $mode = 'iphone1';
- # Get iphone redirect
+ if ( $prog->{type} eq 'radio' ) {
+ $data{$mode}{bitrate} = 128;
+ $data{$mode}{type} = "(iplayer_streaming_http_mp3) http mp3 128kbps stream";
+ } else {
+ $data{$mode}{bitrate} = 480;
+ $data{$mode}{type} = "(iplayer_streaming_http_mp4) http h264 480x272 480kbps stream";
+ }
$data{$mode}{streamurl} = $streamurl;
$data{$mode}{streamer} = 'iphone';
$data{$mode}{ext} = 'mov';
@@ -5745,12 +5843,12 @@
'bbc_radio_essex' => 'BBC Essex',
'bbc_london' => 'BBC London',
'bbc_radio_kent' => 'BBC Kent',
- 'bbc_southern_counties_radio' => 'BBC Southern Counties',
+ 'bbc_radio_surrey' => 'BBC Surrey',
+ 'bbc_radio_sussex' => 'BBC Sussex',
'bbc_radio_oxford' => 'BBC Oxford',
'bbc_radio_berkshire' => 'BBC Berkshire',
'bbc_radio_solent' => 'BBC Solent',
'bbc_radio_gloucestershire' => 'BBC Gloucestershire',
- 'bbc_radio_swindon' => 'BBC Swindon',
'bbc_radio_wiltshire' => 'BBC Wiltshire',
'bbc_radio_bristol' => 'BBC Bristol',
'bbc_radio_somerset_sound' => 'BBC Somerset',
@@ -5767,7 +5865,7 @@
# Class cmdline Options
sub opt_format {
return {
- radiomode => [ 1, "radiomode|amode=s", 'Recording', '--radiomode ,,...', "Radio Recording mode(s): iphone,flashaac,flashaudio,realaudio,wma (default: iphone,flashaac,flashaudio,realaudio)"],
+ radiomode => [ 1, "radiomode|amode=s", 'Recording', '--radiomode ,,...', "Radio Recording mode(s): iphone,flashaac,flashaachigh,flashaacstd,flashaaclow,flashaudio,realaudio,wma (default: iphone,flashaachigh,flashaacstd,flashaudio,realaudio,flashaaclow)"],
bandwidth => [ 1, "bandwidth=n", 'Recording', '--bandwidth', "In radio realaudio mode specify the link bandwidth in bps for rtsp streaming (default 512000)"],
lame => [ 0, "lame=s", 'External Program', '--lame ', "Location of lame binary"],
outputradio => [ 1, "outputradio=s", 'Output', '--outputradio ', "Output directory for radio recordings"],
@@ -5816,16 +5914,18 @@
main::logger "WARNING: Not using flash modes since flvstreamer/rtmpdump is not found\n" if $opt->{verbose};
$mlist = 'iphone,realaudio,wma';
} else {
- $mlist = 'iphone,flashaudio,flashaac,realaudio,wma';
+ $mlist = 'iphone,flashaachigh,flashaacstd,flashaudio,realaudio,flashaaclow,wma';
}
}
# Deal with BBC Radio fallback modes and expansions
# Valid modes are iphone,rtmp,flashaac,flashaudio,realaudio,wmv
# 'rtmp' or 'flash' => 'flashaudio,flashaac'
- # flashaac => flashaac1,flashaac2
- $mlist = main::expand_list($mlist, 'best', 'flashaac,iphone,flashaudio,realaudio,wma');
+ # flashaac => flashaachigh,flashaacstd,flashaaclow
+ # flashaachigh => flashaachigh1,flashaachigh2
+ $mlist = main::expand_list($mlist, 'best', 'flashaachigh,flashaacstd,iphone,flashaudio,realaudio,flashaaclow,wma');
$mlist = main::expand_list($mlist, 'flash', 'flashaudio,flashaac');
$mlist = main::expand_list($mlist, 'rtmp', 'flashaudio,flashaac');
+ $mlist = main::expand_list($mlist, 'flashaac', 'flashaachigh,flashaacstd,flashaaclow');
return $mlist;
}
@@ -6134,6 +6234,7 @@
'bbc_radio_cambridge' => 'BBC Cambridgeshire',
'bbc_radio_norfolk' => 'BBC Norfolk',
'bbc_radio_suffolk' => 'BBC Suffolk',
+ 'bbc_radio_sussex' => 'BBC Sussex',
'bbc_radio_essex' => 'BBC Essex',
'bbc_london' => 'BBC London',
'bbc_radio_kent' => 'BBC Kent',
@@ -6191,15 +6292,18 @@
main::logger "WARNING: Not using flash modes since flvstreamer/rtmpdump is not found\n" if $opt->{verbose};
$mlist = 'realaudio,wma';
} else {
- $mlist = 'flashaac,realaudio,wma';
+ $mlist = 'flashaachigh,flashaacstd,realaudio,flashaaclow,wma';
}
}
# Deal with BBC Radio fallback modes and expansions
- # Valid modes are iphone,rtmp,flashaac,flashaudio,realaudio,wmv
- # 'rtmp' or 'flash' => 'flashaudio,flashaac'
- $mlist = main::expand_list($mlist, 'best', 'flashaac,realaudio,wma');
+ # Valid modes are rtmp,flashaac,realaudio,wmv
+ # 'rtmp' or 'flash' => 'flashaac'
+ # flashaac => flashaachigh,flashaacstd,flashaaclow
+ # flashaachigh => flashaachigh1,flashaachigh2
+ $mlist = main::expand_list($mlist, 'best', 'flashaachigh,flashaacstd,realaudio,flashaaclow,wma');
$mlist = main::expand_list($mlist, 'flash', 'flashaac');
$mlist = main::expand_list($mlist, 'rtmp', 'flashaac');
+ $mlist = main::expand_list($mlist, 'flashaac', 'flashaachigh,flashaacstd,flashaaclow');
return $mlist;
}
@@ -6287,46 +6391,39 @@
my $ua = shift;
my $pid = shift;
- # Create url with appended 12 digit random number /mediaselector/3/auth/iplayer_streaming_http_mp4/b0067vmx?r=101477348958
- # http://www.bbc.co.uk/mediaselector/3/auth/iplayer_streaming_http_mp4
- my $iphone_download_prefix = 'http://www.bbc.co.uk/mediaselector/3/auth/iplayer_streaming_http_mp4';
- my $url_1 = ${iphone_download_prefix}.'/'.${pid}.'?r='.(sprintf "%012.0f", 999999999999*rand(0) );
- main::logger "INFO: iphone stream URL = $url_1\n" if $opt->{verbose};
-
- # This doesn't work through url-prepend proxies
- ## Use url prepend if required
- #if ( $opt->{proxy} =~ /^prepend:/ ) {
- # $url_1 = $opt->{proxy}.$url_1;
- # $url_1 =~ s/^prepend://g;
- #}
-
- # Stage 2: e.g. "Location: http://download.iplayer.bbc.co.uk/iplayer_streaming_http_mp4/121285241910131406.mp4?token=iVXexp1yQt4jalB2Hkl%2BMqI25nz2WKiSsqD7LzRmowrwXGe%2Bq94k8KPsm7pI8kDkLslodvHySUyU%0ApM76%2BxEGtoQTF20ZdFjuqo1%2B3b7Qmb2StOGniozptrHEVQl%2FYebFKVNINg%3D%3D%0A"
- #main::logger "\rGetting iplayer iphone URL " if (! $opt->{verbose}) && ! $opt->{streaminfo};
+ # Look for href="http://download.iplayer.bbc.co.uk/iplayer_streaming_http_mp4/5439950172312621205.mp4?token=iVX.lots.of.text.x9Z%2F2GNBdQKl0%3D%0A&pid=b00qhs36"
+ my $url;
+ my $iphone_download_prefix = 'http://www.bbc.co.uk/mobile/iplayer/episode';
+ my $url_0 = ${iphone_download_prefix}.'/'.${pid};
+ main::logger "INFO: iphone stream URL = $url_0\n" if $opt->{verbose};
+ my $safari_ua = main::create_ua( 'safari' );
+ my $html = main::request_url_retry( $safari_ua, $url_0, 3, undef, undef, 1 );
+ $html =~ s/\n/ /g;
+ # Check for guidance warning
+ my $guidance_post;
+ $guidance_post = $1 if $html =~ m{(isOver\d+)};
+ if ( $guidance_post ) {
my $h = new HTTP::Headers(
'User-Agent' => $user_agent{coremedia},
'Accept' => '*/*',
- 'Range' => 'bytes=0-1',
+ 'Accept-Language' => 'en',
+ 'Connection' => 'keep-alive',
+ 'Pragma' => 'no-cache',
);
- my $req = HTTP::Request->new ('GET', $url_1, $h);
- # send request (use simple_request here because that will not allow redirects)
- my $res = $ua->simple_request($req);
- # Get resulting Location header (i.e. redirect URL)
- my $url = $res->header("location");
- if ( ! $res->is_redirect ) {
- main::logger "ERROR: Failed to get iphone redirect from iplayer site\n\n";
- return '';
- }
- # Extract redirection Location URL
- $url =~ s/^Location: (.*)$/$1/g;
- # If we get a Redirection containing statuscode=404 then this prog is not yet ready
- if ( $url =~ /statuscode=404/ ) {
- main::logger "\rERROR: iphone stream is not yet ready\n" if $opt->{verbose};
- return '';
- } elsif ( $url =~ /statuscode=403/ ) {
- main::logger "\rERROR: iphone stream is not permitted for recording\n" if $opt->{verbose};
- return '';
+ main::logger "INFO: Guidance '$guidance_post' Warning Detected\n" if $opt->{verbose};
+ # Now post this var and get html again
+ my $req = HTTP::Request->new('POST', $url_0, $h);
+ $req->content_type('application/x-www-form-urlencoded');
+ $req->content('form=guidanceprompt&'.$guidance_post.'=1');
+ my $res = $ua->request($req);
+ $html = $res->as_string;
}
+ $url = decode_entities($1) if $html =~ m{href="(http.//download\.iplayer\.bbc\.co\.uk/iplayer_streaming_http_mp4.+?)"};
+ main::logger "DEBUG: Got iphone mediaselector URL: $url\n" if $opt->{verbose};
+ if ( ! $url ) {
+ main::logger "ERROR: Failed to get iphone URL from iplayer site\n\n";
+ }
return $url;
}
@@ -7262,24 +7359,8 @@
my $file_part_prefix = "$prog->{dir}/$prog->{fileprefix}_part";
for ( my $count = 0; $count <= $#url_list; $count++ ) {
- # Resolve the MMS url if it is an http ref
- if ( $url_list[$count] =~ /^http/ ) {
- my $url = main::request_url_retry($ua, $url_list[$count], 2, '', '');
- chomp($url);
- $url =~ s/[\s\n]//g;
- # HREF="mms://a1899.v394403.c39440.g.vm.akamaistream.net/7/1899/39440/1/bbcworldservice.download.akamai.com/39440//worldservice/css/nb/410060838.wma"
- # HREF = "http://www.bbc.co.uk/worldservice/meta/tx/nb/live/www15.asx"
- $url =~ s/^.*href\s*=\s*\"(.+?)\".*$/$1/gi;
- # Yet another recursion if required!
- if ( $url =~ /^http/ ) {
- # "http://www.bbc.co.uk/worldservice/meta/tx/nb/live/www15.asx"
- $url = main::request_url_retry($ua, $url, 2, '', '');
- chomp($url);
- $url =~ s/[\s\n]//g;
- $url =~ s/^.*href\s*=\s*\"(.+?)\".*$/$1/gi;
- }
- $url_list[$count] = $url;
- }
+ # Parse/recurse playlist if required to get mms url
+ $url_list[$count] = main::get_playlist_url( $ua, $url_list[$count], 'mms' );
# Create temp recording filename
$file_tmp = sprintf( "%s%02d.".$prog->{ext}, $file_part_prefix, $count+1);