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}"
to ensure that all necessary input parameters are passed to the script in the upper text field. The upper text field labeled "Script" will be the one containing the actual bash script.
For example, the following script can be used:
########################################################################### ## 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
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. Similarly, the parameters of the ffmpeg
command can be customized appropriately and, in the given case, the video is transcoded to SDTV quality, within an MP4 container that seems to be supported by all major browsers and with zero latency / fast start flags enabled in order to ensure a speedy and fluent playback without the need to re-encoded the video files.
In order to use Intel QSV GPU acceleration, simply replace the ffmpeg line with:
# FFMpeg command echo "Using FFMpeg to convert file." ffmpeg \ -hwaccel qsv \ -i "$INPUT_FILE" \ -c:v h264_qsv -crf 23 -profile:v baseline -level 3.0 -pix_fmt yuv420p \ -c:a aac -ac 2 -b:a 128k \ -vf "scale_qsv=w=-1:h=480:mode=hq,hwdownload" \ -preset veryfast \ -tune zerolatency \ -movflags faststart -movflags separate_moof \ "$PROCESSING_FILE"
and make sure that the web server user has access to /dev/dri
.