#!perl
use
Encode
qw(find_encoding decode_utf8)
;
my
$encode
=
'utf8'
;
my
$overwrite
= 0;
my
$verbose
= -t STDOUT ? 1 : 0;
my
$interval
= 1;
my
$proxy
=
undef
;
GetOptions(
'C|no-colors!'
=> \
my
$disable_colors
,
'U|url!'
=> \
my
$playback_url
,
'o|output=s'
=> \
my
$output
,
'F|fmt=i'
, => \
my
$fmt
,
's|skip'
=> \
my
$skip
,
'n|dry-run'
=> \
my
$dry_run
,
'v|verbose!'
=> \
$verbose
,
'i|interval=i'
=> \
$interval
,
'e|encode=s'
=> \
$encode
,
'f|force!'
=> \
$overwrite
,
'p|proxy=s'
=> \
$proxy
,
'q|quiet!'
=>
sub
{
$verbose
= 0 },
'h|help'
=>
sub
{ help() },
'm|man'
=>
sub
{ pod2usage(
-verbose
=> 2) },
'V|version!'
=>
sub
{ show_version() },
) or help();
challeng_load_argv_from_fh()
unless
@ARGV
;
help()
unless
@ARGV
;
my
$encoder
= find_encoding(
$encode
) or throw(
"not supported encoding: $encode"
);
$output
=
$encoder
->decode(
$output
)
if
$output
;
my
$client
= WWW::YouTube::Download->new;
if
(
$proxy
) {
$client
->{ua}->proxy([
'http'
,
'https'
] =>
$proxy
);
print
"--> Using proxy $proxy\n"
;
}
main: {
while
(
@ARGV
) {
my
$video_id
=
shift
@ARGV
;
my
$meta_data
=
$client
->prepare_download(
$video_id
);
chatty(
"--> Working on $meta_data->{video_id}"
);
if
(
$fmt
&& !
$client
->_is_supported_fmt(
$video_id
,
$fmt
)) {
throw(
"[$meta_data->{video_id}] this video has not supported fmt: $fmt"
);
}
if
(
$playback_url
) {
my
$p_url
=
$client
->playback_url(
$video_id
, {
fmt
=>
$fmt
});
chatty(
"Playback URL: $p_url"
);
next
;
}
my
$filename
=
$client
->_format_filename(
$output
, {
video_id
=>
$meta_data
->{video_id},
user
=>
$meta_data
->{user},
resolution
=>
$meta_data
->{resolution},
title
=> decode_utf8(
$meta_data
->{title}),
suffix
=>
$fmt
?
$meta_data
->{video_url_map}{
$fmt
}{suffix} :
$meta_data
->{suffix},
fmt
=>
$fmt
||
$meta_data
->{fmt},
});
$filename
= filename_normalize(
$filename
);
$filename
=
$encoder
->encode(
$filename
,
sub
{
sprintf
'U+%x'
,
shift
});
if
(
$dry_run
) {
print
"$filename\n"
;
next
;
}
if
(
$skip
&& -e
$filename
) {
print
"Skipping existing file: $filename\n"
;
next
;
}
eval
{
$client
->download(
$video_id
, {
filename
=>
$filename
,
fmt
=>
$fmt
,
verbose
=>
$verbose
,
overwrite
=>
$overwrite
,
});
};
if
(
my
$e
= $@) {
unlink
$filename
if
-e
$filename
&& !-s
$filename
;
throw(
"[$meta_data->{video_id}] $e"
);
}
chatty(pcolor([
'green'
],
'Download successful!'
));
Time::HiRes::
sleep
(
$interval
)
if
@ARGV
;
}
}
exit
;
sub
challeng_load_argv_from_fh {
return
unless
$0 ne
'-'
&& !-t STDIN;
while
(
defined
(
my
$line
= <STDIN>)) {
chomp
$line
;
$line
=~ s/
$line
=~ s/^\s+|\s+$//g;
push
@ARGV
,
$line
;
}
}
sub
filename_normalize {
my
$filename
=
shift
;
$filename
=~ s
$filename
=~ s
$filename
=~ s
$filename
=~
tr
return
$filename
;
}
sub
throw {
die
pcolor([
'red'
],
'ERROR: '
,
@_
),
"\n"
;
}
sub
chatty {
print
@_
,
"\n"
;
}
sub
pcolor {
my
(
$color
,
@msg
) =
@_
;
if
($^O eq
'MSWin32'
||
$disable_colors
|| !-t STDOUT) {
return
@msg
;
}
return
@msg
if
$@;
return
Term::ANSIColor::colored(
$color
,
@msg
);
}
sub
show_version {
print
"youtube-download (WWW::YouTube::Download) version $WWW::YouTube::Download::VERSION\n"
;
exit
;
}
sub
help {
print
<<
'HELP'
;
Usage:
youtube-download [options] video_id_or_video_url ...
Options:
-C, --
no
-colors Disable colored output
-o, --output Output filename, supports `{
$value
}`
format
-e, --encode File
system
encoding (e.g. cp932)
-F, --fmt Video quality (SEE ALSO Wikipedia)
-f, --force Force overwrite output file
-s, --skip Skip download
when
output file
exists
-i, --interval Download interval
-p, --proxy Use the stated proxy
-n, --dry-run Do not download any videos,
print
target filenames
-v, --verbose Turns on chatty output (
default
: enabled)
-
q, --quiet Turns off progress
-U,
--url Display playback URL
for
a video
-h, --help Display help
-m, --man Display man page
-V, --version Display version
supported `{
$value
}`
format
are:
{video_id} / {user} / {title} / {fmt} / {suffix} / {resolution}
Examples:
$ youtube-download -o
"[{video_id}] {title}.{suffix}"
HELP
exit
1;
}