Originally published May 14, 2019 @ 1:59 pm
All that crap I’ve been saving from YouTube, Facebook and whatnot tends to add up. As quality is not a huge concern here (not that it was very high to begin with), optimizing those video files can recover a surprisingly significant amount of disk space. If you have CPU cycles to spare that is. The main advantage here is really not the disk space, which is cheap nowadays, but faster network transfer rates.
All of this has been done in Windows 10 Pro running Ubuntu 18.04.1 LTS installed from the Microsoft store. The ffmpeg
utility was installed like so:
sudo su - cd /tmp && wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz tar xf ffmpeg-release-amd64-static.tar.xz mv ffmpe*amd64-static/ /opt/ffmpeg/ ln -s /opt/ffmpeg/ffmpeg /usr/bin/ffmpeg ln -s /opt/ffmpeg/ffprobe /usr/bin/ffprobe ln -s /opt/ffmpeg/qt-faststart /usr/bin/qt-faststart
The script below does a few things:
- Finds video files in the source folder. You can control the depth of search.
- Identifies the original encoding (this is if you want to stay with it).
- Calculates the optimal bitrate based on the duration of the video.
- Re-encodes the file using H.265 (or you can stick with the original codec).
- Tells you how much disk space you saved.
So let me break this down a bit. This line will find “video” files in the specified folder, without descending into subfolders. You can control this by modifying the -maxdepth
option.
find "${in_dir}" -mindepth 1 -maxdepth 1 -type f -exec file -N -i -- {} + | sed -n 's!: video/[^:]*$!!p'
The two lines below will attempt to get the name of the codec used by the original file and to identify the appropriate encoder available on your system. This does not always work as expected, unfortunately, so feel free to make improvements.
codec="$(ffprobe "${p}/${n}.${e}" 2>&1 >/dev/null | grep -oP "(?<=Video: )[a0-z9]{1,}(?= )")" encoder="$(ffmpeg -codecs 2>/dev/null| grep "decoders: ${codec}" | grep -oP "(?<=encoders: )[a0-z9]{1,}(?= )")"
The nested ffmpeg
in the command below identifies the duration of the video in seconds. It then divides 10^9
(1GB) by that value to get the optimal bitrate and passes that to the -b
option.
ffmpeg -i "${p}/${n}.${e}" -vcodec ${target_encoder} -crf 20 \ -b $(echo "scale=0; 10^9 / $(ffmpeg -i "${p}/${n}.${e}" 2>&1 | grep -oP -m1 "(?<=ion: )([0-9]{2}(:)?){3}(?=\.[0-9]{2},)" | \ awk '{split($1,A,":"); split(A[3],B,".");print 3600*A[1]+60*A[2]+B[1]}')"|bc) \ "${p}/${n}_${target_encoder}.${e}" >/dev/null 2>&1
The script is below and is also available on my GitHub.
While I am on the subject of videos, recently I went to an event and made a few rather shaky videos with my little Sony camera (lots of people pushing and shoving, and the two beers I had didn’t help steady the hand either).
So here’s a quick-and-dirty way to remove some of the shakiness out of your videos.
ffmpeg -i 00009.MTS -vf vidstabdetect -f null - ffmpeg -i 00009.MTS -vf vidstabtransform=smoothing=30:input="transforms.trf" -vcodec libx264 00009.mkv
If your video is extremely shaky, you may need to pass some additional parameters to the first command that generates the transforms.trf
file. However, keep in mind that the more smoothing you do, the more weird the outcome might be.
ffmpeg -i 00009.MTS -vf vidstabdetect=shakiness=10:accuracy=15 -f null -
Here’s a useful one: you can make a side-by-side video of the original and the stabilized versions to see the overall effect:
ffmpeg -i 00009.MTS -i 00009.mp4 -vcodec libx264 -filter_complex "[0:v]setpts=PTS-STARTPTS, pad=iw*2:ih[bg]; [1:v]setpts=PTS-STARTPTS[fg]; [bg][fg]overlay=w" 00009_sbs.mp4
Thanks for watching.
Experienced Unix/Linux System Administrator with 20-year background in Systems Analysis, Problem Resolution and Engineering Application Support in a large distributed Unix and Windows server environment. Strong problem determination skills. Good knowledge of networking, remote diagnostic techniques, firewalls and network security. Extensive experience with engineering application and database servers, high-availability systems, high-performance computing clusters, and process automation.