Created
March 22, 2014 16:35
-
-
Save skaji/9710019 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use strict; | |
use warnings; | |
use utf8; | |
use Encode qw{ encode decode }; | |
use WWW::YouTube::Download; | |
use Term::ReadKey (); | |
use List::Util qw(first); | |
use File::Temp (); | |
use File::Spec (); | |
use IO::Handle; | |
use constant { | |
WIN => $^O eq 'MSWin32', | |
MAC => $^O eq 'darwin', | |
}; | |
die 'Only for MSWin32 or Mac.' if !WIN && !MAC; | |
STDOUT->autoflush; | |
my @AAC_FMT_LIST = qw{37 22 35 34 18}; | |
my ($TERMINAL_WIDTH) = Term::ReadKey::GetTerminalSize(); | |
print "Input a video URL:\n"; | |
chomp(my $video_url = <STDIN>); | |
my $client = WWW::YouTube::Download->new; | |
my $meta = $client->prepare_download($video_url); | |
my ($title, $fmt, $suffix) = get_title_fmt_suffix($meta); | |
my $dir = File::Temp->newdir(CLEANUP => 1); | |
my $filename = File::Spec->catfile($dir, $title); | |
print "Dir: $dir\n"; | |
# ビデオダウンロード | |
open my $fh, '>:raw', $filename or die "Cannot open $filename: $!"; | |
print "Downloading: $title (suffix=$suffix, fmt=$fmt)\n"; | |
eval { | |
$client->download($video_url, {fmt => $fmt, cb => \&callback}); | |
}; | |
die "Error: Can't complete downloading: $@" if $@; | |
close $fh; | |
print "Successfully finished downloading.\n"; | |
# ffmpeg | |
my $null = WIN ? 'nul' : '/dev/null'; | |
system qq|ffmpeg -i "$filename" -vn | | |
.qq|-acodec copy -y "$filename.m4a" 1> $null 2>&1|; | |
# iTunes | |
if (WIN) { | |
system qq|start iTunes "$filename.m4a"|; | |
} | |
elsif (MAC) { | |
system qw{open -a /Applications/iTunes.app}, "$filename.m4a"; | |
} | |
print "Waiting 20 seconds to start iTunes.....\n"; | |
sleep 30; | |
exit; | |
sub callback { | |
my ($chunk, $res, $proto) = @_; | |
print {$fh} $chunk; | |
my $size = tell $fh; | |
my $total = $res->header('Content-Length'); | |
my $width = $TERMINAL_WIDTH - 26; | |
my $progress = int($size / $total * $width); | |
printf "Total:%5.1fMB (%5.1f%%)", ( | |
$total / 1024 / 1024, $size / $total * 100 | |
); | |
print '['; | |
print '=' x $progress; | |
print ' ' x ($width - $progress); | |
print "]\r"; | |
print "\n" if $total == $size; | |
} | |
sub get_title_fmt_suffix { | |
my $meta = shift; | |
my $title = filename_normalize( | |
decode('utf8', $meta->{title}) | |
); | |
if (WIN) { | |
$title = encode('cp932', $title); | |
} | |
elsif (MAC) { | |
$title = encode('utf8', $title); | |
} | |
my $fmt = _get_aac_fmt( $meta->{fmt_list} ); | |
my $suffix = $meta->{video_url_map}{$fmt}{suffix}; | |
return ($title, $fmt, $suffix); | |
} | |
sub _get_aac_fmt { | |
my %get_fmt_list = map { $_ => 1 } @{shift()}; | |
first { exists $get_fmt_list{$_} } @AAC_FMT_LIST; | |
} | |
# 以下は youtube-download からの丸写し | |
sub filename_normalize { | |
my $filename = shift; | |
$filename =~ s#[[:cntrl:]]##smg; # remove all control characters | |
$filename =~ s#^\s+|\s+$##g; # trim spaces | |
$filename =~ s#^\.+##; # remove multiple leading dots | |
$filename =~ tr#"/\\:*?<>|#'\-\-\-_____#; # NTFS and FAT unsupported characters | |
return $filename; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment