aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2013-06-08 19:28:05 -0700
committerJames Bottomley <JBottomley@Parallels.com>2013-06-08 19:28:05 -0700
commitaa603a460f9cb26d5c6cd784b0fecd1ec57060e5 (patch)
tree6b36d0e06536288d14ddb99598812fd3eabfb130
parentd145c2c471afc7817e5750e176f75d80a92142d9 (diff)
downloadget-flash-videos-aa603a460f9cb26d5c6cd784b0fecd1ec57060e5.tar.gz
Syfy: Add preliminary support
This adds support for the Syfy site and its allied sites like defiance. It works with video hosted on syfy.com (full episodes and clips) and with video on defiance.com. It looks like there are quite a few other syfy related sites, so the site list could be expanded somewhat. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--lib/FlashVideo/Site/Syfy.pm142
1 files changed, 142 insertions, 0 deletions
diff --git a/lib/FlashVideo/Site/Syfy.pm b/lib/FlashVideo/Site/Syfy.pm
new file mode 100644
index 0000000..71ba6bf
--- /dev/null
+++ b/lib/FlashVideo/Site/Syfy.pm
@@ -0,0 +1,142 @@
+# Part of get-flash-videos. See get_flash_videos for copyright.
+package FlashVideo::Site::Syfy;
+use strict;
+use FlashVideo::Utils;
+use FlashVideo::JSON;
+
+sub make_guid {
+ my($self, $len) = @_;
+
+ my @chars = ('A' .. 'Z');
+ return join "", map { $chars[rand @chars] } 1 .. $len;
+}
+
+sub find_video {
+ my ($self, $browser, $embed_url, $prefs) = @_;
+
+ ##
+ # For the Syfy website, the video player is embedded in an iframe
+ # the current player is from player.theplatform.com
+ #
+ # Note too that there are several other iframes in the page, mostly
+ # for adverts. Currently the player iframe is first but if the regexp
+ # below stops working, likely theres an advert iframe above it
+ ##
+
+ my $url;
+ if ($browser->content =~ /<iframe\n\s*class=.*\n\s*src="([^"]*)"/) {
+ $browser->get($1);
+ if (!$browser->success) {
+ die "Couldn't download iframe $url: " . $browser->response->status_line;
+ }
+ if ($browser->content =~ /tp:releaseUrl="([^"]*)"/) {
+ $url = $1;
+ } else {
+ die "Couln't find SMIL url in " . $browser->uri->as_string;
+ }
+ $url .= 'feed=All%20Videos&defaultm3ubitrate=1000&manifest=f4m&format=SMIL&Tracking=true&Embedded=true';
+ } elsif ($browser->uri->as_string =~ m,(http://[^/]*)/.*vid:(\d+),) {
+ my ($host,$vid) = ($1, $2);
+ ##
+ # This is a lot of heuristics, so if anything goes wrong it's
+ # probably in here
+ ##
+ # First heuristic, the nbcParams.js file exists and gives the
+ # base URLs for most of the downloads
+ ##
+ $browser->get($host.'/_utils/video/codebase/js/nbcParams.js');
+ info $browser->uri;
+ die "Looks like nbcParams heuristic no longer works" if (!$browser->success);
+ my ($json) = from_json($browser->content);
+ $host =~ m,https?://www\.([^\.]*).com,;
+ $host = $1;
+ my $feedurl;
+ foreach (@{$json->{channels}}) {
+ info "found name ".$_->{name};
+ if ($_->{name} eq $host) {
+ $feedurl = $_->{feed}->{url};
+ last;
+ }
+ }
+ die "Couldn't find feed URL for $host" if (!defined($feedurl));
+ ##
+ # another nasty hairy heuristic
+ ##
+ $feedurl .= '?&form=json&fields=guid,title,description,:subtitle,content,thumbnails,categories,:fullEpisode,:disallowSharing%20&fileFields=url,duration,width,height,contentType,fileSize,format,isDefault&byGuid='.$vid;
+ $browser->get($feedurl);
+ die "Feed URL heuristic failed" if (!$browser->success);
+
+ $json = from_json($browser->content);
+ ##
+ # the reason for this bizzarre sequence is that the json seems
+ # to contain a set of media descriptors and resolutions, but
+ # the link file urls are all for the same f4m manifest, so
+ # just pull out the firs one
+ ##
+ $url = $json->{entries}->[0]->{'media$content'}->[0]->{'plfile$url'};
+ die "Failed to parse feedurl json" if (!$url);
+ $url .= '&manifest=f4m&format=SMIL&Tracking=true&Embedded=true';
+ } else {
+ die "Couln't recognise Syfy video in " . $browser->uri->as_string;
+ }
+
+ ##
+ # OK, now we have the url, try to find the F4V manifest. First we
+ # need the SMIL data
+ ##
+
+ $browser->get($url);
+ if (!$browser->success) {
+ die "Couldn't download SMIL $url: " . $browser->response->status_line;
+ }
+
+ ##
+ # SMIL is really just XML with a certain schema
+ ##
+ my $xml = from_xml($browser->content);
+
+ my $seq = $xml->{body}->{seq};
+
+ my $par = $seq;
+
+ $par = $seq->{par} if (defined($seq->{par}));
+
+ my $vid;
+
+ if (ref $par eq 'HASH') {
+ $vid = $par->{video};
+ } else {
+ foreach (@{$par}) {
+ if (defined($_->{video})) {
+ $vid = $_->{video};
+ last;
+ }
+ }
+ }
+
+ die "Failed to find video tag in ".$url if (!defined($vid));
+
+
+
+ ##
+ # now we have to slap on a 12 letter GUID and the version of hdcore
+ ##
+ my $auth = 'g='.$self->make_guid(12);
+ $url = $vid->{src}.'?'.$auth."&hdcore=3.0.3";
+ my $title = $vid->{title};
+
+ return {
+ downloader => 'f4m',
+ manifest => $url,
+ flv => title_to_filename($title),
+ };
+}
+
+sub can_handle {
+ my($self, $browser, $url) = @_;
+
+ return $url =~ m,http://www\.defiance\.com/,i
+ || $url =~ m,http://www\.syfy\.com/,i;
+}
+
+1;