Reversing a video file on Linux

How to use the commands ffmpeg & sox to reverse a video file on the Linux command line.

A good video editing effect is the reverse. It works well in action shots where the video is paused for a moment before being reversed. Later versions of my preferred video editor kdenlive, supports reversing videos directly from the clips within the project tree. However, the current version I’m using with my Linux distribution doesn’t have the feature, so I looked into how to reverse the video using only command line tools.

Let’s take a look at the finished effect. Below is a short clip where my son jumps into a cupboard and his clothes fall to the floor. This is achieved using a rotoscoping technique. I wanted the video to reverse so that the clothes jump back up from the floor and my son jumps backwards out of the cupboard.

It makes him laugh every time he watches it.

To reverse any video on the Linux command line, you need to do it five simple steps which are outlined below. However, before you start you’ll need to ensure that you have both the ffmpeg and sox commands installed on your machine. On a Debian/Ubuntu Linux distribution use the following apt-get commands to update your packages and install the required tools.

sudo apt-get update
sudo apt-get install ffmpeg sox

Step 1 - Exact the audio from the video

Beside reversing the video, we also need to reverse the audio. So the first step in the process is to extract the audio track from the video and save it as a .wav file. We use ffmpeg to process the video file input.mp4 and dump the audio to its own file.

ffmpeg -i input.mp4 -vn -ac 2 audio.wav

Step 2 - Reverse the audio

The second step involves using the sox command to reverse the audio. We pass in the audio file created in step 1 and produce a new audio file called backwards.wav

sox -V audio.wav backwards.wav reverse

Step 3 - Extract each video frame as an image

The third step involves extracting each frame of the video and saving it as an image file. As the ffmpeg command reads the video file it creates sequentially numbered jpg files starting from one. This will create a lot of jpg files depending on how long your video clip is. For example a ten second clip filmed at thirty frames per second will produce 300 image files.

We create the numbered image files so that when we reassemble the video we can feed the images back into the ffmpeg command in reverse order.

So this is how you create the individual images for each frame

ffmpeg -i input.mp4 -an -qscale 1 %06d.jpg

Step 4 - Reassemble the images & audio

The forth step is to reassemble all the images back into a video merging in the reversed audio. As the individual frame images were created in order, the later frames will have the latest modification date/time. So in the command below we are using the list command with the -t switch which sorts the jpg files by modification time, with the newest files being first in the list.

cat $(ls -t *.jpg) | ffmpeg -f image2pipe -vcodec mjpeg -r 30 -i - -i backwards.wav -vcodec libx264 -vpre slow -crf 20 -threads 0 -acodec flac reversed.mkv

We then pipe the list of files into the ffmpeg command supplying the backwards.wav file as the audio input. After the command has run we are left with a new video file called reversed.mkv

You also need to supply the frame rate that the original video was captured in. In the above example I’m using a frame rate of thirty frames per second -r 30. If the video was originally filmed on an action camera like the GoPro and you’d used sixty frames per second, then you would need to change the value of the -r switch to 60.

Step 5 - Delete all the image files

Finally you can delete all the frame image files by using the rm command.

rm *.jpg

Slowing down the reverse

Sometimes it’s fun to do a slow motion reverse. To achieve this you also need to slow down the audio. You can use an additional sox command after step two to slow the backwards.wav file to half its original speed.

sox -V backwards.wav halfspeed.wav speed 0.5

Then when you’re reassembling the video you would include the halfspeed.wav file and reduce the frame rate by half.

cat $(ls -t *.jpg) | ffmpeg -f image2pipe -vcodec mjpeg -r 15 -i - -i halfspeed.wav -vcodec libx264 -vpre slow -crf 20 -threads 0 -acodec flac reversed.mkv