You're viewing a comment by Michael and its responses.

Michael Permalink
December 14, 2009, 02:30

Today I made my first Perl steps, inspired by this one-liner. I added a direkt pipe to convert the file to mp3 with ffmpeg, a name extraction from the youtube page, like in the awk script, and a download status bar, to have some more convenience than with the one-liner. Comments for better code style anytime welcome.

#!/usr/bin/perl
# Requires some packages
# For debian/ubuntu ->
# sudo apt-get install libwww-perl libwww-mechanize-perl ffmpeg

$outdir = $ENV{HOME}."/incoming/youtube";
chdir $outdir or die "Chdir \"$outdir\": $!";

use WWW::Mechanize;
use feature 'state';

$_ = shift;
my $m = WWW::Mechanize->new;
s!http://|www\.|youtube\.(com|de)/|watch\?|v=|&[^v][^=][^&]*!!g; # remove all except id
s/%(..)/chr(hex($1))/ge for 
	(($u) = $m->get("http://www.youtube.com/watch?v=$_")->content =~ /l_map": .+(?:%2C)?5%7C(.+?)"/);

my $stream = HTML::TokeParser->new(\$m->content);
$stream->get_tag("title");
my $name = $stream->get_trimmed_text("/title");
$name =~ s/^YouTube\s*-\s*//;
$name =~ s![\\/]!-!g;
$name =~ s![^\w,.-]! !g;
$name =~ s/^\s+|\s+$//g;

STDOUT->autoflush(1);
open(CONVERT, "| ffmpeg -i - -y -acodec copy \"$outdir/$name.mp3\" 2>/dev/null") 
	or die "Can't fork ffmpeg: $!";
$m->get($u, ":content_cb" => \&get_chunk) or die "Get \"$u\": $!";
close(CONVERT);
print "\nDone.\n";

sub get_chunk {
	($data, $response) = @_;
	print CONVERT $data;
	state $b = 0;
	state $l = $response->content_length;
	if ($l) {
		$b += length($data);
		$percent = 100. * $b / $l;
		print STDOUT sprintf("Downloading \"$name\": %.0f%%  \r", $percent);
	}         
}

Reply To This Comment

(why do I need your e-mail?)

(Your twitter name, if you have one. (I'm @pkrumins, btw.))

Type first 3 letters of your name: (just to make sure you're a human)

Please preview the comment before submitting to make sure it's OK.