User Tools

Site Tools


Sidebar


Здравствуйте!

Меня зовут Михаил!
Я системный администратор
и наполняю эту wiki,
решая разнообразные IT-задачки.

Моя специализация - виртуализация!

Я всегда готов помочь Вам
наладить IT-инфраструктуру
за скромное вознаграждение!

mike@autosys.tk
+7 (910) 911-96-23

linux_faq:bash_script_to_batch_convert_video_files_to_h265

to do

1. добавить вывод даты/времени в начале конвертирования каждого файла. бывает, что handbrake зависает и непонятно долго ли он уже мурыжит этот файл.

3. Сделать проверку/сравнение длительности потока исходного и конечного файла. Просто я столкнулся с тем, что в отсутствие кодеков, handbrake создает файл без видеопотока, но ошибок не сообщает.

ffprobe videofile.avi -v error -select_streams 0 -show_entries stream=duration

4. Сделать проверку и исправление исходного файла, в случае, когда не совпадает длительность потока.

Для чего

Мне захотелось оптимизировать свой видеоархив при помощи кодека h265, который позволяет существенно сэкономить место на диске практически без потери качества видеоматериалов.

Применяемые средства

Для конвертации я буду использовать HandBrakeCLI под Ubuntu 16.04.
Устанавливать HandBrakeCLI лучше из репозитория разработчиков. Версия, которая есть в репозиториях Ubuntu 16.04 старая и некорректно обрабатывает звук (он просто пропадает после конвертации).
Также понадобится ffmpeg для определения кодека (чтобы повторно не конвертировать файлы уже сконвертированные в h265) и работы с данными EXIF.

sudo add-apt-repository ppa:stebbins/handbrake-releases
sudo apt-get update
sudo apt-get install handbrake-cli ffmpeg

Описание скрипта

Скрипт адаптирован к именам файлов и папок, содержащим пробелы.
Скрипт формирует список файлов в папке и вложенных папках по типу MIME - video.
Затем, у каждого файла проверяется текущий видеокодек и если он не HEVC (h265), то файл проверяется на наличие ошибок и если все все хорошо - конвертируется. Конвертированный файл кладется с именем оригинального файла на то же место, где лежал оригинальный файл.
После конвертации в файле меняется значение EXIF-аттрибута creation_date на значение извлеченное из оригинального файла.
В качестве бонуса подсчитывается количество сэкономленного места.
Для работы нужно задать параметры - папку с исходными файлами, папку куда будут положены исходные файлы после конвертации, а также количество потоков для HandBrakeCLI, чтобы система оставалась юзабельной во время конвертации.

#!/bin/bash

srcdir=/files/cloud/2014
oldfilesdir=`dirname "$srcdir"`/Unconverted_Video_`basename "$srcdir"`
filelist=`find $srcdir -type f -exec file -N -i -- {} + | sed -n 's!: video/[^:]*$!!p'`
logfile=$oldfilesdir/convertation_`date +"%d.%m.%y_%H-%M"`.log
threads=3

mkdir $oldfilesdir
oldsize=0; newsize=0; filesleft=0; corruptedfiles=0
filesleft=`echo "$filelist" | wc -l`
echo $filesleft "video files detected" | tee -a $logfile
while read -r file
do
echo "FILE - $file" | tee -a $logfile
echo "ffprobe -show_format \"$file\" 2>&1 | grep Video: | grep hevc" | /bin/bash 1>/dev/null 2>/dev/null
if [ $? -eq 0 ]; then echo "This File is already in HEVC (h265)" | tee -a $logfile
else
        echo "Checking file for errors..." | tee -a $logfile
        echo "ffmpeg -i \"$file\" -v error -f null - 2>/dev/null 1>/dev/null" | /bin/bash 1>/dev/null 2>/dev/null
        if [ $? -ne 0 ]; then echo "File corrupted. Skipping..." | tee -a $logfile; (( corruptedfiles++ ))
        else
        filedir=`dirname "$file"`
        filesize=`du -k "$file" | cut -f1`
        filename=`basename "$file"`
        creationtime=`echo "ffprobe \"$file\" 2>&1 | grep -m 1 creation_time | sed -n -e 's/^.*creation_time\ *:\ *//p'" | /bin/bash`
        oldsize=$(( oldsize + filesize ))
        mkdir --parents "$oldfilesdir"/"$filedir"
        mv "$file" "$oldfilesdir"/"$filedir"
        echo "HandBrakeCLI -i \"$oldfilesdir\"/\"$file\" -o \"$filedir\"/\"$filename\" -e x265 -q 20 -E av_aac \
        --custom-anamorphic --keep-display-aspect -O -x threads=$threads 2> /dev/null" | /bin/bash
        handbrakereturn=$?
        if [ "$handbrakereturn" -eq 0 ]
                then echo "Convertation Done." | tee -a $logfile
                if [ "$creationtime" ]
                        then echo "Preserving Creation Time..." | tee -a $logfile
                        echo "ffmpeg -i \"$filedir\"/\"$filename\" -metadata:s:v:0 creation_time=\"$creationtime\" \
                        -metadata:s:a:0 creation_time=\"$creationtime\" -metadata creation_time=\"$creationtime\" \
                        -c copy \"$filedir\"/\"new_date_$filename\" 2> /dev/null" | /bin/bash
                        if [ $? -eq 0 ]; then echo "Done." | tee -a $logfile; else echo "Preservation of Creation Time metadata failed..." | tee -a $logfile; fi 
                        mv "$filedir"/"new_date_$filename" "$filedir"/"$filename"
                        else echo "Creation Time metadata not found" | tee -a $logfile
                fi
                else echo "Convertation ERROR. HandBrakeCLI Exit Code: $handbrakereturn" | tee -a $logfile
                mv "$oldfilesdir"/"$file" "$file"
        fi
        sync
        filesize=`du -k "$file" | cut -f1`
        newsize=$(( newsize + filesize ))
fi
fi
        (( filesleft-- ))
        echo $filesleft "files left to convert" | tee -a $logfile
done < <(echo "$filelist")
echo "Converted files old size - $oldsize Kb" | tee -a $logfile
echo "Converted files new size - $newsize Kb" | tee -a $logfile
echo "Saved Space - $(( $oldsize - $newsize )) Kb" | tee -a $logfile
echo "Corrupted files: $corruptedfiles" | tee -a $logfile

Discussion

Enter your comment. Wiki syntax is allowed:
T​ Q A B S
 
linux_faq/bash_script_to_batch_convert_video_files_to_h265.txt · Last modified: 2017/07/05 08:04 by admin