Wednesday, September 13, 2017

How to make MP4 video files smaller

The important command for this is:

ffmpeg -nostdin -i "$ORIGINAL_FILE" -vcodec libx264 -crf 26 "$OUTPUT_FILE"

The crf factor can be higher, then the file size will be even smaller.

It is possible to process more files at once.

Let's find files that have bitrate more than 3000 kb/s (which means we have probably not processed them yet):

find . -name "*.mp4" | while read F; do if [ `ffprobe "$F" 2>&1 | sed -n 's/.*bitrate:[^0-9]*\([0-9]*\).*/\1/p'` -gt 3000 ]; then echo "$F"; fi; done | tee tmp_mp4_list

If we want to see some details like the bitrate and file size, we can add this info for us:

find . -name "*.mp4" | while read F; do BTR=`ffprobe "$F" 2>&1 | sed -n 's/.*bitrate:[^0-9]*\([0-9]*\).*/\1/p'`; if [ "$BTR" -gt 3000 ]; then echo "$BTR `ls -lh "$F"`"; fi; done | tee tmp_mp4_list_details

We can pass the output from the first find command to ffmpeg:

cat tmp_mp4_list | while read F; do F_ORIG=`echo "$F" | sed 's/\(\.[^.]*\)$/_orig\1/'`; F_NEW=`echo "$F" | sed 's/.mp4$/.MP4/'`; mv -i "$F" "$F_ORIG" && ffmpeg -nostdin -i "$F_ORIG" -vcodec libx264 -crf 26 "$F_NEW"; if [ ! $? -eq 0 ]; then echo "$F" "$?" >> tmp_errors; fi; done

It will rename the original file to file_orig.mp4. The new one will have an uppercase extension .MP4 so that we can recognize we dealt with it already. We do not add extra characters to not make the filename longer in order to save space on a mobile display. If an error occurs, the filename will be mentioned in the 'tmp_errors' file.