4/16/2012

Cкачать кешированное видео youtube из браузера в стиле UNIX

Испорченные мышекликанием пользователи считают, как тот программист из UNIX коанов мастера Фу, что "средства командной строки UNIX грубые и отсталые - современные правильно спроектированные операционные системы делают все через графический интерфейс пользователя". Однако время, потраченное на изучение того, как работает UNIX под этой графической мишурой, окупается сторицей при решении повседневных задач быстрее и эффективнее мышекликания.

Эта заметка появилась из вопроса, заданного мне местным убунтушником, который никак не мог скачать видеолекции с YouTube: в Firefox плагин VideoDownloader не срабатывал по какой-то причине, как и скрипт youtube-dl. То есть видео закешировано, в броузере играет и поёт, но скопировать его в файл из броузера не получается. Здесь нам на помощь придёт файловая система proc и тот замечательный факт, что удалённый файл реально удаляется только после того, как он закрыт всеми приложениями, его использующими.


Вытаскивание кешированнго YouTube видео из-под Firefox

Для самых нетерпеливых, собственно, рецепт:

1. Заходим на YouTube, кликаем на интересующее видео и ждём, пока оно полностью загрузится.

2. В консоли запрашиваем список всех открытых видеороликов Flash:
$ lsof -n | grep Flash
Старые версии Firefox просто хранят кешированное видео в директории /tmp
и в этом случае видео можно просто скопировать. В этом случае вы увидите что-то вроде:
beast@notebeast:~/docs/mygtd$ lsof -n | grep Flash
plugin-co 6231 beast 15u REG 3,2 1938773 1746302 /tmp/FlasheY4skF
С обновлённым флеш-плагином этого не будет, а будет вот что:
beast@notebeast:~/docs/mygtd$ lsof -n | grep Flash
plugin-co 6231 beast 15u REG 3,2 1938773 1746302 /tmp/FlasheY4skF (deleted)
И ничего в /tmp мы, натурально, не найдём. Но файл всё-таки есть, так как в броузере он поёт, а значит, к нему в Linux можно добраться.

3. Запоминаем идентификатор процесса (в нашем случае 6231), который открыл вожделенное видео с утуба, и в консоли переходим в директорию /proc

Тут мы видим кучу подкаталогов с цифрами и странными названиями - нас интересует директория 6231 и она, как выясняется, не пуста. Переходим в подкаталог:
$ cd /proc/6231/fd
и после этого пытаемся просмотреть все файлы там:
$ ls -l
и увидим что-то вроде:

beast@notebeast:/proc/6231/fd$ ls -l
итого 0
lr-x------ 1 beast beast 64 2012-03-03 10:04 0 -> /dev/null
l-wx------ 1 beast beast 64 2012-03-03 10:04 1 -> /home/beast/.xsession-errors
lrwx------ 1 beast beast 64 2012-03-03 10:04 10 -> socket:[15270]
lrwx------ 1 beast beast 64 2012-03-03 10:04 11 -> socket:[15271]
lr-x------ 1 beast beast 64 2012-03-03 10:04 12 -> pipe:[15272]
l-wx------ 1 beast beast 64 2012-03-03 10:04 13 -> pipe:[15272]
lrwx------ 1 beast beast 64 2012-03-03 10:04 14 -> socket:[15284]
lrwx------ 1 beast beast 64 2012-03-03 10:04 15 -> /tmp/FlasheY4skF (deleted)
lr-x------ 1 beast beast 64 2012-03-03 10:04 16 -> /dev/snd/timer
lrwx------ 1 beast beast 64 2012-03-03 10:04 17 -> /dev/snd/pcmC0D0p
lrwx------ 1 beast beast 64 2012-03-03 10:04 18 -> /dev/snd/controlC0
l-wx------ 1 beast beast 64 2012-03-03 10:04 2 -> /home/beast/.xsession-errors
lrwx------ 1 beast beast 64 2012-03-03 10:04 3 -> socket:[15182]
lrwx------ 1 beast beast 64 2012-03-03 10:04 4 -> socket:[15183]
lr-x------ 1 beast beast 64 2012-03-03 10:04 5 -> pipe:[15268]
l-wx------ 1 beast beast 64 2012-03-03 10:04 6 -> pipe:[15268]
lr-x------ 1 beast beast 64 2012-03-03 10:04 7 -> pipe:[15269]
l-wx------ 1 beast beast 64 2012-03-03 10:04 8 -> pipe:[15269]
lrwx------ 1 beast beast 64 2012-03-03 10:04 9 -> anon_inode:[eventpoll]

