in reply to YouTube Video Downloader

Youtube changed its page layout recently, so none of the common tools (this script, but also clive and the Firefox VideoDownloader extension) works anymore. So I quickly modified this script to make it work again. Here it is :
#!/usr/bin/perl use strict; use warnings; use LWP::Simple; use LWP::UserAgent; # shamelessly reversed engineered from a python script :-) print "starting first page retrieval\n"; my $urlin = shift || "http://youtube.com/watch?v=NeiLBET8Cdk"; my $content = get( $urlin ) or die "argh : $!\n"; print "done first page retrieval : $urlin\n"; # print "$content" ; # regex for 2 key text strings which identify the video file # the second one $2 is unique for each download attempt # $content =~ /player2\.swf\?video_id=([^&]+)&.*t=([^&]+)&/ ; $content =~ /<title>(.*)<\/title>/ ; my $infile = $1.'.flv' ; $content =~ /watch_fullscreen\?video_id=([^&]+)&.*t=([^&]+)&/ ; print $1, "\n" , $2, "\n"; #http://www.youtube.com/get_video?video_id=p_YMigZmUuk&t=OEgsToPDskLRl +9-iKyfQVcNT8xes2OIT my $get_url = 'http://www.youtube.com/get_video?video_id='.$1.'&t='.$2 +; print "gettin video file : $infile\n"; # don't buffer the prints to make the status update $| = 1; open(IN,"> $infile") or die "$_\n"; my $ua = LWP::UserAgent->new(); my $received_size = 0; my $url = $get_url; print "Fetching $url\n"; my $request_time = time; my $last_update = 0; my $response = $ua->get($url, ':content_cb' => \&callback, ':read_size_hint' => 8192, ); print "\n"; close IN; #play the flv file with mplayer # system( "mplayer $infile" ); ############################################# sub callback { my ($data, $response, $protocol) = @_; my $total_size = $response->header('Content-Length') || 0; $received_size += length $data; # write the $data to a filehandle or whatever should happen # with it here. print IN $data; my $time_now = time; # this to make the status only update once per second. return unless $time_now > $last_update or $received_size == $total_s +ize; $last_update = $time_now; print "\rReceived $received_size bytes"; printf " (%i%%)", (100/$total_size)*$received_size if $total_size; printf " %6.1f/bps", $received_size/(($time_now-$request_time)||1) if $received_size; } __END__
Enjoy!

Replies are listed 'Best First'.
Re^2: YouTube Video Downloader
by zentara (Cardinal) on Sep 04, 2007 at 12:35 UTC
    Thanks for pointing that out, it worked here. I did notice that YouTube started changing it's downloads a few months ago. At the time, it looked to me like they were trying to work out a system of regional servers to improve efficiency, and there was some extra codes in there. I figured that ultimately I would need to switch to WWW:Mechanize, and decided it wasn't worth the effort..... since the novelty of YouTube has worn off for me, and they might change it all again at some future time. :-)

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re^2: YouTube Video Downloader
by Anonymous Monk on Jan 29, 2008 at 18:00 UTC
    Well the times they keep a changin' ...
    #!/usr/bin/perl use strict; use warnings; use LWP::Simple; use LWP::UserAgent; # shamelessly reversed engineered from a python script :-) print "starting first page retrieval\n"; my $urlin = shift || "http://youtube.com/watch?v=vCsQLQ00hvs"; my $content = get( $urlin ) or die "argh : $!\n"; print "done first page retrieval : $urlin\n"; # print "$content" ; # regex for 2 key text strings which identify the video file # the second one $2 is unique for each download attempt # $content =~ /player2\.swf\?video_id=([^&]+)&.*t=([^&]+)&/ ; my $infile = ($content =~ m{<title>([^<]+)</title>})[0] . '.flv'; my ($video_id) = ($content =~ /watch_fullscreen\?(?:.*?)video_id=([^&] ++)/); my ($t_id) = ($content =~ /watch_fullscreen\?(?:.*?)t=([^&]+)/); my $get_url = "http://www.youtube.com/get_video?video_id=$video_id&t=$ +t_id"; print "gettin video file : $infile\n"; # don't buffer the prints to make the status update $| = 1; open(IN,"> $infile") or die "$_\n"; my $ua = LWP::UserAgent->new(); my $received_size = 0; my $url = $get_url; print "Fetching $url\n"; my $request_time = time; my $last_update = 0; my $response = $ua->get($url, ':content_cb' => \&callback, ':read_size_hint' => 8192, ); print "\n"; close IN; #play the flv file with mplayer # system( "mplayer $infile" ); ############################################# sub callback { my ($data, $response, $protocol) = @_; my $total_size = $response->header('Content-Length') || 0; $received_size += length $data; # write the $data to a filehandle or whatever should happen # with it here. print IN $data; my $time_now = time; # this to make the status only update once per second. return unless $time_now > $last_update or $received_size == $total_s +ize; $last_update = $time_now; print "\rReceived $received_size bytes"; printf " (%i%%)", (100/$total_size)*$received_size if $total_size; printf " %6.1f/bps", $received_size/(($time_now-$request_time)||1) if $received_size; } __END__
    Works like a charm again! :)
      thanks for the update !
        i cannot get this to work on my macintosh. nothing is displayed or played but it completes the script.
        Can you get this to work with videos from clipfish.de, too? (Wrong URL in previous posting, sorry...)
Re^2: YouTube Video Downloader
by Anonymous Monk on Jan 18, 2008 at 07:26 UTC
    missing binmode again