Welcome to HBH! If you have tried to register and didn't get a verification email, please using the following link to resend the verification email.
CLI Youtube Viewer - Perl Code Bank
CLI Youtube Viewer
Search and play videos from Youtube with MPlayer.
Deps on Unix: perl-libwww, mplayer
Deps on Windows: Active-Perl, SMPlayer
#!/usr/bin/perl
#
# Copyright (C) 2010-2011 Trizen <echo dHJpemVueEBnbWFpbC5jb20K | base64 -d>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#-------------------------------------------------------
# (C) 2010-2011 by Trizen
# Created on: 02 Jun 2010
# Latest edit on: 03 July 2011
# Website: http://trizen.go.ro
# Email: echo dHJpemVueEBnbWFpbC5jb20K | base64 -d
#-------------------------------------------------------
#
# [?] What is this script for?
# - This script is useful to search and watch YouTube videos with MPlayer...
# - Have fun!
#
# [!] Most important changes are written in the changelog!
#
# [CHANGELOG]
# - Added few options to control cache of MPlayer and lower cache for lower video resolutions - NEW (v2.5.1)
# - Added colours for text (--colours) or $colours = 1, 360p support (-3), playlist support - NEW (v2.5.0)
# - Added support for today and all time Youtube tops (usage: -t, --tops, -a, --all-time) - (v2.4.*)
# - Re-added the support for the next page / Added support for download (-d, --download) - (v2.4.*)
# - Added support for Youtube CCaptions. (Depends on: 'gcap' - http://gcap.googlecode.com) - (v2.4.*)
# - First version with Windows support. Require SMPlayer to play videos. See MPlayer Line - (v2.4.*)
# - Code has been changed in a proportion of ~60% and optimized for speed // --480 became -4 - (v2.4.*)
# - Added mega-powers of omnibox to the STDIN :) - (v2.3.*)
# - Re-added the option to list and play youtube videos from a user profile. Usage: -u [user] - (v2.3.*)
# - Added a new option to play only the audio track of a videoclip. Usage: [words] -n - (v2.3.*)
# - Added option for fullscreen (-f, --fullscreen). Usage: youtube-viewer [words] -f - (v2.3.*)
# - Added one new option '-c'. It shows available categories and will let you to choose one. - (v2.3.*)
# - Added one new option '-m'. It shows 3 pages of youtube video results. Usage: [words] -m - (v2.3.*)
# - For "-A" option has been added 3 pages of youtube video results (50 clips) - (v2.3.*)
# - Added "-prefer-ipv4" to the mplayer line (videoclips starts in no time now). - (v2.3.*)
# - Search and play videos at 480p, 720p. Ex: [words] --480, [words] -A --480 - (v2.3.*)
# - Added support to play a video at 480p even if it's resolution is higher. Ex: [url] --480 - (v2.2.*)
# - Added a nice feature which prints some informations about the current playing video - (v2.2.*)
# - Added support to play videos by your order. Example: after search results, insert: 3 5 2 1 - (v2.1.*)
# - Added support for next pages of video results (press <ENTER> after search results) - (v2.1.*)
# - Added support to continue playing searched videos, usage: "youtube-viewer [words] -A" - (v2.1.*)
# - Added support to print counted videos and support to insert a number instead of video code - (v2.1.*)
# - Added support to search YouTube Videos in script (ex: youtube-viewer avatar trailer 2009) - (v2.0.*)
# - Added support for script to choose automat quality if it is lower than 1080p - (v2.0.*)
# - Added support to choose the quality only between 720p and 1080p (if it is available) - (v2.0.*)
# - Added support for an YouTube video code (ex: youtube-viewer WVTWCPoUt8w) - (v1.0.*)
# - Added support for 720p and 1080p YouTube Videos... - (v1.0.*)
# Special thanks to:
# - Army (for bugs reports and for his great ideas)
# - dhn (for adding youtube-viewer in freshports.org)
use URI::Escape;
use HTML::Entities;
my $os = $^O;
my $appname = 'youtube-viewer';
my $version = '2.5.1';
my $colours = 0;
my $cache = 30000;
my $cache_min = 5;
my $user_lower_cache = 0;
my $order_by = 'relevance';
my $time_p = 'all_time';
my $mplayer_settings = "-prefer-ipv4 -cache $cache -cache-min $cache_min";
my $mplayer_srt_settings = '-unicode -utf8';
if ( $os =~ /(?:win|dos)/i ) {
$MPlayer_exe = $ENV{'ProgramFiles'} . '\\SMPlayer\\mplayer\\mplayer.exe';
unless ( -e $MPlayer_exe ) {
warn "\n\n!!! Please install SMPlayer to stream Youtube videos.\n\n";
}
$MPlayerLine = qq["$MPlayer_exe" $mplayer_settings];
}
else {
$MPlayerLine = "mplayer $mplayer_settings";
}
sub UserAgent {
require LWP::UserAgent;
$lwp = 'LWP::UserAgent'->new;
$lwp->agent('Mozilla/5.0 (X11; U; Linux i686; en-US) Chrome/10.0.648.45');
$lwp->env_proxy;
$lwp->timeout(15);
$lwp->show_progress(1) if $debug;
$lwp_is_set = 1;
}
if ( not $os =~ /(?:win|dos)/i ) {
$bred = "\e[1;31m";
$bgreen = "\e[1;32m";
$reset = "\e[0m";
}
else {
$bred = '';
$bgreen = '';
$reset = '';
}
foreach my $arg (@ARGV) {
if ( $arg =~ /^-/ ) {
$stdin_argvs .= " $arg ";
}
else {
$Search .= "$arg ";
}
next unless $arg =~ /^-/;
if ( $arg =~ /^-+cache=(\d+)$/ ) {
my $cache = $1;
$MPlayerLine =~ s/-cache\s+\d+/-cache $cache/;
$user_cache = 1;
next;
}
if ( $arg =~ /^-+(?:l|lower.?cache)$/ ) {
$user_lower_cache = 1;
next;
}
if ( $arg =~ /^-+cache.?min=(\d+)$/ ) {
my $cache_min = $1;
$MPlayerLine =~ s/-cache-min\s+\d+/-cache-min $cache_min/;
$user_cache_min = 1;
next;
}
if ( $arg =~ /^-+(?:n|no.?video)$/ ) {
$MPlayerLine =~ s/mplayer /mplayer -novideo /;
$MPlayerLine =~ s/mplayer\.exe"/mplayer.exe" -novideo/;
$stdin_argvs .= ' --480';
next;
}
if ( $arg =~ /^-+time=(.+)/ ) {
$time_p = $1;
next;
}
if ( $arg =~ /^-+(?:T|tty|M|mplayer)=(.+)/ ) {
$MPlayerLine .= " $1";
next;
}
if ( $arg =~ /^-+(?:o|order.?by)=(.+)/ ) {
$order_by = $1;
next;
}
if ( $arg =~ /^-+(?:sub|lang)=([\w]+)$/ ) {
$default_sub = lc $1;
next;
}
if ( $arg =~ /^-+(?:colou?rs?|C|cl)$/ ) {
$colours = 1;
next;
}
if ( $arg =~ /^-+(?:d|download)$/ ) {
$download_video = 1;
next;
}
if ( $arg =~ /^-+(?:a|all.?time)$/ ) {
$all_time = 1;
next;
}
if ( $arg eq '--debug' ) {
$debug = 1;
next;
}
if ( $arg =~ /^-+(?:A|all)$/ ) {
$playback = 1;
$stdin_argvs .= ' --1080';
next;
}
if ( $arg =~ /^-+(?:m|more)$/ ) {
$MoreResults = 1;
next;
}
if ( $arg =~ /^-+(?:fs?|fullscreen)$/ ) {
$MPlayerLine =~ s/mplayer /mplayer -fs /;
$MPlayerLine =~ s/mplayer.exe"/mplayer.exe" -fs/;
}
}
if ( $colours and not $os =~ /(?:win|dos)/i ) {
$cblack = "\e[40m";
$byellow = "\e[1;33m";
$bpurle = "\e[1;35m";
$bblue = "\e[1;34m";
}
else {
$bblue = '';
$cblack = '';
$bpurle = '';
$byellow = '';
}
$stdin_argvs ||= '';
$default_sub ||= 'en';
$Search ||= '';
foreach my $arg (@ARGV) {
++$i;
next unless $arg =~ /^-/;
if ( $arg =~ /^[-]+(?:h|help|\?|usage)$/i ) {
&help;
}
if ( $arg =~ /^[-]+(?:v|version)$/i ) {
&version;
}
if ( $arg =~ /^[-]+(?:pl?|playlists?)$/ ) {
&search_playlists;
}
if ( $arg =~ /^[-]+(?:c|categories)$/ ) {
&categories_area;
}
if ( $arg =~ /^[-]+(?:a|all[_-]?time|t|tops)$/ ) {
&youtube_tops;
}
if ( $arg =~ /^[-]+(?:u|username)$/ ) {
if ( $ARGV[$i] ) {
unless ( $ARGV[$i] =~ /^-/ ) {
$user = $ARGV[$i];
}
}
unless ($user) {
$i -= 2;
if ( $ARGV[$i] ) {
unless ( $ARGV[$i] =~ /^-/ ) {
$user = $ARGV[$i];
}
}
}
if ($user) {
&videos_from_username($user);
}
}
}
foreach $_ (@ARGV) {
if ( not $_ =~ /^-/ or length $_ == 11 ) {
$non_argv = 1;
last;
}
}
&insert_url unless $non_argv;
foreach my $code (@ARGV) {
if ( $code =~ /^([\w-]{11})$/ ) {
$code = $1;
if ( $code =~ /[\d]+|[A-Z]+|-/ ) {
$dont_exit = 1;
&get_youtube($code);
}
}
elsif ( $code =~ /view_play_list\?p=([A-Z0-9]+)/ ) {
$playlist = 1;
&list_playlist($1);
}
elsif ( $code =~ m[(?:v|embed)[=/]+([\w-]{11})] ) {
$code = $1;
$dont_exit = 1;
if ( length $code == 11 ) {
&get_youtube($code);
}
else {
next;
}
}
elsif ( $code =~ m[^http://] and not $code =~ /youtube\.com/ ) {
&code_from_content($code);
}
else {
next;
}
}
sub help {
my $appname = uc $appname;
print "\n\t" . '=' x 25 . " $appname " . '=' x 25 . qq[
\t\t\t\t\t\t by Trizen (trizen.go.ro)
\n Usage: youtube-viewer [<url> | <video_id>] [-(4|7|1)]
[-u <username>] [-categories] [-(a|t)]
[<keywords>] [-fs] [-novideo] [-(m|p)]
\nBase Options: youtube-viewer [...]
<url> : play an YouTube video by URL
<code> : play an YouTube video by code
<keywords> : search and list YouTube videos
<playlist_url> : list a playlist of Youtube videos
\nYoutube options:
-t, --tops : shows today Youtube tops
-a, --all-time : shows all time Youtube tops
-c, --categories : shows available YouTube categories
-m, --more : shows more video results (50 clips)
-p, --playlist : searches for Youtube playlists
-u <username> : lists videos uploaded by a specific user
-order-by=<ORDER> : order entries by: published, viewCount or rating
-time=<TIME> : valid values are: today, this_week and this_month
-2, -3, -4, -7, -1 : plays videos at 240p, 360p, 480p, 720p and 1080p
\nMPlayer options:
-f, --fullscreen : plays all videos in fullscreen mode
-n, --novideo : plays only the audio track of video(s)
-l, --lower-cache : set a lower cache for MPlayer (for slow connections)
-mplayer='SETTINGS' : add some extra options to the MPlayer line
-sub=<LANG> : subtitle language (default: en) (depends on gcap)
-cache=<VALUE> : set cache for MPlayer (default: $cache)
-cache-min=<VALUE> : set cache-min for MPlayer (default: $cache_min)
\nOther options:
-d, --download : downloads youtube video(s) with LWP
-A, --all : plays all video results in order
-C, --colors : use colors for text output
-v, --version : prints version and exits
-h, --help : prints help and exits
\nTips and tricks:
1. After search results, press <ENTER> for the next page
2. After search results, insert: <number> (--download, -d, -1, -4, -7)
3. After search results, insert more numbers to play videos in your order
4. Play all audio tracks of video results by adding "-A -n" after keywords.
5. Play all video results in fullscreen mode at 720p: "<keywords> -A -f -7"
6. Play all videos from a user at 480p: "<username> -u -4" and insert "all"
\n];
exit;
}
sub version {
print "Youtube Viewer $version\n";
exit;
}
sub code_from_content {
&UserAgent unless $lwp_is_set;
$connect = $lwp->get( $_[0] ) if $_[0];
if ( $connect->content =~ m[youtube\.com/(?:v|embed)/([\w-]{11})] ) {
&get_youtube($1);
}
}
sub insert_url {
print "\n$bred=>>$reset$bgreen "
. "Insert an YouTube URL or search something...\n$reset> ";
chomp( $youtube = <STDIN> );
if ( $youtube =~ m[(?:v|embed)[=/]+([\w-]{11})] ) {
&get_youtube($1);
}
elsif ( $youtube =~ /view_play_list\?p=([A-Z0-9]+)/ ) {
$playlist = 1;
&list_playlist($1);
}
elsif ( $youtube =~ m[^http://] and not $youtube =~ /youtube\.com/ ) {
&code_from_content($youtube);
}
elsif ($youtube) {
$stdin_argvs .= ' ' . $youtube;
$Search = $youtube;
$number = 0;
&search;
}
else {
warn "\n$bred(x_x) Unable to continue...$reset\n\n";
exit;
}
}
sub videos_from_username {
$yt_api_url = "http://gdata.youtube.com/feeds/api/users/$_[0]/uploads";
&YoutubeAPI;
}
sub search_playlists {
$playlists = 1;
unless ($lwp_is_set) {
&UserAgent;
}
my $url = $_[0]
|| "http://gdata.youtube.com/feeds/api/playlists/snippets?q=$Search"
. '&start-index=1';
if ($MoreResults) {
$url .= '&max-results=50&v=2';
}
else {
$url .= '&max-results=20&v=2';
}
my (@playlists) = split( m?<title>?, $lwp->get($url)->content, 0 );
my $n = -1;
foreach $_ (@playlists) {
if ( $_ =~ m[^([^<]*)</title>] ) {
my $title = $1;
if ( $n == -1 ) {
++$n;
next;
}
$title = decode_entities($title);
$line = "<title=$title>";
}
if ( $_ =~ m[<summary>([^<]*)</summary>] ) {
$summary = $1;
$summary =~ s/\s+/ /g;
$summary = $1 if $summary =~ /^(.{10})/;
$summary = decode_entities($summary);
$line .= "<summary=$summary>";
}
else {
$line .= '<summary=>';
}
if ( $_ =~ m[<yt:playlistId>([^<]+)</yt:playlistId>] ) {
++$n;
$line .= "<playlist=$1>";
}
else {
next;
}
if ( $_ =~ m[<yt:countHint>(\d+)</yt:countHint>] ) {
$line .= "<count=$1>";
}
else {
$line .= '<count=0>';
}
if ( $_ =~ m[<name>([^<]+)</name>] ) {
$line .= "<author=$1>";
}
else {
$line .= '<author=Unknown>';
}
$line = "<#=$n>" . $line;
push @list_of_playlists, $line;
}
print "\n";
foreach $_ (@list_of_playlists) {
if (
/^<#=(\d+)><title=([^>]*)><summary=([^>]*)>
?<playlist=([^>]+)><count=(\d+)><author=([^>]+)>$/
) {
if ( $1 < 10 ) {
print ' ';
}
print "$cblack$bred$1$reset$cblack - $byellow$2 $3$reset"
. "$cblack (${bpurle}by $6$reset$cblack) "
. "($bblue$5$reset$cblack)$reset\n";
}
}
print "\n$bred=>>$reset ${bgreen}Pick one playlist$reset\n> ";
chomp( $pick = <STDIN> );
if ( not $pick =~ /^\s*\d+\s*$/ and $pick =~ /^(?:\s*|)$/ ) {
if ( $url =~ /start-index=(\d+)/ ) {
$old_index = $1;
$new_index = $1 + 20;
if ($MoreResults) {
$new_index += 30;
}
$url =~ s/start-index=\d+/start-index=$new_index/;
undef @list_of_playlists;
&search_playlists($url);
}
}
elsif ( $pick =~ /^\D+/ and not $pick =~ /^\s+\d+/ ) {
$Search = $pick;
undef @list_of_playlists;
&search_playlists;
}
elsif ( $pick =~ /^\s*(\d+)/ ) {
$pick = $1;
}
foreach $_ (@list_of_playlists) {
if ( $_ =~ /^<#=$pick>[\w\W]+<playlist=([^>]+)/ ) {
&list_playlist($1);
}
}
}
sub list_playlist {
if ( $_[0] and $_[0] =~ /^([A-Z0-9]+)$/ ) {
$yt_api_url = "http://gdata.youtube.com/feeds/api/playlists/$1";
&YoutubeAPI;
}
}
sub youtube_tops {
print "\n";
$n = 0;
unless ($all_time) {
$today = 1;
}
$youtube_top_url = 'http://gdata.youtube.com/feeds/api/standardfeeds';
foreach my $line (
'top_rated', 'top_favorites',
'most_viewed', 'most_popular',
'most_recent', 'most_discussed',
'most_responded', 'recently_featured'
) {
++$n;
my $top_name = ucfirst $line;
$top_name =~ s/_/ /;
print "$bred$n$reset - $top_name\n";
push @tops, "$n - $youtube_top_url/$line";
}
print "\n$bred=>>$bgreen Pick one of$reset\n> ";
chomp( my $pick = quotemeta <STDIN> );
foreach $_ (@tops) {
if ( $_ =~ /^$pick - (.+)/ ) {
$yt_api_url = $1;
if ($today) {
unless ( $yt_api_url =~ /recent/ ) {
$yt_api_url .= '?time=today';
}
}
&YoutubeAPI;
}
}
}
sub categories_area {
&UserAgent unless $lwp_is_set;
$connect =
$lwp->get('http://gdata.youtube.com/schemas/2007/categories.cat');
@cates = split( /category term=/, $connect->content, 0 );
$n = 0;
print "\n";
foreach my $cat (@cates) {
if ( $cat =~ /^'([^']+)' label='([^']+)'/ and not $cat =~ /deprecated/ )
{
++$n;
my $cat_name = $1;
my $cat_label = $2;
$cat_label =~ s/&/&/;
if ( $n < 10 ) {
print ' ';
}
print "$bred$n$reset - $cat_label\n";
push @categories, "$n - $cat_name";
}
}
print "\n$bgreen=>> Insert a category number\n>$reset ";
chomp( $pickcat = quotemeta <STDIN> );
foreach my $cat (@categories) {
if ( $cat =~ /^$pickcat - (.+)/ ) {
$yt_api_url = 'http://gdata.youtube.com/feeds/api/standardfeeds/'
. "recently_featured_$1";
&YoutubeAPI;
}
}
}
sub MPlayer {
print "** STREAMING: $streaming\n\n" if $debug;
if ( $download_video or $tmp_download_video ) {
$title =~ s[/][|]g;
if ( not -e "$title.mp4" ) {
print "** Saving to: '$title.mp4'\n";
$lwp->show_progress(1);
$lwp->mirror( $streaming, "$title.mp4" );
$lwp->show_progress(0);
}
else {
warn "** '$title.mp4' already exists...\n";
}
undef $tmp_download_video if $tmp_download_video;
}
else {
print "** MPlayer Line: $MPlayerLine\n\n" if $debug;
`$MPlayerLine "$streaming"`;
}
print "\n";
if ($Picks) {
&foreach_pick;
}
if ( $playlist or $video_results and not $dont_exit ) {
&print_results;
}
unless ($dont_exit) {
exit;
}
}
sub YoutubeAPI {
undef @Videos;
if ($MoreResults) {
$results = 50;
}
else {
$results = 20;
}
if ( not $yt_api_url =~ /\?/ ) {
$yt_api_url .= '?start-index=1';
}
else {
$yt_api_url .= '&start-index=1';
}
$yt_api_url .= "&max-results=$results";
&parse_content($yt_api_url);
&print_results;
}
unless ( $dont_exit or $playlists ) {
&search;
}
sub search {
$PageNumber = 1;
$FirstPage = 1;
$Search =~ s/^\s+|\s+$//g;
$Search = uri_escape($Search);
if ($MoreResults) {
$results = 50;
}
else {
$results = 20;
}
$ys = "http://gdata.youtube.com/feeds/api/videos?q=$Search"
. "&max-results=$results&time=$time_p&orderby=$order_by&start-index=1";
&parse_content($ys);
&print_results;
}
sub parse_content {
&UserAgent unless $lwp_is_set;
undef @Videos;
my (@content) = split( /<entry>/, $lwp->get( $_[0] )->content, 0 );
foreach $_ (@content) {
if ($debug) {
print "$_\n\n";
}
next unless $_ =~ /^<id>/;
if ( $_ =~ m[<name>([^<]+)</name>] ) {
$video_line = "<author=$1>";
}
if ( $_ =~ m[v=([\w-]+)&feature=youtube_gdata'/>] ) {
$video_line .= "<v=$1>";
}
if ( $_ =~ m[>([^<]+)</title>] ) {
$video_line .= "<title=$1>";
}
if ( $_ =~ /<media:category label=['"]([^']+)['"]/ ) {
$category_label = $1;
$category_label =~ s/&/&/;
$video_line .= "<category=$category_label>";
}
else {
$video_line .= '<category=None>';
}
if ( $_ =~ /<published>([\d-]+)/ ) {
$video_line .= "<published=$1>";
}
else {
$video_line .= '<published=0>';
}
if ( $_ =~ /duration[^']+'(\d+)'/ ) {
$video_line .= "<time=$1>";
}
else {
$video_line .= '<time=0>';
}
if ( $_ =~ /viewCount='(\d+)'/ ) {
$video_line .= "<views=$1>";
}
else {
$video_line .= '<views=0>';
}
if ( $_ =~ /<media:description type='plain'>([^<]+)/ ) {
$video_line .= "<description=$1>";
}
else {
$video_line .= '<description=No description available...>';
}
if ($debug) {
print "$video_line\n\n";
}
push @Videos, $video_line;
}
}
sub print_results {
$#codes = -1;
my $number = 0;
print "\n";
exit unless scalar @Videos;
foreach $line (@Videos) {
if (
$line =~ /^<author=([^>]+)><v=([^>]+)><title=([^>]+)>
<category=([^>]+)><published=([^>]+)><time=
([^>]*)><views=([^>]*)><description=([^>]+)>$/x
) {
++$number;
my $author = $1;
my $code = $2;
my $title = decode_entities($3);
my $category = $4;
my $published = $5;
my $time = format_time($6);
my $views = $7;
my $description = $8;
push @codes,
"$number>title=$title>published=$published>"
. "category=$category>time=$time>code="
. "$code>views=$views>desc=$description>";
print "$bred";
if ( $number < 10 ) {
unless ($video_results) {
$video_results = 1;
}
print "$cblack ";
}
print "$cblack$bred$number$reset$cblack - $byellow$title$reset"
. "$cblack (${bpurle}by $author$reset$cblack) "
. "($bblue$time$reset$cblack)$reset\n";
}
}
if ($playback) {
for ( $i = 1 ; $i <= $number ; ++$i ) {
push @picks, $i;
}
$playback_mode = 1;
&picks_area;
}
print "\n$bred=>>$reset$bgreen Insert a number or "
. "search something else\n$reset> ";
chomp( my $youtube = <STDIN> );
$PickBackup = $youtube;
if ( $youtube =~ /^(?:q|quit|exit)$/ ) {
exit;
}
elsif ( $PickBackup =~ m[^http://] and not $PickBackup =~ /youtube\.com/ ) {
&code_from_content($PickBackup);
}
elsif ( $PickBackup =~ /([\d]+) -([\w\s-]+)/ ) {
$youtube = $1;
$stdin_argvs = " -$2";
@options = split( m? ?, "-$2", 0 );
foreach $_ (@options) {
if ( $_ =~ /^[-]+(?:d|download)$/ ) {
$tmp_download_video = 1;
last;
}
}
}
if ( $youtube =~ /^\s*([\d]+)\s*$/ ) {
if ( $youtube > $number or not $youtube ) {
print "\n";
&print_results;
}
else {
&foreach_code($1);
}
}
elsif ( $youtube =~ /^\s*$/ ) {
&next_page;
}
elsif ( $youtube eq 'all' ) {
$stdin_argvs .= ' --1080 --play-all';
undef @picks if $#picks > -1;
for ( $i = 1 ; $i <= $number ; ++$i ) {
push @picks, $i;
}
&picks_area;
}
elsif ( $youtube =~ /view_play_list\?p=([A-Z0-9]+)/ ) {
&list_playlist($1);
}
elsif ( $youtube =~ m[(?:v|embed)[=/]+([\w-]{11})] ) {
&get_youtube($1);
}
elsif ( $youtube =~ /\d+[,\s]+\d+/ ) {
@picks = split( m?\D?, $youtube, 0 );
&picks_area;
}
else {
$Search = $youtube;
&search;
}
}
sub next_page {
$PageNumber = $FirstPage;
++$PageNumber;
if ($ys) {
if ( $ys =~ /index=([\d]+)/ ) {
$old_index = $1;
$start_index = $old_index + $results;
$ys =~ s/index=$old_index/index=$start_index/;
&parse_content($ys);
&print_results;
}
}
elsif ($yt_api_url) {
undef @Videos;
$ys = '';
if ( $yt_api_url =~ /index=([\d]+)/ ) {
$old_index = $1;
$start_index = $old_index + $results;
$yt_api_url =~ s/index=$old_index/index=$start_index/;
&parse_content($yt_api_url);
&print_results;
}
}
}
sub picks_area {
$NrOfPicks = scalar @picks;
$no = 0;
$lastpick = '';
&foreach_pick;
}
sub foreach_pick {
for ( $number = $no ; $number <= $NrOfPicks ; ++$number ) {
$no = $number;
$pick = $picks[$number];
if ($pick) {
next if $lastpick eq $pick;
}
if ( not $playback_mode ) {
&print_results if $number eq $NrOfPicks;
}
else {
&next_page if $number eq $NrOfPicks;
}
$Picks = 1;
$lastpick = $pick;
&foreach_code($pick);
}
}
sub foreach_code {
foreach $line (@codes) {
if ($debug) {
print "** FOREACHCODE: $line\n\n";
}
if (
$line =~ /^$_[0]>title=([^>]+)>published=([^>]+)>
category=([^>]+)>time=([^>]+)>code=([\w-]{11})
>views=([\d]*)>desc=([^>]+)>$/x
) {
my $description = decode_entities($7);
&get_youtube( $5, $1, $4, $6, $3, $2, $description );
}
}
}
sub select_resolution {
$streaming =~ s/^[\w]*%[\w]*http:/http:/;
if ( not $streaming =~ /itag=34/ and $streaming =~ /itag=([\d]+)/ ) {
my $itag = $1;
$streaming =~ s/.*http(.+)itag=$itag([^%]*).+/http$1itag=$itag$2/;
$streaming =~ s/%.*//;
unless ( $stdin_argvs =~ / -+f/ ) {
$MPlayerLine =~ s/-fs //;
}
&lower_cache;
&description;
&MPlayer;
}
elsif ( $stdin_argvs =~ / -+2/ ) {
&lower_quality(5);
&description;
&MPlayer;
}
elsif ( $stdin_argvs =~ / -+3/ ) {
&lower_quality(34);
&description;
&MPlayer;
}
elsif ( $stdin_argvs =~ / -+4/ ) {
&lower_quality;
&description;
&MPlayer;
}
elsif ( $stdin_argvs =~ / -+7/ ) {
if ( $streaming =~ /itag=22/ ) {
$streaming =~ s/.*http(.+)itag=22([^%]*).+/http$1itag=22$2/;
&fullscreen_check;
&description;
&MPlayer;
}
else {
&lower_quality;
&description;
&MPlayer;
}
}
elsif ( $stdin_argvs =~ / -+1/ ) {
if ( $streaming =~ /itag=37/ ) {
$streaming =~ s/.*http(.+)itag=37([^%]*).+/http$1itag=37$2/;
&fullscreen_check;
&description;
&MPlayer;
}
elsif ( $streaming =~ /itag=22/ ) {
$streaming =~ s/.*http(.+)itag=22([^%]*).+/http$1itag=22$2/;
&fullscreen_check;
&description;
&MPlayer;
}
else {
&lower_quality;
&description;
&MPlayer;
}
}
else {
&description;
&check_resolution;
}
}
sub format_time {
my $sec = shift @_ || return (0);
my $time = $sec / 3600 % 24 . ':' . $sec / 60 % 60 . ':' . $sec % 60;
$time =~ s/^0://;
unless ( $time =~ /:/ ) {
$time = "0:$time";
}
if ( $time =~ /(.):(.):(.+)/ ) {
$time = "$1:0$2:$3";
}
if ( $time =~ /^(.+):(.)$/ ) {
$time = "$1:0$2";
}
return $time;
}
sub description {
my ( $date, $rating );
if ( $connect->content =~ /rating average='([\d\.]+)'/ ) {
$rating = $1;
$rating =~ s/^([\d\.]{4}).*/$1/;
}
elsif ( $connect->content =~ /avg_rating=([^&]+)/ ) {
$rating = $1;
$rating =~ s/^([\d\.]{4}).*/$1/;
}
unless ($title) {
my $feed_url = 'http://gdata.youtube.com/feeds/api/videos/' . $code;
my $content = $lwp->get($feed_url)->content;
if ( $content =~ m[media:title type='plain'>([^<]+)</media:title>] ) {
$title = decode_entities($1);
}
if ( $content =~ /viewCount='([\d]+)'/ ) {
$views = $1;
}
if ( $content =~ /<published>([\d-]+)/ ) {
$date = $1;
$date =~ s/-/./g;
$date =~ s/(.+)\.(.+)\.(.+)/$3.$2.$1/;
}
if ( $content =~ m[<media:description type='plain'>([^<]+)</media] ) {
$description = decode_entities($1);
}
if ( $content =~ /duration[^\d]+(\d+)/ ) {
$duration = format_time($1);
}
if ( $content =~ /category label='([^']+)'/ ) {
$category = $1;
$category =~ s/&/&/;
}
}
if ( not $date and $published ) {
$date = $published;
$date =~ s/-/./g;
$date =~ s/(.+)\.(.+)\.(.+)/$3.$2.$1/;
}
if ($views) {
$views = reverse($views);
$views =~ s/([\d]{3})/$1./g;
$views = reverse($views);
$views =~ s/^\.//;
}
if ($description) {
print "\n$bred=>> " . $bgreen . $title . $reset . "\n" . '-' x 80;
print "\n" . $description . "\n" . '-' x 80 . "\n";
}
else {
print "\n";
}
print "$bred=>> ${bgreen}View & Download$reset\n" . '-' x 80;
my $get = $1 if $streaming =~ m[((http://)[^%]+)];
print "\n* URL $url\n* GET $get\n" . '-' x 80 . "\n";
my $count = length $title;
if ( $count <= 40 ) {
print "$bred\t\t=>> ";
}
elsif ( $count >= 40 and $count <= 55 ) {
print "$bred\t=>> ";
}
elsif ( $count >= 56 ) {
print "$bred =>> ";
}
print "$bgreen$title$reset$bred <<=\n$reset";
my $author = $1 if $connect->content =~ /&author=([^&]+)/;
print "\n** Author : $author\n" if $author;
print "** Category : $category\n" if $category;
print "** Duration : $duration\n" if $duration;
print "** Rating : $rating\n" if $rating;
print "** Views : $views\n" if $views;
print "** Published : $date\n" if $date;
print '-' x 80 . "\n\n";
}
sub get_youtube {
( $code, $title, $duration, $views, $category, $published, $description ) =
@_;
undef @_;
my $youtube = "http://www.youtube.com/get_video_info?&video_id=$code"
. '&el=detailpage&ps=default&eurl=&gl=US&hl=en';
unless ($lwp_is_set) {
&UserAgent;
}
$connect = $lwp->get($youtube);
$url = "http://www.youtube.com/watch?v=$code";
$MPlayerLine =~ s/ $mplayer_srt_settings -sub.*//;
if ( $ENV{'PATH'} ) {
@paths = split( m?:?, $ENV{'PATH'}, 0 );
foreach my $path (@paths) {
if ( -e "$path/gcap" ) {
$gcap = "$path/gcap";
last;
}
}
}
else {
$gcap = '/usr/bin/gcap';
}
if ( -e $gcap
and not $MPlayerLine =~ / -novideo/
and $connect->content =~ /&has_cc=True&/
and not $download_video
and not $tmp_download_video ) {
chdir '/tmp/';
print "\n";
system "gcap $url" unless -e "${code}_$default_sub.srt";
my (@srt_files) = glob('*.srt');
undef $srt_file if $srt_file;
foreach $line (@srt_files) {
if ( $line =~ /${code}_$default_sub\.srt/ ) {
$srt_file = "${code}_$default_sub.srt";
$MPlayerLine .= " $mplayer_srt_settings -sub $srt_file";
}
}
unless ($srt_file) {
foreach $line (@srt_files) {
if ( $line =~ /$code([\w]*)\.srt/ ) {
$srt_file = "$code$1.srt";
$MPlayerLine .= " $mplayer_srt_settings -sub $srt_file";
}
}
}
}
print "\n\n" . uri_unescape( $connect->content ) . "\n\n" if $debug;
if ( $connect->content =~ /fmt_url_map=([^&]+)&/ ) {
$streaming = $1;
$streaming =~ s/%3A/:/gi;
$streaming =~ s[%2F][/]gi;
$streaming =~ s/%26/&/g;
$streaming =~ s/%3D/=/gi;
$streaming =~ s/%3F/?/gi;
$streaming =~ s/%252C/,/gi;
&select_resolution;
}
else {
warn "\n$bred(x_x) Something went wrong...$reset\n\n";
warn "$bred(x_x) Unable to stream: $reset$url\n\n";
if ( $video_results and not $dont_exit ) {
unless ( $stdin_argvs =~ / -+(?:all|A|play-all)/ or $NrOfPicks ) {
sleep 1;
&print_results;
}
}
else {
unless ( $video_results or $dont_exit ) {
exit;
}
}
}
}
sub check_resolution {
if ( $streaming =~ /itag=37/ and not $stdin_argvs =~ / -+(?:all|A)/ ) {
&pick;
}
elsif ( $stdin_argvs =~ / -+(?:all|A)/ ) {
if ( $streaming =~ /itag=37/ ) {
$streaming =~ s/.*http(.+)itag=37([^%]*).+/http$1itag=37$2/;
&default_cache;
&fullscreen_check;
&description;
&MPlayer;
}
}
elsif ( $streaming =~ /itag=22/ ) {
$streaming =~ s/.*http(.+)itag=22([^%]*).+/http$1itag=22$2/;
&default_cache;
&fullscreen_check;
&MPlayer;
}
else {
&lower_quality;
&MPlayer;
}
}
sub fullscreen_check {
$MPlayerLine =~ s/mplayer -p/mplayer -fs -p/;
$MPlayerLine =~ s/mplayer.exe" -p/mplayer.exe" -fs -p/;
}
sub pick {
print "$bred=>>$reset $bgreen Please choose "
. 'the quality of video (default: 1)';
print "\n$reset";
print "\n $bred 1$reset - 1280x720 (720p)\n"
. " $bred 2$reset - 1920x1080 (1080p)\n ";
print '=' x 23 . "\n";
print "\n$bgreen=>> Pick format:$reset ";
chomp( my $pick = <STDIN> );
print '-' x 80 . "\n\n";
if ( $pick eq 2 ) {
$streaming =~ s/.*http(.+)itag=37([^%]*).+/http$1itag=37$2/;
&default_cache;
&fullscreen_check;
&MPlayer;
}
else {
$streaming =~ s/.*http(.+)itag=22([^%]*).+/http$1itag=22$2/;
&default_cache;
&fullscreen_check;
&MPlayer;
}
}
sub lower_quality {
if ( $_[0] and $_[0] =~ /^\d+$/ ) {
if ( $streaming =~ /itag=$_[0]/ ) {
$streaming =~ s/.*http(.+)itag=$_[0]([^%]*).*/http$1itag=$_[0]$2/;
&lower_cache;
}
}
else {
foreach $_ ( 35, 34 ) {
if ( $streaming =~ /itag=$_/ ) {
$streaming =~ s/.*http(.+)itag=$_([^%]*).*/http$1itag=$_$2/;
&lower_cache;
last;
}
}
}
unless ( $stdin_argvs =~ / -+f/ ) {
$MPlayerLine =~ s/-fs //;
}
}
sub lower_cache {
$MPlayerLine =~ s/-cache\s*\d+/-cache 1000/ unless $user_cache;
$MPlayerLine =~ s/-cache-min\s*\d+/-cache-min 3/ unless $user_cache_min;
}
sub default_cache {
if ( not $user_lower_cache ) {
$MPlayerLine =~ s/-cache\s*\d+/-cache $cache/ unless $user_cache;
$MPlayerLine =~ s/-cache-min\s*\d+/-cache-min $cache_min/
unless $user_cache_min;
}
else {
&lower_cache;
}
}
Comments
Sorry but there are no comments to display