YouTube View — скрипт для просмотра видео без Flash

7 февраля 2011

Мне не нравится Flash. Очень не нравится. Потому что ничего полезного, кроме баннеров и игр, на нем не делают. Потому что Adobe не беспокоится о выпуске флэш-плагина для 64-х разрядных браузеров. К тому же, все мы прекрасно знаем, насколько он дырявый и тормознутый.

Недавно я попробовал установить Flash, и инстяллятор за каким-то хреном дополнительно установил мне антивирус McAfee. Даже не пытаясь попросить у меня разрешения. Просто взял и поставил! Хотя, в общем-то, понятно за каким хреном он это сделал. Должна же Adobe на чем-то зарабатывать?

Гуру юзабилити Якоб Нильсен пишет о Flash следующее:

About 99% of the time, the presence of Flash on a website constitutes a usability disease.

И самое главное — все, что умеет Flash, можно реализовать средствами HTML5 и jQuery! Нужно отдать ему должное, благодаря флэшу (по крайней мере, точно не без его помощи) сегодня мы имеем потоковое видео и аудио в сети. Но никто же не пользуется Mosaic, просто потому что он был первым графическим браузером?

Понимая вышесказанное и силу открытых технологий, Google ведет работы по внедрению HTML5 на YouTube. К сожалению, релиз Firefox под номером 4 еще не состоялся, а переходить на Оперу только ради Ютуба как-то не хочется. Я мог бы смотреть видео с помощью Flash, но под любимой FreeBSD для этого нужно прибегнуть к использованию linux_base.

Честно говоря, меня в последнее время мало волнует, ставлю я программу, использующую QT или GTK, нужен ли ей для работы linux_base или не нужен. Главное — чтобы работало. Но, в силу старой привычки, наверное, я предпочел написать небольшой скрипт для скачивания и просмотра видео.

#!/usr/bin/perl
# YouTube View Script v 0.9.8
# (c) Alexandr A Alexeev 2011 | http://eax.me/

use strict;

use constant VERSION => "0.9.8";
# куда сохраняем ролики (слэш на конце!)
use constant DEFAULT_PATH => '/tmp/';
# удаляем после просмотра?
use constant DEFAULT_DELETE => 1;
use List::MoreUtils qw/uniq/;
use utf8;

#### проверяем наличие всех необходимых утилит ####
{
  my @depends = qw/date wget mplayer youtube-dl/;
  my $not_found;
  for(@depends) {
    print "ERROR: $_ not found" and ++$not_found
      if system("which $_ > /dev/null");
  }
  exit 1 if $not_found;
}

my $url = shift;
$url =~ s/(^\s+|\s+$)//g;
die "YouTube View Script ver ".VERSION.
  "\nUsage:\n$0 <url>\n$0 --dialog\n" unless($url);

if($url eq "--dialog") {
  print "Dialog mode, enter url(s) or 'exit'\nytview> ";
  while($url = <STDIN>) {
    chomp($url);
    if(length($url)) {
      last if(("\L$url" eq "exit")or("\L$url" eq "quit"));
      $url =~ s/'/\'/g;
      system("$0 '$url'") unless($url eq "--dialog");
      print "\n";
    }
    print "ytview> ";
  }
  exit;
}

my $delete = $ENV{YOUTUBE_VIEW_DELETE};
$delete = DEFAULT_DELETE unless(defined($delete));

my $path = $ENV{YOUTUBE_VIEW_PATH};
$path = DEFAULT_PATH unless(defined($path));

print qq{
delete = $delete
path = $path
};

my @ids;
my $data;
my $q_url = $url;
$q_url =~ s/'/\'/g;

