Using FFmpeg to Get an MP3's Duration and 4 Ways to Get the File Size
Here's a Shell script I created to automate a task that used to take a bunch of steps to do manually.
After 80+ episodes of my Running in Production podcast I finally automated the process of getting an MP3’s duration and file size in bytes so I can add it to the meta data of each episode (the site is built with Jekyll and is open source).
This video goes over what I used to do manually and how I automated it with a Shell script, FFmpeg and a few Unix tools. The takeaway here is you might be able to extract some of the patterns into your own scripts. For example, we’ll go over a while loop that removes leading zeros and colons from a string using a bit of Shell scripting and more.
# Demo Video
Commands
Here’s 4 ways to get a file’s size in bytes (replace $file
with your file):
# POSIX compliant.
wc -c < "${file}"
# Likely only works on Linux but is the fastest.
stat c %s "${file}"
# Likely only works on Linux.
du -sb "${file}"
# Hey it's possible!
python3 -c "import os; print(os.path.getsize('$file'))"
Here’s 2 ways to get the duration of an MP3 using ffmpeg
.
You’ll need to install ffmpeg
with sudo apt-get install ffmpeg
, brew install ffmpeg
or use whatever package manager your OS comes with.
# This is fast but it's only an estimate based on the bitrate of the file.
ffmpeg -i "${file}" 2>&1 | grep -oE "[0-9]{1}:[0-9]{2}:[0-9]{2}"
# More accurate but much slower. The first method hasn't failed me yet, it's
# usually only a difference of a few milliseconds.
ffmpeg -i "${file}" -f null /dev/null 2>&1 | grep -oE "[0-9]{1}:[0-9]{2}:[0-9]{2}" | tail -n 1
Recently I found you can do this with ffprobe
too which comes with ffmpeg
.
Here’s that post.
Timestamps
- 0:14 – Focusing on the why and then the how
- 0:41 – Using this script to get meta data about each podcast episode
- 2:01 – The manual process before I made this script
- 3:45 – The script fixed a bunch of human errors I made in the past
- 4:19 – Running the script to see how it works
- 5:43 – Skimming the script
- 6:27 – Set -e and preparing the file path to modify
- 7:55 – Handling no episode or invalid episode names
- 9:35 – Using find, sort and tail to get the latest episode
- 12:51 – 4 different ways to get the file size in bytes on Linux and Unix
- 17:40 – Using FFmpeg and a regular expression to get the duration of an MP3
- 22:00 – Using a Bash while loop to strip leading 0s and leading colons
- 25:58 – Figuring out if an episode is published or a draft
- 30:43 – Outputting the details if we’re doing a dry run
- 31:54 – Using Perl to do in place edits on the file in a cross platform way
- 33:23 – A Bash 1 liner to run the script on every episode
- 34:53 – Getting a more accurate duration with FFmpeg
Reference Links
- https://runninginproduction.com
- https://github.com/nickjj/runninginproduction.com/blob/master/_bin/podcast-mp3-details
- https://twitter.com/nickjanetakis/status/1398668116872343552
- https://nickjanetakis.com/blog/switching-from-nerdtree-to-fern-for-a-vim-tree-view-plugin
- https://nickjanetakis.com/blog/shell-script-accepting-user-input-heredocs-in-place-edits-and-more
- https://nickjanetakis.com/blog/resize-and-see-how-big-any-window-is-using-a-free-tool-called-sizer
What are you going to do with this script? Let me know below.