+ my $id;
+ my $res;
+
+ $url =~ m|$pattern|;
+ $url = $1;
+ $id = $2;
+
+ $self->debug("Matched id %s from pattern %s", $id, $pattern);
+
+ $res = $self->_parse_by_video_info($url, $id);
+ if (defined($res)) {
+ if (ref($res)) {
+ return $res;
+ } else {
+ $self->debug("_parse_by_video_info failed with status noretry");
+ return undef;
+ }
+ } else {
+ $self->debug("_parse_by_video_info failed with status retry");
+ $res = $self->_parse_by_scrape($url, $id);
+ }
+
+ return $res;
+}
+
+#
+# Try to get video information by using the API call.
+#
+# Returns hashref on success
+# Returns undef on retryable error (try to scrape the website)
+# Returns 0 on non-retryable error
+#
+sub _parse_by_video_info {
+ my $self = shift;
+ my $url = shift;
+ my $id = shift;
+ my $quality = $self->_getval('QUALITY');
+ my $metadata;
+ my $videourl;
+ my $ua = $self->ua();
+ my $preflist;
+ my $r;
+ my $content;
+ my $urls;
+
+ $metadata->{'URL'} = $url;
+ $metadata->{'ID'} = $id;
+ $metadata->{'TYPE'} = 'video';
+ $metadata->{'SOURCE'} = $self->{'NAME'};
+ $metadata->{'TITLE'} = undef;
+ $metadata->{'DLURL'} = undef;
+
+ $preflist = $preflist{$quality};
+ $self->debug("Quality: %s, preflist: [%s]", $quality, join(", ", @{$preflist}));
+
+ $videourl = sprintf('%s://www.youtube.com/get_video_info?video_id=%s&eurl=%s',
+ $self->_getval('HTTPS')?'https':'http', $id, 'http%3A%2F%2Fwww%2Eyoutube%2Ecom%2F');
+ $self->debug("Video info URL: %s", $videourl);
+
+ $r = $ua->get($videourl);
+ unless($r->is_success()) {
+ $self->debug('Could not download %s: %s', $videourl, $r->code());
+ return undef;
+ }
+
+ $content = $r->content();
+ $self->debug('Content from get_video_info: %s', $content);
+
+ # Decode content
+ $content = $self->decode_querystring($content);
+
+ $self->debug("Decoded get_video_info: %s", Dumper($content));
+
+ if ($content->{'status'} ne 'ok') {
+ $self->debug("Non OK status code found: %s", $content->{'status'});
+ return undef;
+ }
+
+ # Check if this is live content
+ if (exists($content->{ps}) and ($content->{ps} eq 'live')) {
+ $self->error("Video URL seems to point to a live stream, cannot save this");
+ return 0;
+ }
+
+ if (exists($content->{'fmt_url_map'})) {
+ # Decode fmt_url_map
+ $urls = $self->decode_hexurl($content->{'fmt_url_map'});
+ $urls = { split /[\|,]/, $urls };
+ } elsif (exists($content->{'url_encoded_fmt_stream_map'})) {
+ $urls = $self->_decode_url_encoded_fmt_stream_map($content->{'url_encoded_fmt_stream_map'}, 1);
+ } else {
+ $self->debug("No URL data found");
+ return undef;
+ }
+
+ unless(exists($content->{'title'})) {
+ $self->debug("No title found");
+ return undef;
+ }
+
+ $self->__pick_url($urls, $preflist, $metadata);
+
+ $metadata->{'TITLE'} = $content->{'title'};
+ $metadata->{'TITLE'} =~ s/\+/ /g;
+ $metadata->{'TITLE'} = $self->decode_hexurl($metadata->{'TITLE'});
+ $metadata->{'TITLE'} = decode("utf8", $metadata->{'TITLE'});
+
+ $self->debug('Title found: %s', $metadata->{'TITLE'});
+
+ unless(defined($metadata->{'DLURL'}) && defined($metadata->{'TITLE'})) {
+ $self->error('Could not determine download URL');
+ return undef;
+ }
+
+ return $metadata;
+}
+
+sub _parse_by_scrape {
+ my $self = shift;
+ my $url = shift;
+ my $id = shift;