xaicron / p5-www-youtube-download

YouTube video download interface.
http://blog.livedoor.jp/xaicron/
Other
38 stars 28 forks source link

unexpected end of string while parsing JSON string #65

Open 05022021 opened 3 years ago

05022021 commented 3 years ago

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.

oalders commented 3 years ago

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.

toddr commented 1 year ago

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 commented 1 year ago

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 {
oalders commented 1 year ago

@toddr do you want to create a PR?

toddr commented 1 year ago

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 commented 1 year ago

@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.

oalders commented 1 year ago

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