| # 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; |