Youtube: Add support for adaptive video formats (split video/audio)
authorRalf Ertzinger <ralf@skytale.net>
Sun, 8 Dec 2013 16:05:28 +0000 (17:05 +0100)
committerRalf Ertzinger <ralf@skytale.net>
Sun, 8 Dec 2013 16:05:28 +0000 (17:05 +0100)
videosite-dl.pl
videosite/FileGetter.pm
videosite/YouTubeGrabber.pm

index a907b84..688efb3 100755 (executable)
@@ -16,6 +16,7 @@ my %config = (
     mode => 'download',
     getter => 'filegetter',
     'plugin.youtube.QUALITY' => 'hd',
+    'plugin.youtube.ADAPTIVE' => 1,
     'plugin.filegetter.FILEPATTERN' => './%3$s.flv',
 );
 
index b2a0cea..48278dd 100644 (file)
@@ -60,6 +60,17 @@ sub get {
         return 0;
     }
 
+    if (exists($video->{'DLURL_AUDIO'})) {
+        $dlfile = $dlfile . ".audio";
+        $self->debug('Going to download %s to %s', $video->{'DLURL_AUDIO'}, $dlfile);
+
+        $res = $ua->mirror($video->{'DLURL_AUDIO'}, $dlfile);
+        if (!$res->is_success()) {
+            $self->error('Could not download %s to %s (%s)', $video->{'DLURL_AUDIO'}, $dlfile, $res->code());
+            return 0;
+        }
+    }
+
     return 1;
 }
 
index 423184c..148974a 100644 (file)
@@ -20,11 +20,17 @@ use videosite::JSArrayParser;
 use strict;
 
 my %preflist = (
-    'insane' => [38, 37, 22, 35, 18, 34, 6, 5, 43],
-    'hd' => [37, 22, 35, 18, 34, 6, 5, 38, 43],
-    'h264' => [18, 34, 37, 22, 35, 6, 5, 38, 43],
-    'high' => [34, 35, 18, 37, 22, 6, 5, 38, 43],
-    'normal' => [6, 5, 34, 35, 18, 22, 37, 38, 43]);
+    'insane' => [38, 37, 137, 22, 136, 35, 135, 18, 134, 34, 6, 5, 43],
+    'hd' => [37, 137, 22, 136, 35, 135, 18, 134, 34, 6, 5, 38, 43],
+    'h264' => [18, 134, 34, 37, 137, 22, 136, 35, 135, 6, 5, 38, 43],
+    'high' => [34, 35, 135, 18, 134, 37, 137, 22, 136, 6, 5, 38, 43],
+    'normal' => [6, 5, 34, 35, 135, 18, 134, 22, 136, 37, 137, 38, 43]);
+my %audiopreflist = (
+    'insane' => [172,141,171,140,139],
+    'hd' => [172,141,171,140,139],
+    'h264' => [172,141,171,140,139],
+    'high' => [171,140,172,141,139],
+    'normal' => [171,140,172,141,139]);
 my %videoformats = (
     # Container/Video codec/Audio codec/Resolution
     5 => 'FLV/Sorenson/MP3/240p',
@@ -49,6 +55,17 @@ my %videoformats = (
     100 => 'WebM/VP8/Vorbis/360p/3D',
     101 => 'WebM/VP8/Vorbis/480p/3D',
     102 => 'WebM/VP8/Vorbis/720p/3D',
+    133 => 'MP4/H264/240p/AdaptiveVideo',
+    134 => 'MP4/H264/360p/AdaptiveVideo',
+    135 => 'MP4/H264/480p/AdaptiveVideo',
+    136 => 'MP4/H264/720p/AdaptiveVideo',
+    137 => 'MP4/H264/1080p/AdaptiveVideo',
+    139 => 'MP4/AAC/48kbit/AdaptiveAudio',
+    140 => 'MP4/AAC/128kbit/AdaptiveAudio',
+    141 => 'MP4/AAC/256kbit/AdaptiveAudio',
+    160 => 'MP4/H264/144p/AdaptiveVideo',
+    171 => 'WebM/Vorbis/128kbit/AdaptiveAudio',
+    172 => 'WebM/Vorbis/160kbit/AdaptiveAudio',
     );
 
 sub new {
@@ -74,7 +91,8 @@ sub new {
                            hd => 'HD720 resolution'}],
             USERNAME => ['', 'Username to use for YouTube login'],
             PASSWORD => ['', 'Password to use for YouTube login'],
-            HTTPS => [1, 'Whether to use HTTPS (if available) to connect to YouTube']
+            HTTPS => [1, 'Whether to use HTTPS (if available) to connect to YouTube'],
+            ADAPTIVE => [0, 'Whether to use adaptive rate URLs (if available)'],
         },
         @_,
     );
