Часто, занимаясь своими делами, я люблю открыть какие-нибудь фильмы/клипы/сериалы, которые не требуют никакого внимания, повесив плеер где-нибудь в углу экрана. В наш век быстрого интернета и большого количества свободного видео в социальных сетях(например Vkontakte) во многом удобно смотреть их в потоке, не захламляя ненужными файлами жесткий диск… Но, попытавшись реализовать описанную выше схему, мы сталкиваемся с тем, что повесить окно браузера с плеером «где-нибудь» в углу экрана так, чтобы делать что-то полезное, больше не отвлекаясь проигрывание видео, не так уж просто. Кроме того, flash обычно ест больше ресурсов, чем обычный плеер в системе, что несколько критично для маломощных нетбуков.
Поэтому ( а еще потому, что в плеере Vkontakte отсутствует playlist, и это заставляет отвлекаться от основного занятия, когда заканчивается серия), взвесив все плюсы и минусы и посмотрев на исходный код страниц с видео, я понял, что в большинстве своем, они не сильно отличаются, и возможностей bash вполне достаточно, для реализации родившейся идеи — всё, что требуется для получения со страницы ссылки на видео — подобрать необходимые регулярные выражения и разобрать полученные wget-ом данные с помощью стандартных команд, таких как grep, sed и tr.
Первой, да и, наверное, единственной проблемой стала необходимость авторизации в контакте, для получения большинства страниц. С помощью wget не было найдено возможности воспользоваться cookies из браузера и, из-за этого возникла необходимость предварительного создания файла с cookies непосредственно для wget:
Дальнейшее казалось не очень сложным — найти закономерность и фразы от которых можно оттолкнуться и, воспользовавшись возможностями редактора sed, получить ссылку на видео. Но и здесь поджидали некоторые проблемы: одной из самых больших неожиданностей стало различие в получаемых значениях в таких случаях как
Перед добавлением файла в плейлист или его скачиванием необходимо было реализовать проверку на его наличие на сервере — что было очень просто сделать при помощи стандартных возможностей wget:
Собрав это все вместе, я получил не очень сложный скрипт, для просмотра видео. Но для добавления каждого файла необходимо было
Не самое короткая последовательность действий, особенно. когда добавляешь целый сезон какого-нибудь сериала. Поэтому, немного подумав, я сел искать возможности по облегчению процесса, без его существенного усложнения.
Первым пунктом в этом стало использование очень полезной утилиты xsel, которая позволяет обращаться к буферу системы. Так команда была сокращена от «vkvid http ://csNNNNNN.vk.com/uNNNNNN/video/nnnnnnnnn.mov», где всегда присутствовала необходимость менять ссылку, до постоянной vkvid "$(xsel -o)", которую можно было брать из истории команд не задумываясь.
Следующим, вполне ожидаемым шагом, стало добавление какого-никакого, а GUI. Сложные варианты даже не рассматривались, так как для них, было бы необходимо переписывать основную часть скрипта. Поэтому, после непродолжительного поиска, были найдены несколько вариантов: Xdialog и более широкий в плане возможностей Zeniti.
Но ни один, ни другой не позволяют реализовывать хоть сколько-нибудь сложные окна, считающие в себе несколько вариантов выбора, как, например, Radiobutton, checklist и текстовая форма.
Поэтому, поиск был продолжен, пока не был найден еще один вариант GUI для Bash-скриптов — YAD. Этот еще довольно молодой, развивающийся проект почти полностью подходил для поставленной задачи.
Создание не утяжеленного ничем лишним окна не отняло много времени:
Результат выполнения формы — это строка разделенная "|", в разборке которой опят же пригодился редактор sed.
Как дополнительный бонус, очень простой оказалась реализация процесса загрузки файла при скачивании файла. В Zeniti и очень похожем на неё Yad для этого потребовалась всего одна строчка
После написания, команда была прикреплена к сочетанию клавиш на клавиатуре. Таким образом, количество операций, необходимых для добавления файла, сократилось до 2-х:
Для корректной работы необходимы:
Код:
UPD: Простота реализации прогресс бара оказалась несколько преувеличенной. GUI загрузки отключался, когда размер сохраненной части файла превышал 100 Mb. Поэтому, с помощью Google и Ubuntuforums, были внесены небольшие корректировки:
UPD2: поправил баг, проявляющийся при сохранении, если в названии присутствуют спецсимволы: [,],{.},|
Полный вариант кода исправлен.
Поэтому ( а еще потому, что в плеере Vkontakte отсутствует playlist, и это заставляет отвлекаться от основного занятия, когда заканчивается серия), взвесив все плюсы и минусы и посмотрев на исходный код страниц с видео, я понял, что в большинстве своем, они не сильно отличаются, и возможностей bash вполне достаточно, для реализации родившейся идеи — всё, что требуется для получения со страницы ссылки на видео — подобрать необходимые регулярные выражения и разобрать полученные wget-ом данные с помощью стандартных команд, таких как grep, sed и tr.
Получение Видео
Первой, да и, наверное, единственной проблемой стала необходимость авторизации в контакте, для получения большинства страниц. С помощью wget не было найдено возможности воспользоваться cookies из браузера и, из-за этого возникла необходимость предварительного создания файла с cookies непосредственно для wget:
wget -O- -q --save-cookies .vk-cookie.txt "http://vk.com/login.php?act=login&email=$mail&pass=$pass" >>/dev/null
Дальнейшее казалось не очень сложным — найти закономерность и фразы от которых можно оттолкнуться и, воспользовавшись возможностями редактора sed, получить ссылку на видео. Но и здесь поджидали некоторые проблемы: одной из самых больших неожиданностей стало различие в получаемых значениях в таких случаях как
В первом и третьем случае — команда не выполняется, сообщая о синтаксической ошибке в где-то в середине строки. В пятом случае команда ничего не выполняет никаких действий с передаваемой строкой. И только воспользовавшись вторым и четвертым вариантами — мы получим желаемый результат( замену "/" на "\/").echo "/me/" | sed "s/\//\\\//"g>>var echo "/me/" | sed s/'\/'/'\\\/'/g >>var var=`echo "/me/" | sed s/'\/'/'\\\/'/g` var=`echo "/me/" | sed s#'\/'#'\\\/'#g` var=`echo "/me/" | sed "s/\//\\\//"g`
Перед добавлением файла в плейлист или его скачиванием необходимо было реализовать проверку на его наличие на сервере — что было очень просто сделать при помощи стандартных возможностей wget:
wget --spider $addr >>/dev/null # checking if [ $? -ne 0 ]; then #if file not exist else fi
Собрав это все вместе, я получил не очень сложный скрипт, для просмотра видео. Но для добавления каждого файла необходимо было
- Скопировать ссылку на него
- Открыть консоль
- Вызвать скрипт
- Передать ему ссылку
- Выбрать действия с файлом(сохранить/проиграть)
Не самое короткая последовательность действий, особенно. когда добавляешь целый сезон какого-нибудь сериала. Поэтому, немного подумав, я сел искать возможности по облегчению процесса, без его существенного усложнения.
Упрощение процесса
Первым пунктом в этом стало использование очень полезной утилиты xsel, которая позволяет обращаться к буферу системы. Так команда была сокращена от «vkvid http ://csNNNNNN.vk.com/uNNNNNN/video/nnnnnnnnn.mov», где всегда присутствовала необходимость менять ссылку, до постоянной vkvid "$(xsel -o)", которую можно было брать из истории команд не задумываясь.
Графический интерфейс
Следующим, вполне ожидаемым шагом, стало добавление какого-никакого, а GUI. Сложные варианты даже не рассматривались, так как для них, было бы необходимо переписывать основную часть скрипта. Поэтому, после непродолжительного поиска, были найдены несколько вариантов: Xdialog и более широкий в плане возможностей Zeniti.
Но ни один, ни другой не позволяют реализовывать хоть сколько-нибудь сложные окна, считающие в себе несколько вариантов выбора, как, например, Radiobutton, checklist и текстовая форма.
Поэтому, поиск был продолжен, пока не был найден еще один вариант GUI для Bash-скриптов — YAD. Этот еще довольно молодой, развивающийся проект почти полностью подходил для поставленной задачи.
Создание не утяжеленного ничем лишним окна не отняло много времени:
action=$(yad --center --width=400 --title="Vkvideo Save" --text="Simple video downloader" --form --field="Select Resolution::CB" --field="Name" --field="Folder:DIR" --field="Keep Cookies:CHK" "720!480!360!240" "$tname" "$HOME" TRUE --button="Open File:2" --button="Save File:0" --button="gtk-cancel:1")
Результат выполнения формы — это строка разделенная "|", в разборке которой опят же пригодился редактор sed.
tres=`echo $action | sed -e s/'|.*|'/''/` tname=`echo $action | sed -e s/"$tres"'|'/''/ | sed -e s/"|.*"/''/` tfolder=`echo $action | sed -e s/"$tres"'|'"$tname"'|'/''/ | sed -e s/"|.*"/''/`
Как дополнительный бонус, очень простой оказалась реализация процесса загрузки файла при скачивании файла. В Zeniti и очень похожем на неё Yad для этого потребовалась всего одна строчка
wget $addr -O "$tfolder/$tname.$tres.mov" 2>&1 |sed -u 's/.* \([0-9]\+%\)\ \+\([0-9.]\+.\) \(.*\)/\1\n# Downloading at \2\/s, time left: \3/'| yad --width=500 --center --title="Downloading progress" \ --text="Downloading '$tname.$tres.mov' " --progress --auto-close --auto-kill &
После написания, команда была прикреплена к сочетанию клавиш на клавиатуре. Таким образом, количество операций, необходимых для добавления файла, сократилось до 2-х:
- Скопировать ссылку из поиска видео Vkontakte
- Нажать сочетание клавиш и выбрать сохраниение или добавление в playlist
Для корректной работы необходимы:
- enco
- YAD
- Player — написано для двух вариантов — SMPlayer и VLC
Код:
#!/bin/bash #$1 link name #$2 resolution #$3 save file name #checking for existing cookies res=(720 480 360 240) tadr=$1 tres=$2 tname=$3 if [ -z "$tres" ]; then echo "$tres" tres=720 fi if [ ! -f "$HOME/.vk-cookie.txt" ]; then action1=$(yad --center --title="Lost cookies" --text="You need to enter mail and password" --form --field='Mail' --field='Password':H --button="gtk-ok:0" --button="gtk-cancel:1") mail=`echo $action1 | sed -e s/'|.*|'/''/` password=`echo $action1 | sed -e s/"$mail|"/''/ | tr -d '|'` echo "Getting cookies" wget -O- -q --save-cookies .vk-cookie.txt "http://vk.com/login.php?act=login&email=$mail&pass=$pass" >>/dev/null echo "Cookies saved" fi while [ "$SoD" != "finishdone" ] do echo "Page downloading...." LANG=ru_RU.CP1251 wget -q --load-cookies .vk-cookie.txt "$tadr" -O .tempf #download the page echo "Page recieved" enconv -x=UTF-8 -L ru .tempf grep -i ltag .tempf| egrep -o "http:\\\/\\\/cs[0-9]*.vkontakte.ru\\\/[a-z][0-9]*\\\/"| sed -e s/'http:\\\/\\\/cs'/'http:\/\/cs'/ | sed -e s/'vkontakte.ru\\\/'/'vk.com\/'/| sed -e s/'\\'/''/ >> .tempama #get server and owner names echo video/>> .tempama if [ "$tname" == "" ]; then #echo `cat .tempf` egrep -o "md_title.*md_author" .tempf | sed -e s/'md_title\\\"\:\\\"'/''/ |sed -e s/'\\\"\,\\\"md_author.*'/''/>>.tempnam tname=`cat .tempnam|sed s#' | '#' '#g|sed s#'[|,/,\]'#' '#g|tr --squeeze-repeats ' '| tr '[]{}' '()()'|sed s#' \([(,)]\)'#'\1'#g|sed s#'\([(,)]\) '#'\1'#g` rm .tempnam fi addr=`cat .tempama` addr=`echo $addr | tr -d ' '` if [ $addr == "video/" ]; then tadr=$(yad --width 500 --center --title="Bad address" --text="Bad address. Reenter please" --entry --button="gtk-cancel:1" ) rm .tempama rm .tempf else SoD=finishdone fi done echo "Ready for downloading" action=$(yad --center --width=400 --title="Vkvideo Save" --text="Simple video downloader" --form --field="Select Resolution::CB" --field="Name" --field="Folder:DIR" --field="Keep Cookies:CHK" "720!480!360!240" "$tname" "$HOME" TRUE --button="Open File:2" --button="Save File:0" --button="gtk-cancel:1") SO=$? tres=`echo $action | sed -e s/'|.*|'/''/` tname=`echo $action | sed -e s/"$tres"'|'/''/ | sed -e s/"|.*"/''/` tfolder=`echo $action | sed -e s/"$tres"'|'"$tname"'|'/''/ | sed -e s/"|.*"/''/` echo $tfolder | sed "s$\/$\\\/$"g>>tvar tvar=`cat tvar` keep=`echo $action | sed -e s/"$tres"'|'"$tname"'|'"$tvar"'|'/''/ | tr -d '|'` rm tvar grep -i ltag .tempf| egrep -o 'vtag\\\"\:\\\"[a-z0-9]*\\'| sed 's/vtag\\\"\:\\\"//'|sed -e s/'\\'/'\.'"$tres"'\.mov'/ >>.tempam #get video file name addr=`cat .tempama .tempam` #recover full link addr=`echo $addr | tr -d ' '` #remove spaces rm .tempama rm .tempam rm .tempf case $keep in TRUE) ;; FALSE) rm $HOME/.vk-cookie.txt;; esac case $SO in 0) wget --spider $addr >>/dev/null if [ $? -ne 0 ]; then rm "$tname.$tres.mov" for ((i=0; i <= 3 ; i++)) do if [ $i -ne 0 ];then let "j = $i - 1" else j=0; fi if [ ${res[$i]} -le $tres ]; then addr=`echo $addr | sed -e s/"${res[$j]}"/"${res[$i]}"/` if [ ${res[$i]} -ne $tres ];then wget --spider $addr >>/dev/null if [ $? -eq 0 ]; then RtD=2 tres=${res[$i]} i=10 fi fi fi done else RtD=1 fi rand="$RANDOM `date`" pipe="/tmp/pipe.`echo '$rand' | md5sum | tr -d ' -'`" mkfifo $pipe tdown=0 tnamesp=`echo "$tname" |tr -d '|'| tr ' ' '_'` wget -c $addr -O "$tfolder/$tnamesp.$tres.mov" 2>&1 | while read data; do if [ "`echo $data | grep '^Length:'`" ]; then total_size=`echo $data | grep "^Length:" | sed 's/.*\((.*)\).*/\1/' | tr -d '()'` fi if [ "`echo $data | grep '[0-9]*%' `" ];then percent=`echo $data | grep -o "[0-9]*%" | tr -d '%'` current=`echo $data | grep "[0-9]*%" | sed 's/\([0-9BKMG.]\+\).*/\1/' ` echo $percent echo "#Name: $tnamesp \nVideo size: $tres \nFrom: $1\n$current of $total_size ($percent%)\n" fi if [ "$current" != "$total_size" ];then tdown=fail fi done > $pipe & wget_info=`ps ax |grep "wget.*$addr" |awk '{print $1"|"$2}'` wget_pid=`echo $wget_info|cut -d'|' -f1 ` zenity --progress --auto-close --text="Connecting to $addr\n\n\n" --width="350" --title="Downloading"< $pipe if [ "`ps -A |grep "$wget_pid"`" ];then kill $wget_pid rm $tnamesp.$tres.mov tdown=fail fi rm -f $pipe if [ "$tdown" != "fail" ] then case $RtD in 2) echo "Resolution change. File "$tnamesp"."$tres".mov successfully saved" yad --center --text-align=center --height=25 --title="File Saved" --no-buttons --timeout=8 --text="Resolution change. File $tnamesp.$tres.mov successfully saved";; 1) yad --center --text-align=center --height=25 --title="File Saved" --no-buttons --timeout=8 --text="File $tnamesp.$tres.mov successfully saved" echo "File "$tnamesp"."$tres".mov successfully saved";; esac else yad --center --text-align=center --height=25 --title="ERROR" --no-buttons --timeout=8 --text="File $tname.$tres.mov has NOT been saved" fi;; 2) wget --spider $addr >>/dev/null # checking if [ $? -ne 0 ]; then for ((i=0; i <= 3 ; i++)) do if [ $i -ne 0 ];then let "j = $i - 1" else j=0; fi if [ ${res[$i]} -le $tres ]; then addr=`echo $addr | sed -e s/"${res[$j]}"/"${res[$i]}"/` if [ ${res[$i]} -ne $tres ];then wget --spider $addr >>/dev/null # checking if [ $? -eq 0 ]; then i=10; fi fi fi done fi echo "Playing file" echo "$tname" #vlc --started-from-file --playlist-enqueu "$addr" & smplayer -minigui -add-to-playlist $addr & sleep 5 echo "File is playing";; esac exit
UPD: Простота реализации прогресс бара оказалась несколько преувеличенной. GUI загрузки отключался, когда размер сохраненной части файла превышал 100 Mb. Поэтому, с помощью Google и Ubuntuforums, были внесены небольшие корректировки:
rand="$RANDOM `date`" pipe="/tmp/pipe.`echo '$rand' | md5sum | tr -d ' -'`" mkfifo $pipe wget -c $addr -O "$tfolder/$tname.$tres.mov" 2>&1 | while read data; do if [ "`echo $data | grep '^Length:'`" ]; then total_size=`echo $data | grep "^Length:" | sed 's/.*\((.*)\).*/\1/' | tr -d '()'` fi if [ "`echo $data | grep '[0-9]*%' `" ];then percent=`echo $data | grep -o "[0-9]*%" | tr -d '%'` current=`echo $data | grep "[0-9]*%" | sed 's/\([0-9BKMG.]\+\).*/\1/' ` echo $percent echo "#Name: $tname \nVideo size: $tres \nFrom: $1\n$current of $total_size ($percent%)\n" fi if [ "$current" != "$total_size" ];then tdown=fail fi done > $pipe & wget_info=`ps ax |grep "wget.*$addr" |awk '{print $1"|"$2}'` wget_pid=`echo $wget_info|cut -d'|' -f1 ` zenity --progress --auto-close --text="Connecting to $addr\n\n\n" --width="350" --title="Downloading"< $pipe
UPD2: поправил баг, проявляющийся при сохранении, если в названии присутствуют спецсимволы: [,],{.},|
Полный вариант кода исправлен.