I've accumulated too many quadcopter (drone) footage files (.mp4, .MOV, etc).
I researched how to ffmpeg
re-encode with "practical" losslessness (i.e. not lessless, but human eye acceptable).
These are my resultant scripts. The filenames say "reduce" but should actually be "re-encode".
In the case of GoPro, these scripts should retain the Gyro data.
I recommend footage filenames and folder-names to not include spaces. I rename
all existing files in a folder with the command rename "s/[[:space:]]/_/g" *
to make certain i have no spaces in filenames.
You could rename all files in subfolders as well: e.g. find ~/SYNC/YT-Archive/ -type f -name "*[[:space:]]*" -exec rename "s/[[:space:]]/_/g" "{}" \;
.
The same goes for folders themselves if you use -type d
. To rename both, exclude the -type
specification altogether.
I have a base reduce-crf-only.sh
that will re-encode the input file with a specified crf
value. 18-23 is "visually" lossless. 18 if you want top quality; 23 if you want minimal filesize. i typically go 18 for my best work, and 20 or 21 for all others.
I've re-watched all the output files and never noticed any reduction of quality or color. However, i have not recorded in "LOG" type formats for post-production color-grading, so this is intended for hobby-grade videos.
Further notes: This script uses N-2 cpu cores for re-encoding and uses the preset slow
along with libx264
. You could easily change these in the script. libx265(h265) are generally smaller, so one could decrease the crf value for additional quality. The scripts have hard-coded script source locations. These are expected to be located in ~/scripts/
. A conversions.log
will be stored for reference.
The output will be the filename plus the text "_crfXX .mp4" where XX is the 18-23 you specified. e.g. input.MOV --> input.MOV_crf21.mp4
reduce-crf-only.sh
will either: 1) Delete the re-encoded file if it was not smaller than the source, or 2) "Trash" the source if it was larger than the re-encoded output. Note that the log will contain the hostname when trashing files. this helps if files are synced across multiple machine and one needs to know which trash-bin to view.
reduce-all-crf.sh
will run reduce-crf-only.sh
against all MOV, MP4, & AVI files. this uses BASH
's built in case-insensitivity option. it will filter out any files with _crf
in the filename.
reduce-wildcard-crf.sh
will run reduce-crf-only.sh
against a specified wildcard string. HOWEVER, you must specify such in quotes. e.g. reduce-wildcard-crf.sh "*.webm" 20
.
In some rare cases, i may want to change the resolution of a file while re-encoding. to do so i use the reduce-resolution-crf.sh
script in the form reduce-resolution-crf.sh INPUT.mp4 1080 18
. It calculates the width-value to remain symmetric, so you only have to enter 720, 1080, or 1440, etc.
I've also included a script split-video.sh
to cut (clip) files given the start-time and end-time. This personal need has also led to a more complex, all inclusive split-and-reduce-crf.sh
which can both cut and re-encode footage, while also retaining GoPro gyro data.
Finally, I have discovered a pretty cool find
command to iterate sub-folders and re-encode a specified wildcard (excluding already re-encoded _crf
filenames):
find ~/SYNC/YT-Archive/ -type f \( -name "201*.mp4" ! -iname "*crf*" \) -exec bash -c 'cd "$(dirname {})"; pwd ; ~/scripts/reduce-crf-only.sh "$(basename {})" 20' \;
Edit 2024: So i copied all my files here again, there have been multiple edits since this project was first uploaded. That said this is certainly spaghetti code and in many cases much duplication. At one time i duplicated the files to a h265 version, but have not necessarily kept them in sync with the original h264 versions. There are some -1080.sh files which downscale larger than 1080p files to 1080p.