5+ Linux Video Editing Tool Tips

Finding a video editor in Linux that isn’t severely handicapped or come with an extreme learning curve is difficult. But this article isn’t about fancy video editors. As it turns out many of the things you need to get done are easiest with a few command-line tools. The packages you’ll want to install are mpv, ffmpeg, mencoder, normalize, and sox.

Create a Slideshow Video from Images

Assuming you have 6 images in a folder names frames numbered 00001.jpg through 00006.jpg you would use the following command to make an 18 second long video of them where each picture is shown for 3 seconds.

ffmpeg -framerate 6/18 -i frames/%05d.jpg -codec copy output.mp4 1 2 ffmpeg - framerate 6 / 18 - i frames / % 05d.jpg - codec copy output .mp4

The way to determine the frame rate is to put the number of pictures you are using in as the numerator (first number) and the amount of seconds you want as the video length as the denominator (the number it’s divided by). The “%05d.jpg” will grab all images that start with 5 digits. If you have a different prefix on your image like “IMG_” name with only 3 digits you would write this as “IMG_%03d.jpg” . The “-codec copy” is optional but will help in cases where the images won’t render in the video otherwise (like in concatenating incompatible videos detailed below).

And there you have it! A slide show from a set of images!

Concatenating Incompatible Videos

Surprisingly simple concatenation doesn’t always work. Videos have all sorts of things that are incompatible with each other which may include frame rate and color scheme. Now a sure fire way to get it done is to extract all the video frames from each video into images and then render a new video from those images.

mkdir frames ffmpeg -i input.mp4 -r 30 -qscale:v 2 frames/%05d.jpg ffmpeg -start_number 481 -i input2.mp4 -r 30 -vframes 100 frames/%05d.jpg 1 2 3 4 mkdir frames ffmpeg - i input .mp4 - r 30 - qscale : v 2 frames / % 05d.jpg ffmpeg - start _ number 481 - i input2 .mp4 - r 30 - vframes 100 frames / % 05d.jpg

The first command will dump all of the video frames out in high quality JPEG images. Assuming we get 480 frames of the first video then we want to start the second video right after that with “-start_number 481” . The “-vframes 100” is optional and is used if we only want to take 100 frames from the second video. It is very important to set how many frames per second you want in the output with “-r 30“. If you have a slideshow video that shows 1 frame every so many seconds it needs to create the additional frames by having the frame rate set with “-r“.

Now to merge the two sets of videos together simply use the slideshow command above and put the input frame rate as 30. Using a different number than the one you extracted with will change the video speed.

Fade Outs and Fade Ins with Sox

This on is rather straight forward.

Spec: fade [type] fade-in-length [stop-position(=) [fade-out-length]]

The most common type of fade (IMO) is a straight line. Sox calls this a triangle so the type parameter will be a “t“. After that the first value is the length of the fade in on the audio. The second parameter after type is the hard ending of the audio file (where you cut/crop/trim it to end) and the third parameter after type is how long of a fade for the ending. You can set the stop position to “0” to no shorten the audio file.

To make an audio file fade out during the last 7 seconds you would type:

sox input.wav output.wav fade t 0 0 7 1 2 sox input .wav output .wav fade t 0 0 7

Extract Audio or Convert Video

With both mpv and ffmpeg this is stupidly simple. Basically when you tell either of these what file name you want as output it automatically renders that output file.

Extract audio:

ffmpeg -i MVI_8308.MOV -nv MVI_8308.wav mpv MVI_8308.MOV --no-video -o MVI_8308.wav 1 2 3 ffmpeg - i MVI_8308 .MOV - nv MVI_8308 .wav mpv MVI_8308 .MOV -- no - video - o MVI_8308 .wav

These will both work without specifying the no video option.

Convert video:

ffmpeg -i MVI_8308.MOV MVI_8308.mp4 mpv MVI_8308.MOV -o MVI_8308.mp4 1 2 3 ffmpeg - i MVI_8308 .MOV MVI_8308 .mp4 mpv MVI_8308 .MOV - o MVI_8308 .mp4

These generally get things done for you without the hassle. If you want to get nit-picky about your output format you can look up the documentation on these for further options.

Substitute Audio for a Video

Use mpv! mpv makes a lot of helpful assumptions when it gets the job done. If you have a video file and an audio file in the same directory with the same basename then it will play the audio of the external audio file rather than the internal audio channel. If you have files named epicness.mp4 and epicness.wav in the same directory and you want them merged into one file all you need to do is play the video file with mpv and specify an output file.

mpv epicness.mp4 -o result.mp4 1 2 mpv epicness .mp4 - o result .mp4

Since mpv chooses the external audio file over the internal one the output file named result.mp4 now is the original video with replaced audio.

Video and Audio Sync