@@ -127,6 +145,7 @@ sub _parse_by_video_info {
     my $videourl;
     my $ua = $self->ua();
     my $preflist;
+    my $audiopreflist;
     my $r;
     my $content;
     my $urls;
@@ -139,7 +158,11 @@ sub _parse_by_video_info {
     $metadata->{'DLURL'} = undef;
 
     $preflist = $preflist{$quality};
-    $self->debug("Quality: %s, preflist: [%s]", $quality, join(", ", @{$preflist}));
+    $audiopreflist = $audiopreflist{$quality};
+    $self->debug("Quality: %s, preflist: [%s], audiopreflist: [%s]",
+            $quality,
+            join(", ", @{$preflist}),
+            join(", ", @{$audiopreflist}));
 
     $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');
@@ -181,12 +204,24 @@ sub _parse_by_video_info {
         return undef;
     }
 
+    if (exists($content->{'adaptive_fmts'})) {
+        $self->debug('Video has adaptive_fmts');
+        if ($self->_getval('ADAPTIVE')) {
+            my %af = %{$self->_decode_url_encoded_fmt_stream_map($content->{'adaptive_fmts'}, 1)};
+            while (my ($k, $v) = each %af) {
+                $urls->{$k} = $v;
+            }
+        } else {
+            $self->debug('Use of adaptive URLs not enabled');
+        }
+    }
+
     unless(exists($content->{'title'})) {
         $self->debug("No title found");
         return undef;
     }
 
-    $self->__pick_url($urls, $preflist, $metadata);
+    $self->__pick_url($urls, $preflist, $audiopreflist, $metadata);
 
     $metadata->{'TITLE'} = $content->{'title'};
     $metadata->{'TITLE'} =~ s/\+/ /g;
@@ -332,7 +367,7 @@ sub _parse_by_scrape {
 
 
             if (%urls) {
-                $self->__pick_url(\%urls, $preflist, $metadata);
+                $self->__pick_url(\%urls, $preflist, undef, $metadata);
                 last SWF_ARGS;
             }
         } elsif ('div' eq $tag->[0]) {
@@ -503,7 +538,9 @@ sub __pick_url {
     my $self = shift;
     my $urls = shift;
     my $preflist = shift;
+    my $audiopreflist = shift;
     my $metadata = shift;
+    my $picked_format;
 
     foreach (keys(%{$urls})) {
         if (exists($videoformats{$_})) {
@@ -517,6 +554,7 @@ sub __pick_url {
         if (exists($urls->{$_})) {
             $self->debug("Selected URL with quality level %s", $_);
             $metadata->{'DLURL'} = $urls->{$_};
+            $picked_format = $_;
             if (exists($videoformats{$_})) {
                 $metadata->{'FORMAT'} = $videoformats{$_};
             } else {
@@ -526,6 +564,28 @@ sub __pick_url {
         }
     }
 
+    if (defined($picked_format)) {
+        if ($metadata->{'FORMAT'} =~ m/Adaptive/) {
+            if (defined($audiopreflist)) {
+                # Pick an audio format as well
+                foreach (@{$audiopreflist}) {
+                    if (exists($urls->{$_})) {
+                        $self->debug("Selected audio URL with quality level %s", $_);
+                        $metadata->{'DLURL_AUDIO'} = $urls->{$_};
+                        if (exists($videoformats{$_})) {
+                            $metadata->{'FORMAT_AUDIO'} = $videoformats{$_};
+                        } else {
+                            $metadata->{'FORMAT_AUDIO'} = 'unknown';
+                        }
+                        last;
+                    }
+                }
+            } else {
+                $self->error('Need an audio preflist, but none provided');
+            }
+        }
+    }
+
     $self->debug('URL found: %s', $metadata->{'DLURL'});
 }