Unfortunately, the plugins are not enough and the pre-configured video transcoding options are insufficient to satisfy all the needs when converting video files such that more than often it required to just use a custom shell script and provide ffmpeg with custom parameters.
A custom ffmpeg script can be created by installing the "External Worker Processor Script" plugin. The execution type can be set to Bash Script
. In the lower text field labeled with "Arguments to pass to the command or script" can be filled with the following:
"{source_file_path}" "{file_out_path}" "{data_json_file}"
The parameters at the top can be changed; in particular DATABASE_FILE
should be changed to reflect the full path to a file where the bash script will record the status of the videos that have been transcoded.
The script is designed to track the videos that have been transcoded and will not transcode them again given a followup library enumeration.
The conversion makes the following assumptions:
########################################################################### ## Copyright (C) Wizardry and Steamworks 2023 - License: GNU GPLv3 ## ########################################################################### INPUT_FILE="$1" CONVERTED_FILE="${1%.*}.mp4" PROCESSING_FILE="${2%.*}.mp4" JSON_FILE="$3" DATABASE_FILE=/opt/unmanic/unmanic.db ########################################################################### # Initialize database if not already done. echo "CREATE TABLE IF NOT EXISTS 'unmanic' ( Hash STRING PRIMARY KEY );" | sqlite3 "$DATABASE_FILE" # Check whether the file to transcode already exists. echo "Checking if file has been already processed." FILE_HASH=`md5sum "$INPUT_FILE" | awk '{ print $1 }'` COUNT=`echo "SELECT COUNT() FROM 'unmanic' WHERE Hash='$FILE_HASH';" | sqlite3 "$DATABASE_FILE"` if [ $COUNT -gt 0 ]; then echo "File already processed." exit 1 fi # FFMpeg command echo "Using FFMpeg to convert file." /usr/bin/ffmpeg \ -i "$INPUT_FILE" \ -c:v libx264 -crf 23 -profile:v baseline -level 3.0 -pix_fmt yuv420p \ -c:a aac -ac 2 -b:a 128k \ -vf "scale=480:trunc(ow/a/2)*2" \ -preset veryfast \ -tune zerolatency \ -movflags faststart -movflags separate_moof \ "$PROCESSING_FILE" LFT=`/usr/bin/ffprobe -i "$INPUT_FILE" -show_format -v quiet | grep duration | awk -F '=' '{ print $2 }' | xargs printf "%.0f\n"` RHT=`/usr/bin/ffprobe -i "$PROCESSING_FILE" -show_format -v quiet | grep duration | awk -F '=' '{ print $2 }' | xargs printf "%.0f\n"` echo "LFT vs. RHT size: "$LFT" vs. "$RHT if [ $LFT -gt $RHT ]; then echo "FFMpeg could not convert the file." exit 1 fi # Save file as processed to database. echo "Adding conerted file hash to database." FILE_HASH=`md5sum "$PROCESSING_FILE" | awk '{ print $1 }'` echo "INSERT INTO 'unmanic' ( Hash ) VALUES ( '$FILE_HASH' );" | sqlite3 "$DATABASE_FILE" echo "Passing complete file to unmanic..." cat << EOF > "$JSON_FILE" { "file_out": "$PROCESSING_FILE" } EOF
Note that if this script is run under Docker, access to the graphics card is necessary and currently Docker does not support passing the graphics card to services running on Docker swarm nodes.
########################################################################### ## Copyright (C) Wizardry and Steamworks 2023 - License: GNU GPLv3 ## ########################################################################### INPUT_FILE="$1" CONVERTED_FILE="${1%.*}.mp4" PROCESSING_FILE="${2%.*}.mp4" JSON_FILE="$3" DATABASE_FILE=/tmp/unmanic/unmanic.db ########################################################################### # Initialize database if not already done. echo "CREATE TABLE IF NOT EXISTS 'unmanic' ( Hash STRING PRIMARY KEY );" | sqlite3 "$DATABASE_FILE" # Check whether the file to transcode already exists. echo "Checking if file has been already processed." FILE_HASH=`md5sum "$INPUT_FILE" | awk '{ print $1 }'` COUNT=`echo "SELECT COUNT() FROM 'unmanic' WHERE Hash='$FILE_HASH';" | sqlite3 "$DATABASE_FILE"` if [ $COUNT -gt 0 ]; then echo "File already processed." exit 1 fi # FFMpeg command echo "Using FFMpeg to convert file." nice -n19 ffmpeg \ -hwaccel qsv \ -i "$INPUT_FILE" \ -map 0:v:0 -map 0:a:0 \ -c:v h264_qsv -crf 23 -profile:v baseline -level 3.0 -pix_fmt nv12 \ -c:a aac -ac 2 -b:a 128k \ -c:s copy \ -vf "scale_qsv=w=-1:h=480:format=bgra,hwdownload,format=bgra" \ -preset veryfast \ -tune zerolatency \ -movflags faststart -movflags separate_moof \ "$PROCESSING_FILE" LFT=`ffprobe -i "$INPUT_FILE" -show_format -v quiet | grep duration | awk -F '=' '{ print $2 }' | xargs printf "%.0f\n"` RHT=`ffprobe -i "$PROCESSING_FILE" -show_format -v quiet | grep duration | awk -F '=' '{ print $2 }' | xargs printf "%.0f\n"` echo "LFT vs. RHT size: "$LFT" vs. "$RHT if [ $LFT -gt $RHT ]; then echo "FFMpeg could not convert the file." exit 1 fi # Save file as processed to database. echo "Adding conerted file hash to database." FILE_HASH=`md5sum "$PROCESSING_FILE" | awk '{ print $1 }'` echo "INSERT INTO 'unmanic' ( Hash ) VALUES ( '$FILE_HASH' );" | sqlite3 "$DATABASE_FILE" echo "Passing complete file to unmanic..." cat << EOF > "$JSON_FILE" { "file_out": "$PROCESSING_FILE" } EOF