I started playing violin recently and I’ve been recording videos of my weekly progress. Apple’s devices take excellent video and most of the time it will have decent audio. But in the case of violin playing the audio sounds warped and warbly. To get good audio (which is very important!) I needed a separate audio source. In my case I used two microphones to record stereo to the PC. After transferring the video to the computer I needed to replace the audio.

I named the audio file the same name as the video so mpv would play back the external audio file “violinweek6.mov” and “violinweek6.wav“. I ran “normalize-audio” on the wav file to get the correct decibel level and then started watching the video and audio file together by simply typing “mpv violinweek6.mov” . Now while watching the video I experimented with the audio sync by pressing CTRL - and CTRL + to switch the sync by 100 milliseconds. I found that the audio was roughly -400 milliseconds seconds off. But when I set an option for mpv to change the audio sync “–audio-delay=-0.4” and specified an output file – it didn’t move the audio/video sync.

I did a quick Google search and found the following option.

ffmpeg -i input.mov -itsoffset 0.4 -i input.mov -map 0:0 -map 1:1 -acodec copy -vcodec copy synced.mov 1 2 ffmpeg - i input .mov - itsoffset 0.4 - i input .mov - map 0 : 0 - map 1 : 1 - acodec copy - vcodec copy synced .mov

This made a new video file called “synced.mov” and the changes were there. But it still wasn’t perfect. The video player only moved in chunks of 100 milliseconds, but I needed a smaller change than that. So I simply repeated the same command above on the synced file and played a game of hotter or colder. First I tried altering the video 0.05 seconds and was colder. So I repeated that with -0.05 and was hotter. Next I did it for 0.025 and 0.0125 each with positive or negative and each on the hotter result until the audio sync felt just right. I ended up with files named “synced1.mov” through “synced4.mov” with the last one being the one I publish.

And that’s a not too difficult way to sync video and audio.

Add it to Bash

You can add these as functions to your .bashrc file so you won’t have to type them out each time. Here are 4 of them I’ve put into my own .bashrc file.

brighten() { INPUT_FILE=$1 OUTPUT_FILE=$2 ffmpeg -i "$INPUT_FILE" -vf curves=preset=lighter -c:a copy "$OUTPUT_FILE" } slideshow() { FRAMERATE=$1 IMAGE_SET=$2 OUTPUT_FILE=$3 ffmpeg -framerate $FRAMERATE -i "$IMAGE_SET" -codec copy "$OUTPUT_FILE" } fadeout() { INPUT_FILE=$1 OUTPUT_FILE=$2 FADE_OFFSET=$3 FADE_LENGTH=$4 sox "$INPUT_FILE" "$OUTPUT_FILE" fade t 0 $FADE_OFFSET $FADE_LENGTH } videosync() { INPUT_FILE=$1 OUTPUT_FILE=$2 OFFSET=$3 ffmpeg -i $INPUT_FILE -itsoffset $OFFSET -i $INPUT_FILE -map 0:0 -map 1:1 -acodec copy -vcodec copy $OUTPUT_F } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 brighten ( ) { INPUT_FILE = $ 1 OUTPUT_FILE = $ 2 ffmpeg - i "$INPUT_FILE" - vf curves = preset = lighter - c : a copy "$OUTPUT_FILE" } slideshow ( ) { FRAMERATE = $ 1 IMAGE_SET = $ 2 OUTPUT_FILE = $ 3 ffmpeg - framerate $FRAMERATE - i "$IMAGE_SET" - codec copy "$OUTPUT_FILE" } fadeout ( ) { INPUT_FILE = $ 1 OUTPUT_FILE = $ 2 FADE_OFFSET = $ 3 FADE_LENGTH = $ 4 sox "$INPUT_FILE" "$OUTPUT_FILE" fade t 0 $FADE_OFFSET $FADE_LENGTH } videosync ( ) { INPUT_FILE = $ 1 OUTPUT_FILE = $ 2 OFFSET = $ 3 ffmpeg - i $INPUT_FILE - itsoffset $OFFSET - i $INPUT_FILE - map 0 : 0 - map 1 : 1 - acodec copy - vcodec copy $OUTPUT_F }

The dollar values are the order of the parameters you give. To brighten a video with the brighten function I have above you would type

brighten input.mp4 output.mp4 1 2 brighten input .mp4 output .mp4

After adding these new bash functions to your rc file you can load them into your current shell by typing:

. ~/.bashrc 1 2 . ~ / .bashrc

Summary

It’s amazing how powerful the command line tools are for video editing in Linux. It boggles my mind why it’s easier to edit videos in the console than with a Linux GUI video editor. mpv is actually a continuation of the excellent mplayer/mencoder open source project. It makes so many excellent assumptions I’m quite happy with it.

Have fun with these! If you have any great tips to share please do in the comment section below! As always I hope you found this educational and enjoyable! Please feel free to comment, share, subscribe to my RSS Feed, and follow me on twitter @6ftdan!

God Bless!

-Daniel P. Clark

Image by Michael Wilson via the Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Generic License