Скрипт захвата видео с компьютера и вывода диалога в zenityПодписка на Комментарии к "Скрипт захвата видео с компьютера и вывода диалога в zenity"

Аватар ormorph

Задался целью написать скрипт захвата видео с помощью программы ffmpeg.
Для диалога скрипт использует программу zenity.

Принцип действия

Запускается скрипт, я прописал его в меню оконного менеджера FluxBox, у меня на него созданно два пункта в меню, это захват видео без звувка, и захват видео со звуком.
Для того чтобы использовать вывод со звуком используется ключик -sound, в противном случае захват осуществляется без звука.

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

В данном окошке можно нажать отмена, тогда все файлы данного захвата будут удалены.
Видео по умолчанию сохраняется в $HOME/screenshot.

Принцип обработки диалога конвертирования файла в более сжатый.

Принцип работы данного диалога описан https://help.gnome.org/users/zenity/2.32/zenity-progress-options.html.ru
Остается только обработать вывод ffmpeg.

В выводе ffmpeg присутствует строчка с надписью Duration: 00:01:23.50, где 00:01:23 предположительное время сколько должен занять процесс конвертирования файла.

Так же ffmpeg выдает через определенные интервалы времени строчки содержащие надпись time=00:00:29.20 - это сколько времени уже прошло. Используя эти данные можно подсчитать сколько процентов уже выполнено, и вывести эти данные в диалоговое окно индикатора прогресса zenity.

Собственно вот и сам скрипт.

#!/bin/bash

# Каталог куда будет сохраняться файл
OUTDIR="$HOME/screenshot"

if ! [ -d "$OUTDIR" ] ; then
        mkdir -p "$OUTDIR"
fi

#Определяет текущее разрешение экрана:
while read file
do
        MASS=($file)
        if [ -n "$(echo ${MASS[1]}|egrep '\*\+')" ] ; then
                SCR_SIZE="${MASS[0]}"
        fi
done <<<"$(xrandr --current)"

#Генерирует случайное имя
NAME="$(tr -cd [:digit:] < /dev/urandom | head -c8)"
FILE="VID_$NAME"

#Выбор со звуком или без - вывод звука на pulseaudio
if [ "$1" == "-sound" ] ; then
        SOUND="-f alsa -ac 2 -i pulse -acodec pcm_s16le "
else
        SOUND=""
fi

# Команда захвата видео
ffmpeg $SOUND-f x11grab -s $SCR_SIZE -r 10 -i :0.0 -vcodec mpeg4 -sameq $OUTDIR/$NAME.mp4 >/dev/null 2>&1 &