4. Оказывается, что в директории /proc лежит наше вожделенное видео, только вместо имени там стоит номер, в данном случае 15 который указывает на видеофайл:

15 -> /tmp/FlasheY4skF (deleted)
Так как в UNIX действует принцип всё есть файл, мы просто копируем файл 15 в свою домашнюю директорию:
$ cp 15 ~/myNewCoolGreatFlashYouTubevideo.flv
Всё, теперь видео с тюбика в наших руках, и можно делать с ним всё, что душе угодно, в цветастом и мышастом Гноме (точнее, теперь уже Юнити).


Как это работает
После запуска, каждый процесс (и его подпроцессы) получает индетификатор (PID), при этом в каталоге /proc создаётся подкаталог с номером, соответствующем номеру PID вроде /proc/PID. Внутри создаются файлы и подкаталоги, которые содержат информацию о процессе. Вот ей-то мы и воспользовались в своих корыстных целях.

Среди прочего, о чём можно узнать из обновлённого поста о proc или другой документации, нас интересует каталог /proc/PID/fd. Этот каталог содержит символическую ссылку для дескрипторов файлов, которые открыты процессом. Это значит, что мы можем увидеть здесь ссылки на открытые файлы и устройства.

Внутри мы видим ссылки в виде номеров:
0 1 10 11 12 13 2 3 4 5 6 7 8 9,
но команда ls -l скажет вам намного больше интересного (об этом было выше). Ключевая строчка:

lrwx------ 1 beast beast 64 2012-03-03 10:04 15 -> /tmp/FlasheY4skF (deleted)

Ссылка 15 ведёт на файл с флеш-видео, который сейчас открыт. Помня, что в UNIX всё есть файл, мы скопируем ссылку 15 в свой домашний каталог. Только вместо ссылки копируется её содержимое. Ларчик открывается сравнительно просто, если знать как.


Заключение и выводы
На самом деле, подобные вопросы в процессе работы как раз и позволяют глубже понять принципы работы операционной системы, а не просто клацать мышкой по кнопкам. Тем более, что настоящая мощь UNIX как раз и находится под всей этой графической мишурой.

Главная проблема пользователей Windows-like дистрибутивов (Ubuntu, OpenSUSE, Fedora...) в том, что они тащят свои дурные привычки из Windows, которые в Linux\UNIX не позволяют добиться желаемого. Разница - в подходе ко взаимодействию системы и пользователя:
  • В UNIX схема работы ``от понимания - к действию'': чтобы что-то сделать, надо понимать (или хотя бы смутно догадываться), как оно устроено.
  • В Windows схема работы ``методом тыка'' (буквально): знаю КАК что-то сделать (куда нажать, какую галочку отметить) -> делаю.
Понимание устройства файловой системы в данном конкретном случае - ключ к решению проблемы. Но Windows-ориентированные дистрибутивы этому не способствуют. Никакого рокетсаенса в приведённом пример, конечно, нет, но тем не менее.

Эта заметка так же сподвигла автора обновить старый пост о /proc, немного почитать документацию, поработать Капитаном Очевидностью на полставки и, как говаривал Эркюль Пуаро, напрячь свои маленькие серые клеточки.

