This might be of interest to some of you.
As I’ve finally organised my library (and thanks for the help with the extras management), I wanted to have a data-rich experience and having the files’ metadata pop up is really rather cool.
However, there is an issue with the aspect ratio as I have ripped my 4k UHD collection initially to ISO files, but have now extracted the content into MKV files. This means that they’re the full 3840x2160 resolution, i.e. always 1.85 and don’t take into account all the films in scope with the letterbox bars.
With some research and help from ChatGPT, I made up a script which uses ffmpeg to analyse the individual files to determine the actual aspect ratio and create corresponding .NFO files for each movie containing the correct aspect ratio.
This would have been straight forward except that the analysis of files doesn’t really work when they’re 10-bit HDR / DV because ffmpeg is expecting 8-bit files.
Also, I needed some nested directory support so it will scan all the movies, each in their own directory without scanning and extras subdirectory (unless you want to scan for correct aspect ratio on the extras).
Here’s my script, you can adjust the parameters to your liking.
#!/bin/bash
BASE_DIR="./"
FRAMES_TO_SCAN=500
START_TIME="00:05:00"
find "$BASE_DIR" -maxdepth 2 -type f \( -iname "*.mp4" -o -iname "*.mkv" \) -print0 | \
while IFS= read -r -d '' video; do
echo "Processing: [$video]"
CROP=$(ffmpeg -ss "$START_TIME" -i "$video" -vf "format=yuv420p,cropdetect=20:2:0" -frames:v "$FRAMES_TO_SCAN" -f null - < /dev/null 2>&1 \
| grep -o "crop=[0-9]*:[0-9]*:[0-9]*:[0-9]*" \
| sort | uniq -c | sort -nr | head -n 1 | awk '{print $2}')
if [[ -z "$CROP" ]]; then
echo " Could not detect crop."
continue
fi
CROP_WIDTH=$(echo "$CROP" | cut -d':' -f1)
CROP_HEIGHT=$(echo "$CROP" | cut -d':' -f2)
if [[ "$CROP_HEIGHT" -eq 0 ]]; then
echo " Invalid crop height."
continue
fi
ASPECT_RATIO=$(awk "BEGIN { printf \"%.2f\", $CROP_WIDTH / $CROP_HEIGHT }")
BASENAME="${video%.*}"
TITLE="$(basename "$BASENAME")"
NFO_FILE="${BASENAME}.nfo"
echo " Detected Aspect Ratio: $ASPECT_RATIO"
cat > "$NFO_FILE" <<EOF
<movie>
<title>$TITLE</title>
<aspectratio>$ASPECT_RATIO</aspectratio>
</movie>
EOF
echo " Wrote $NFO_FILE"
done
You should modify BASE_DIR
to reflect your directory containing your films (each in their corresponding named directory).
FRAMES_TO_SCAN
- I put 500 but a lower number like 200 is probably sufficient. Note that this doesn’t take into account changing aspect ratio movies. That could be catered for with an average I guess.
START_TIME
- Currently set at 5 minutes (5 minutes into the file). To cover scenarios where there’s a lot of black screen at the beginning meaning detection won’t work.
The script appears to be working reliably with filenames containing spaces and round brackets (I have the year to help identify the film in the scraper.
When running, it will output each file it’s processing, the detected aspect ratio and the creation of a corresponding .NFO file.
Sample output from my usage:
Processing: [./Godzilla (2014)/Godzilla (2014).mkv]
Detected Aspect Ratio: 2.39
Wrote ./Godzilla (2014)/Godzilla (2014).nfo
Processing: [./Gremlins (1984)/Gremlins.mkv]
Detected Aspect Ratio: 1.78
Wrote ./Gremlins (1984)/Gremlins.nfo
Processing: [./Ghostbusters (1984)/Ghostbusters.mkv]
Detected Aspect Ratio: 2.39
Wrote ./Ghostbusters (1984)/Ghostbusters.nfo
Processing: [./Life (2017)/Life.mkv]
Detected Aspect Ratio: 2.39
Wrote ./Life (2017)/Life.nfo