if($url =~ m#^(?:https?://)?(?:www\.)?(?:youtube\.com/watch\?v=|youtu\.be/)([^\&]+)#i) {
  # некоторое видео (например, с пометкой 18+) может требовать
  # от пользователя авторизации. youtube-dl успешно это обходит
  # так что если ссылка прямо на ролик, не нужно ничего скачивать
  push @ids, $1;
} else {
  # скачиваем веб-страничку
  print "Downloading $url...\n";
  $data = `wget -q '$q_url' -O -`;

  if(my @ljurls = $data =~ /(http:\/\/(?:www\.)?lj-toys\.com\/[^'" ]+)/ig) {
    print "LJ Toys detected, ".scalar(@ljurls)." frames found...\n";
    $data = "";
    for my $url(@ljurls) {
      $url =~ s/&amp;/&/gi;
      print "url = $url\n";
      $data .= `wget -q '$url' -O -`;
    }
  }

  # пытаемся выдрать из нее id ролика (роликов?)
  @ids = $data =~ /http:\/\/(?:www\.)?youtube\.com\/(?:watch)?\??(?:v|video|embed)(?:=|\/)([a-zA-Z0-9\-\_]+)/gi;
  @ids = uniq @ids;
}

my $id;
# сколько роликов на странице?
if((scalar @ids <= 1)or($url =~ /(http:\/\/)?(www\.)?youtu(\.be|be\.com)\//i)) {
  $id = $ids[0];
} else {
  # на странице более одного ролика
  # выводим их id и названия, выбор должен сделать юзер
  my $n;
  print "\nIt was found more than one video:\n";
  for my $vid(@ids) {
    $data = `wget -q 'http://youtu.be/$vid' -O -`;
    utf8::decode($data);
    my ($title) = $data =~ /<meta name="title" content="([^"]+)">/;
    $title = "Undefined title" unless $title;
    $title = substr($title, 0, 30)."..."
      if length($title) > 32;
    utf8::encode($title);
    print $n++.". $vid :: $title\n";
  }

  while($n > $#ids) {
    print "Your choice (0..$#ids): ";
    chomp($n = <STDIN>);
    $n = scalar @ids unless($n =~ /^[0-9]+$/);
  }

  $id = $ids[$n];

  unless($id) {
    die "Failed to parse $url\n".
        "wget returns $?\n".
        "length(\$data) = ".length($data)."\n";
  }
}
print "id = $id, downloading video...\n";
# имя файла для воспроизведения
my $fname;

# проверяем наличие ролика в кэше
my $cached_found = 0;
if(!$delete) {
  my @flist = glob "$path*.flv";
  for my $curr_fname (@flist) {
    if($curr_fname =~ /\d{4}-\d{2}-\d{2}-([a-z0-9_-]+)\.flv$/i) {
      if($1 eq $id) {
        $fname = $curr_fname;
        $cached_found = 1;
        print "Found cached file: $fname\n";
        last;
      }
    }
  }
}

# скачиваем видео с помощью youtube-dl
if(!$cached_found) {
  chomp(my $date = `date +%Y-%m-%d`);
  $fname = "$path$date-$id.flv";
  print "fname = $fname\n";

  system("youtube-dl 'http://youtube.com/watch?v=$id' -o $fname");
  if($?) {
    unlink "$fname.part";
    die "youtube-dl returns $?\n"
  }
  print "done!\n";
}

# запускаем проигрыватель
system("mplayer -zoom $fname");
print qq{
EMBED CODE:
--------8<--------8<--------
<iframe class="youtube-player" type="text/html"
  width="640" height="385"
  src="http://www.youtube.com/embed/$id" frameborder="0">
</iframe>
<div style="font-size: 0.8em">Posted via <a href="http://eax.me/youtube-view/">YouTube View</a> script.</div>
--------8<--------8<--------
SHORT LINK: http://youtu.be/$id
};
unlink $fname if $delete;

Идея простая — берем код страницы, содержащей видео, и выдираем из нее ID ролика. Затем скачиваем этот ролик с помощью youtube-dl (/usr/ports/www/youtube_dl) и просматриваем в mplayer. Плюс к этому, скрипт выводит embed-код и короткую ссылку на видео (http://youtu.be/…). Есть возможность работать со страницами, содержащими несколько роликов.

По умолчанию видео сохраняется скриптом в каталог /tmp и удаляется после просмотра. Изменить такое поведение можно с помощью переменных окружения:

# кусок моего ~/.bashrc

# алиас к скрипту
alias ytview="~/scripts/perl/ytview.pl"
# не удаляем ролики после просмотра
export YOUTUBE_VIEW_DELETE=0
# каталог для сохранения роликов (слэш на конце!)
export YOUTUBE_VIEW_PATH=~/nodump/youtube/

Мне такое решение нравится намного больше, чем скачивание пол-линукса и установка флэш-плагина. Костыль, конечно, но поможет дождаться повсеместного внедрения HTML5 Video. Надеюсь, вам этот скрипт тоже пригодится.

Дополнение: Также вас могут заинтересовать скрипты для загрузки видео с RuTube и Vimeo.com, а также для скачивания mp3 из ВКонтакта.

Метки: .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.