21 комментарий:

  1. Браво, Михаил! "Заумные" вещи расписаны довольно просто и понятно.

    в Firefox плагин VideoDownloader не срабатывал по какой-то причине
    Юзаю DownloadHelper, срабатывает всегда, видео до конца смотреть не нужно, достаточно всего пары секунд.

    Несколько багфиксов: "Заключение и выводы" написаны вплотную к последующему тексту. Ну и кавычки везде ''такие", как будто только что из ЛаТеХа :-)

    И да, по поводу социальных кнопок. Ждал я, пока Вы сами уберёте кнопку давным-давно закрытого Buzz'а, а не убрали... И от мемориза знак подчёркивания вылез за картинку.
    Кстати, не знаю, как там у Вас в Австралии, но в России последнее время набирает популярность сервис Surfingbird.ru. Мне кажется, что для лучшей популяризации контента стоит добавить эту кнопочку на сайт

    ОтветитьУдалить
  2. Изменить по вкусу

    #!/bin/bash

    strs=$(ps -eo pid,args | grep 'libflash' | grep -v grep | awk '{print $1}')
    PIDS="$strs"

    movs=''
    for i in $PIDS; do
    movs="$movs $(ls -l /proc/$i/fd | grep Flash | awk '{print $9}')"
    done

    echo $movs

    for mov in $movs;
    do
    for PID in $PIDS; do
    mplayer -idx /proc/$PID/fd/$mov ;
    done
    done

    ОтветитьУдалить
  3. Спасибо большое. Просто очень полезная информация. Я и раньше извлекал много чего интересного из /proc, но а теперь вот случайно узнал про расположение файловых дескрипторов.

    ОтветитьУдалить
  4. Отличный тру подход к решению задачи. Спасибо.

    На будущее если хотите скачать ролик с ютюба просто добавте две буквы s перед youtube , т.е. www.youtube.com/?foo=bar замените на www.ssyoutube.com/?foo=bar и будет Вам счастье.

    ОтветитьУдалить
  5. все думал как же на практике lsof можно применить. доходчиво.

    может пригодится моя библиотечка на джаве для скачивания с ютуба https://github.com/axet/vget

    ОтветитьУдалить
  6. А можно сделать проще, перед URL с видео на youtube набрать слово kick (получится kickyoutube.....) и скачать в удобном формате. Раньше сразу был выбор, теперь немного рекламы прикрутили.

    ОтветитьУдалить
  7. не подскажете, как скачать, к примеру, это видео?

    http://www.youtube.com/watch?v=uB80gnsWNfw

    ОтветитьУдалить
  8. Это просто суперпост!!! Я восхищен, насколько просто, круто и юниксвейно можно сделать эту операцию (хотя у меня DownloadHelper на Firefox обычно справляется с подобной задачей). Спасибо автору за подробной разъяснение "сути процесса".

    ОтветитьУдалить
  9. А почему бы не вернуть старое поведение флешплеера, когда он оставлял файлы в /tmp ? Я так и сделал, довольно удобно. Единственный минус — нужно добавлять LD_PRELOAD в скрипт запуска браузера каждый раз после обновления.

    ОтветитьУдалить
  10. >не подскажете, как скачать, к примеру, это видео?
    >youtube.com/watch?v=uB80gnsWNfw | youtube.com/watch?v=jaj6BtCf_XA

    и другие с "мосфильма" приведенными методами не обнаруживаются... что подскажут знатоки?

    ОтветитьУдалить
  11. А вот так их можно сразу проигрывать в mplayer с усилением звука:

    #!/bin/bash

    lsof -n | grep /tmp/Flash | awk '{line = "/proc/" $2 "/fd/" $4; sub("[^0-9]*$","",line); print line}' | xargs mplayer -softvol-max 1000

    # http://habrahabr.ru/post/134385/

    ОтветитьУдалить
  12. > и другие с "мосфильма" приведенными методами не обнаруживаются... что подскажут знатоки?

    rtmpdump, есть скринкаст: http://www.youtube.com/watch?v=8PuUnQCS7DQ

    ОтветитьУдалить
  13. В свое время делал себе скриптик для этого по тем же методам. :)

    http://ollycat.blogspot.com/2011/04/youtube.html

    Не претендует на оптимальность, так как писался быстро и на коленке ибо надо было "здесь и сейчас", но свое дело делает до сих пор. :)

    ОтветитьУдалить
  14. @Vlsu комментирует...
    Браво, Михаил! "Заумные" вещи расписаны довольно просто и понятно.
    Да ладно, вещи в самом деле простые. Когда пытаешься что-то объяснить другим, лучше понимаешь сам, про что речь.

    DownloadHelper, срабатывает всегда
    Шут его знает. Не сработал. Но дело не в этом - всегда полезно знать, как что-то работает на самом деле.

    Несколько багфиксов
    Конечно!

    "Заключение и выводы" написаны вплотную к последующему тексту.
    Привет обновлённой форме Блоггера. Она косяково обрабатывает переезды на другую строку. Исправлено.

    Ну и кавычки везде ''такие", как будто только что из ЛаТеХа
    Они-то как раз православные ;-)

    Ждал я, пока Вы сами уберёте кнопку давным-давно закрытого Buzz'а
    Всё течёт, всё меняется. Убрал, спасибо.

    Кстати, не знаю, как там у Вас в Австралии, но в России последнее время набирает популярность сервис Surfingbird.ru
    Попробую. Занёс в блокнотик для улучшений.
    Тут в Австралии рулит del.icio.us - делишес, одно слово, и stumbleupon ещё слышал пользуется популярностью.

    стоит добавить эту кнопочку на сайт
    Vlsu, я вот тут думаю, как бы мне модернизировать эти кнопки. Всюду советуют всякие приблуды на джаваскрипте, но у меня на джаву аллергия. Есть решение?


    @Анонимный комментирует...
    Изменить по вкусу
    Изящно. Но это скрипт надо писать, а тут оно парой команд. Тем не менее, мерси боку. Спасибо, то есть.


    @Олег Мороз комментирует...
    Спасибо большое. Просто очень полезная информация. Я и раньше извлекал много чего интересного из /proc
    Да не за что. Кстати, вообще этот пост - типа заглушки. На самом деле, пост про /proc, и он сильно обновлён - фактически, переписан заново.

    Кстати, скоро будет пост про другую псевдо-файловую систему, оставайтесь на волне.


    @makov комментирует...
    На будущее если хотите скачать ролик с ютюба просто добавте две буквы s перед youtube
    Описанный подход юниксвейнее, так как не завязан на тюбик.


    @Alexey Kuznetsov комментирует...
    все думал как же на практике lsof можно применить. доходчиво.
    О, ну как же - куча полезных применений. Можно посмотреть, кто держит флешку и не даёт её отмонтировать. Можно посмотреть, какие файлы открыты программой. Ещё TCP-соединения можно глянуть.

    @Алексей Плутахин комментирует...
    А можно сделать проще, перед URL с видео на youtube набрать слово kick
    Забавно. Алексей, но оно только для ютуба, а если видео играет откуда ещё?

    ОтветитьУдалить
  15. @xgsa комментирует...
    Это просто суперпост
    Ай ладно. Суперпост был про proc, вот на него я действительно кучу времени угрохал. Думал всё написать в этом посте, но потом перекроил старый пост, а здесь оставил только нужно.

    Я восхищен, насколько просто, круто и юниксвейно можно сделать эту операцию
    На самом деле, это вполне себе юниксвейный подход, основанный на понимании того, как на самом деле работает весь этот техноливер под линуксовым капотом.


    @Анонимный комментирует...
    А почему бы не вернуть старое поведение флешплеера, когда он оставлял файлы в /tmp ?
    Анонимус, а как это сделать? Просто я не в теме.
    Мне проще в консоли написать пару команд :-)


    @GiNeR комментирует...
    А вот так их можно сразу проигрывать в mplayer с усилением звука
    О, здорово! Про -softvol-max честно не знал. Надо бы добавить в пост про mplayer...


    @Oleg Adianov комментирует...
    В свое время делал себе скриптик для этого по тем же методам.
    Ну да, дело-то не сложное.

    Кстати, Олег, зря забросили блог.


    @хЕромант комментирует...
    Красная карточка за хамство - комментарий удалён. Выбирай выражения.

    Кстати, напоминаю:
    1. это не дебианвики.
    2. это мой личный блог, и я сюда пишу то, что считаю нужным написать.
    3. мнение автора может не совпадать с мнением херомантов и анонимусов.


    @despicere комментирует...
    Спасибо автору за хороший пост и комментаторам со скриптами :)
    Пожалуйста.

    Да, тут к автору знатная железяка приехала, так что скоро будет много красноглазия, напилинга, олдскулинга, а так же секса и насилия :-) Оставайтесь на этой волне.

    ОтветитьУдалить
  16. @virens
    всегда полезно знать, как что-то работает на самом деле.
    Несомненно, особенно когда речь заходит о строении и взаимодействии с ядром

    Всюду советуют всякие приблуды на джаваскрипте
    Они, кстати, неплохи. К себе в блог залепил с AddThis.com. Сервис имеет неплохую приборную панель, что позволяет вычислить то, какими сервисами пользуются посетители. Однако скорость загрузки страниц страдает, иногда даже слишком...

    у меня на джаву аллергия. Есть решение?
    Ууу, с такой "болячкой" в эпоху вебдваноля наверняка трудно жить. Могу посоветовать только заменить гугл+ на вариант без скрипта:

    <a expr:href='&quot;https://plus.google.com/share?url=&quot; + data:post.url' style="background: url(http://ssl.gstatic.com/s2/oz/images/stars/po/Publisher/sprite4-a67f741843ffc4220554c34bd01bb0bb.png) no-repeat 0 -720px; width: 33px; height: 20px; display: inline-block;">&amp;nbsp;</a>

    При нажатии на такую кнопку сработает +1 и отправит на страницу с предложением поделиться контентом в Google+.

    тут к автору знатная железяка приехала
    Заинтриговали... Будем ждать!

    ОтветитьУдалить
  17. @virens комментирует...

    Анонимус, а как это сделать? Просто я не в теме.

    Примерно вот так: http://www.linux.org.ru/forum/talks/6240949

    ОтветитьУдалить
  18. @Vlsu комментирует...
    Они, кстати, неплохи. К себе в блог залепил с AddThis.com.
    Вот оно-то и не нравится мне. Там слишком много всего. С кнопками проще - нажал и получил, что хотел. В этом АддЗыс нету гуглплюсадын, а она очень даже нужна.

    Однако скорость загрузки страниц страдает, иногда даже слишком...
    Дык джаваскрипт же - что он ещё умеет?!
    Хочется что-нибудь простое и работящее.

    Отвлекаясь от темы поста: меня исключительно бесят современные вебдванольномолодёжные мегапорталы, перегруженные джавой и флешем. Ради одной такой дуры нужно выкачивать пару мегабайт и ждать полчаса, пока мой старый ламповый ноутбук с Этчем прочихается свопом. Поэтому у себя на блоге я стараюсь всё делать просто и дубово (но чтобы симпатично) - поэтому загружается всего 300 Кб и работает быстро, не тормозя отрисовку.

    Ууу, с такой "болячкой" в эпоху вебдваноля наверняка трудно жить.
    В гробу я этот вебдваноль видал, я вам вот что скажу. Грёбаный браузер жрёт памяти больше, чем ОпенОфис с ядром, и ещё требует аппаратного ускорения. На сайты ходят за контентом, а не за джаваскриптовыми мигалками.

    Могу посоветовать только заменить гугл+ на вариант без скрипта
    О, спасибо. Попробуем.

    @Анонимный комментирует...
    Примерно вот так
    ОК, глянем при оказии.

    Да, возвращаясь к теме поста - если у кого возникнет желание прильнуть к посту про proc, то комментарии к тому посту очень даже приветствуются.

    Уиз бест регардс и всё такое.

    ОтветитьУдалить
  19. Если не затруднить, можно ли расширить статью или в комментариях подсказать, как с rutube.ru посмотреть видео через mplayer и скачать при необходимости? Там по rtmp видео раздают и оно как-то в proc не попадает или я что-то не так делаю...

    ОтветитьУдалить
  20. Увы не актуально для версии Firefox 12.

    insider@work:~/$ lsof -n | grep -i flash
    firefox 1988 insider mem REG 8,7 126152 3179485 /usr/lib64/mozilla/plugins-wrapped/nswrapper_64_64.libflashplayer.so
    npviewer. 3256 insider mem REG 8,7 19216752 3360838 /usr/lib64/flash-plugin/libflashplayer.so
    chrome 4295 insider mem REG 8,7 19216752 3360838 /usr/lib64/flash-plugin/libflashplayer.so

    ОтветитьУдалить
  21. пкределанный mozz


    #!/bin/bash

    # mozz - a name easily typed :P
    # Find cached flash video and copy to user's home directory
    # 31 October 2011


    # Check for given filename
    #if [ $# -ne 1 ]; then
    #echo "Usage: mozz [filename]"
    #exit 65
    #fi

    # Make sure we have lsof
    if [ -x /usr/sbin/lsof ]; then
    LSOF=/usr/sbin/lsof
    elif [ -x /usr/bin/lsof ]; then
    LSOF=/usr/bin/lsof
    elif [ -x /usr/local/bin/lsof ]; then
    LSOF=/usr/local/bin/lsof
    else
    echo "lsof was not found... exiting"
    exit 1
    fi

    # Look for flvs in user's home - if not, create one
    #if [ ! -d $HOME/flvs ]; then
    #echo -e "\033[0;31mCreating " $HOME"/flvs"
    #mkdir -v $HOME"/flvs"
    #fi

    # Find a process ID and go there
    PROCDIR=$( $LSOF -X | grep Flash | tail -n1 | awk '{ print $2 }' )

    # Not found? exit gracefully
    if [ "$PROCDIR" == "" ]; then
    echo "No running instance found"
    exit 1
    fi

    # To warn us if nothing happens
    flvflag=0

    # Stat through FDs and copy the first
    for i in /proc/$PROCDIR/fd/*; do
    j=$( stat $i | head -n1 | grep "tmp/Flash")

    if [ ${#j} -gt 0 ]; then
    k=$( echo $j | awk '{ print $2 }' )
    l=${k#?}
    m=$( dd if=${l%?} of=$1"`date +%x-%X.flv`" )
    echo -e "\033[0;32m$m"
    echo -e "\033[0;34mCurrent filesize: \033[0;35m"$( stat --format=%s $1"`date +%x-%X.flv`" )
    flvflag=1
    break
    fi
    done

    # Echo the warning
    if [ $flvflag -eq 0 ]; then
    echo "Warning: no video was copied"
    fi



    http://trizen.go.ro/

    ОтветитьУдалить