I am a 40+ software engineer and recreational Jiu Jitsu practitioner, struggling with vast amount of information related to the sport. I decided to make use of my `computer` skills to aid me in the process of taming this new skill.
This post is going to demonstrate how to use ffmpeg in order to:
- Split long insturctions into logical chapters
- Capture screenshots
- Create animated gifs demonstrating techniques
This post will cover the fundamentals and will be the base for future posts that will demonstrate integrations with ohter tools.
ffmpeg is tools for recording, manipulating and streaming videos. It’s free & opensource and available for most operationg systems. In this post we are going to focus on the `manipulating` part.
Jiu Jitsu instructionals are long. Even though they are usually split into pieces, each piece easily exceeds one hour in duration and looks more like a seminar rather than a lesson. Personally, I find that in most cases it’s really hard to digest more than 10-15 minutes in a single sitting. So, I’d like to split the videos even further, maybe per scene.
Also, I would like to embed parts of the instructional directly inside my notes. For example, in the section where I have my notes on `Juji Gatame` I’d like to have an animated gif demonstrating the technique. In more rare cases, a single screenshot form the video would sufice (e.g. to demonstrate hand placement in various techniques).
This section describes how to install it based on your operating system.
If you are using linux chances are that you don’t really need me to tell you how to install it.
sudo dnf -y install ffmpeg
sudo apt-get install ffmpeg
brew install ffmpeg
Windows users will have to install and get familiar with wsl, first. Then:
sudo apt-get install ffmpeg
From now on all command we provide will need to go via wsl unless explicitly specified.
To make long instructionals more usable:
- easier to search
- split in digestable chunks
we will have to split them.
Luckily, most of them contain multiple scenes each starting with a title screen, like the ones shown below:
This makes it possible to use ffmpeg in order to detect scenes. The idea is to detect frames that have noticable differences than the previous one.
This can be done using a command like:
ffprobe -show_frames -of compact=p=0 -f lavfi "movie=instructional.mkv,select=gt(scene\,0.8)" | awk -F "|" '{print $7}' | cut -f2 -d"="
The command above does the following:
- collect frames that have 80% difference in pixels from the previous one (you can play around with this value
- grab the value of the 7th column of the output that contains the timestamp
- keep only the numeric value
The result will be the timestamps in seconds of each different scene.
There are many things you can do with this timestamp. Below are some examples:
The script below will attempt to detect chapters and split the long video accordingly.
#!/bin/bash
VIDEO=$1
EXTENSION="${VIDEO##*.}"
FRAMERATE=5
SCALE="512:-1"
begin="00:00:00"
scene=1
# For each timestamp:
ffprobe -show_frames -of compact=p=0 -f lavfi "movie=$1,select=gt(scene\,0.8)" 2> /dev/null | awk -F "|" '{print $7}' | cut -f2 -d"=" | while read timestamp; do
#Keep the integer part of the timestamp
ts=`echo $timestamp | cut -d"." -f1`
#Convert timestamp to time using the HH:mm:ss format
hours=`expr $ts / 3600`
if [ $hours -lt 10 ]; then
hours="0$hours"
fi
minutes=`expr $ts % 3600 / 60`
if [ $minutes -lt 10 ]; then
minutes="0$minutes"
fi
seconds=`expr $ts % 60`
if [ $seconds -lt 10 ]; then
seconds="0$seconds"
fi
end="$hours:$minutes:$seconds"
# Perform the split
ffmpeg -y -i $1 -ss $begin -to $end scene-$scene.$EXTENSION < /dev/null 2> /dev/null
begin="$hours:$minutes:$seconds"
let scene=$scene+1
done
If the script isn’t accurate enough, you may need to tinker the pixel percentage.
Even if splitting a large video into smaller chunks, those chunks won’t be small enough. Sometimes, you just need to get a glimpse of a technique in order to remember what it is about. It often helps using and embedding animated images direcly inside your notes (assuming they are in a digital format).
Here’s an example an animated image that is demonstrating the `pumping method` for breaking grips:
#!/bin/bash
VIDEO=$1
BEGINNING=${2:-"00:00:00"}
END=${3:-"00:01:00"}
FRAMERATE=${4:-5}
SCALE=${5:-"512:-1"}
NAME="${VIDEO%.*}"
EXTENSION="${VIDEO##*.}"
ffmpeg -y -i "$VIDEO" -r $FRAMERATE -vf scale=$SCALE -ss $BEGINNING -to $END $NAME.gif < /dev/null 2> /dev/null
done
The script can then be invoked like:
create-animated-gif.sh <your vide here> <beginning HH:mm:ss> <end HH:mm:ss>
The challenge here is to spot and keep track of the beginning and end times. In future posts I am going to provide tips on how to simplify that as much as possible.
Sometimes you just want to extract a single image instead of an animated gif. This can be especially useful if you intend to print your notes on paper.
ffmpeg -i <your video here> -ss <timestamp in HH:mm:ss> -vframes 1 screenshot.png < /dev/null 2> /dev/null
- 01. Hackers guide to Jiu Jitsu: intro wordpress version github version
- 02. Hackers guide to Jiu Jitsu: ffmpeg wordpress version github version
- 03. Hackers guide to Jiu Jitsu: mplayer wordpress version github version
- 04. Hackers guide to Jiu Jitsu: markdown wiki wordpress version github version
- 05. Hackers guide to Jiu Jitsu: flowcharts wordpress version github version