p5-www-youtube-download icon indicating copy to clipboard operation
p5-www-youtube-download copied to clipboard

unexpected end of string while parsing JSON string

Open 05022021 opened this issue 4 years ago • 7 comments

youtube-download.pl https://www.youtube.com/watch?v=NqVE9qfg7yI unexpected end of string while parsing JSON string, at character offset 2 (before "rgs:{raw_player_resp...") at E:\Downloads\youtube-download.pl line 61.

05022021 avatar Feb 05 '21 05:02 05022021

I tried with a different video and it also dies like this. I don't have the bandwidth to fix it, but I'd welcome a PR for this.

oalders avatar Feb 12 '21 04:02 oalders

The code was changed and now it looks like we have vars instead of the needed data in the JSON structure. I also had to change the regex to match on it.

{args:{raw_player_response:window.ytplayer.bootstrapPlayerResponse}}

toddr avatar Jul 17 '23 01:07 toddr

This will fix the reported bug and it does start downloading but VERY slowly. I suspect there's some throttle we need to manipulate on the download.

diff --git a/lib/WWW/YouTube/Download.pm b/lib/WWW/YouTube/Download.pm
index b00d2a6..b01d33f 100644
--- a/lib/WWW/YouTube/Download.pm
+++ b/lib/WWW/YouTube/Download.pm
@@ -157,8 +157,7 @@ sub prepare_download {
     my ($title, $user, $video_url_map);
     my $content = $self->_get_content($video_id);
     if ($self->_is_new($content)) {
-      my $args        = $self->_get_args($content);
-      my $player_resp = JSON()->new->decode($args->{player_response});
+      my $player_resp = $self->_get_player_response($content);
       $video_url_map  = $self->_decode_player_response($player_resp);
       $title          = decode_entities $player_resp->{videoDetails}{title};
       $user           = decode_entities $player_resp->{videoDetails}{author};
@@ -285,7 +284,7 @@ sub _get_content {
     return $res->content;
 }
 
-sub _get_args {
+sub _get_player_response {
     my ($self, $content) = @_;
 
     my $data;
@@ -294,15 +293,15 @@ sub _get_args {
         if ($line =~ /the uploader has not made this video available in your country/i) {
             croak 'Video not available in your country';
         }
-        elsif ($line =~ /^.+ytplayer\.config\s*=\s*(\{.*})/) {
-            ($data, undef) = JSON->new->utf8(1)->decode_prefix($1);
+        elsif ($line =~ /^.+ytInitialPlayerResponse\s*=\s*(\{.*});/) {
+           ($data, undef) = JSON->new->utf8(1)->decode_prefix($1);
             last;
         }
     }
 
-    croak 'failed to extract JSON data' unless $data->{args};
+    croak 'failed to extract JSON data' unless $data;
 
-    return $data->{args};
+    return $data;
 }
 
 sub _is_new {

toddr avatar Jul 17 '23 02:07 toddr

@toddr do you want to create a PR?

oalders avatar Jul 17 '23 02:07 oalders

I see someone talking about having to re-start the download. that'd be a different case.

Try the newest version of Youtube-dl. I was under the impression that they circumvented much of the throttling in later versions (by automatically re-connecting when the speed goes down. Apparently the first few seconds of the connection isn't throttled, as I understand it.)

toddr avatar Jul 17 '23 02:07 toddr

@toddr do you want to create a PR?

I'm only hacking downloads. looks like I'd have to fix all of the get_args callers and fix a lot of tests.

toddr avatar Jul 17 '23 02:07 toddr

Whatever works, but if you want to make it less broken than it currently is, that's a start. :)

oalders avatar Jul 17 '23 02:07 oalders