#определяет PID запущенного процесса ffmpeg
PIDOF=($(pidof ffmpeg))
NUM=$((${#PIDOF[@]}-1))
PID="${PIDOF[$NUM]}"

#иконка в трее
zenity  --notification  --window-icon="/usr/share/icons/hicolor/48x48/apps/gdu-smart-failing.png"  --text "Захват"
kill $PID
sleep 1s

# функсия конвертирует файл и выводит информацию в процентах
CONV(){
        #Команда производящая конвертацию видео файла
        ffmpeg -i "$OUTDIR/$NAME.mp4" -acodec libmp3lame \
        -ab 128k -ac 2 -vcodec libx264 -crf 22 -threads 0 \
        "$OUTDIR/$FILE.mp4" 2>&1| stdbuf -o0 tr \
        '\r' '\n'|while read file #цикл обрабатывающий поток
        do
                MASS=($file)

                if  [ -n "$(echo ${MASS[0]}|egrep Duration)" ] ; then
                DURATION="${MASS[1]:0:8}"
            fi

            if [ -n "$(echo "$file"|egrep "time=")" ] ; then
                TIME="${MASS[7]:5:8}"
                echo "# Процесс сжатия займет $DURATION"
                echo "# Процесс сжатия займет $DURATION"

                HMS1=(${DURATION//:/ })
                                HMS2=(${TIME//:/ })

                                #Удаляем первый ноль из цифр
                                HMS1=(${HMS1[@]#0})
                                HMS2=(${HMS2[@]#0})

                SEK1=$((${HMS1[0]}*3600+${HMS1[1]}*60+${HMS1[2]}))
                SEK2=$((${HMS2[0]}*3600+${HMS2[1]}*60+${HMS2[2]}))
                PERCENT=$(($SEK2*100/$SEK1))
                echo "$(($PERCENT))"
            fi
        done
        }


#Функция для диалога zenity
process(){
        CONV
        echo "100"
        echo "100"
        echo "# Сжатие завершено!"
        sleep 1s
        echo "# удаление исходного файла"
        sleep 1s
        rm $OUTDIR/$NAME.mp4
        echo "# Процесс завершен!"
}

process|zenity --progress \
--title="Обработка видеофайла" \
--text="Начинаю процесс сжатия..." \
--percentage=0

#Удаляет файлы в случае нажатия клавиши отмена
if [ "$?" -eq "1" ]; then
        if [ -f "$OUTDIR/$NAME.mp4" ] ; then
        rm "$OUTDIR/$NAME.mp4"
    fi

    if [ -f "$OUTDIR/$FILE.mp4" ] ; then
        rm "$OUTDIR/$FILE.mp4"
    fi
fi

Интересно само решение работы данного скрипта в плане удобства, команда захвата ffmpeg, может не везде работать, все зависит от самой сборки ffmpeg, какие кодеки включены в него, ну и какой вывод звука использует данная система.
В данном случае используется pulseaudio, для вывода(захвата) звука.
Каждый подбирает нужные параметры ffmpeg сам под себя.

Аватар ormorph

Изменил скрипт под Yad, так как гномовский zenity перестал выводить иконку в трей и требует зависимости с гномом. Так же сделаны изменения в обработке диалога процента, так как в ffmpeg немного изменился вывод в начале.

#!/bin/bash

# Каталог куда будет сохраняться файл
OUTDIR="$HOME/screenshot"

if ! [ -d "$OUTDIR" ] ; then
        mkdir -p "$OUTDIR"
fi

#Определяет текущее разрешение экрана:
while read file
do
        MASS=($file)
        if [ -n "$(echo ${MASS[1]}|egrep '\*\+')" ] ; then
                SCR_SIZE="${MASS[0]}"
        fi
done <<<"$(xrandr --current)"

#Генерирует случайное имя
NAME="$(tr -cd [:digit:] < /dev/urandom | head -c8)"
FILE="VID_$NAME"

#Выбор со звуком или без - вывод звука на pulseaudio
if [ "$1" == "-sound" ] ; then
        SOUND="-f alsa -ac 2 -i pulse -acodec pcm_s16le "
else
        SOUND=""
fi

# Команда захвата видео
ffmpeg $SOUND-f x11grab -s $SCR_SIZE -r 10 -i :0.0 -vcodec mpeg4 $OUTDIR/$NAME.mp4 >/dev/null 2>&1 &

#определяет PID запущенного процесса ffmpeg
PID="$!"

#иконка в трее
yad  --notification --image="start.png"  --text "Захват"
kill $PID
sleep 1s

# функсия конвертирует файл и выводи информацию в процентах
CONV(){
        #Команда производящая конвертацию видео файла
        ffmpeg -i "$OUTDIR/$NAME.mp4" -acodec libmp3lame \
        -ab 128k -ac 2 -vcodec libx264 -crf 22 -threads 0 \
        "$OUTDIR/$FILE.mp4" 2>&1| stdbuf -o0 tr \
        '\r' '\n'|while read file #цикл обрабатывающий поток
        do
                MASS=($file)

                if  [ -n "$(echo ${MASS[0]}|egrep Duration)" ] ; then
                DURATION="${MASS[1]:0:8}"
            fi

            if [ -n "$(echo "$file"|egrep "time=")" ] && [ ! -n "$(echo "$file"|egrep "fps=0")" ] ; then
                TIME="${MASS[7]:5:8}"
                echo "# Процесс сжатия займет $DURATION"
                echo "# Процесс сжатия займет $DURATION"

                HMS1=(${DURATION//:/ })
                                HMS2=(${TIME//:/ })

                                #Удаляем первый ноль из цифр
                                HMS1=(${HMS1[@]#0})
                                HMS2=(${HMS2[@]#0})

                SEK1=$((${HMS1[0]}*3600+${HMS1[1]}*60+${HMS1[2]}))
                SEK2=$((${HMS2[0]}*3600+${HMS2[1]}*60+${HMS2[2]}))
                PERCENT=$(($SEK2*100/$SEK1))
                echo "$(($PERCENT))"
            fi
        done
        }


#Функция для диалога zenity
process(){
        CONV
        echo "100"
        echo "100"
        echo "# Сжатие завершено!"
        sleep 1s
        echo "# удаление исходного файла"
        sleep 1s
        rm $OUTDIR/$NAME.mp4
        echo "# Процесс завершен!"
}

process|yad --progress \
--title="Обработка видеофайла" \
--text="Начинаю процесс сжатия..." \
--percentage=0

Можно конечно еще добавить проверку наличия директории $HOME/screenshot и создания ее в случае отсутствия.
Проверено на ffmpeg-2.8.6.

Добавить комментарий