Video editing from the command line I previously posted about [capturing video in Linux](converting-vhs-and-dv-to-modern-formats---part-1.html). While this isn't exactly part 2 of that post there is enough crossover to warrant a link. This post is about how I have strangely found video editing to be much easier from the command line than a gui app. --- Firstly, there isn't a shortage of gui apps for editing video on Linux for very basic editing. My requirements are very simple. I need to be able to cut and join various video files, and product 2 output files. A file for hosting on the web and a file for archival purposes. Problem 1 - Audio Sync ---------------------- I started out myself with [pitivi](http://www.pitivi.org/) and tried a few others. My trouble with each editor was speed and accuracy (also my brain). On some videos I had to adjust the audio sync and was driven mad by moving audio tracks around. I had alot of trouble knowing if the audio was starting too early or too late and which way to move the audio to correct it. With a gui editor, this involves click and dragging an audio track one way or another (for accuracy, you have to zoom in very far). Once zoomed in and you move the track, you then need to zoom out, place the play head, click play and then make a judgement if you made it better or worse. For some reason, my brain could never tell exactly which way to move the audio until it was way too far in the wrong direction. This was a source of frustration that I initially solved using ffmpeg on the command line. Using ffmpeg I wrote a very simple sh script to output a small time slice of the video many times with different audio offsets. Then it was simply a matter of watching each video and picking the right one. The resulting audio offset that was used for that video can then be used on the entire clip. Firstly, start by creating a small snippet of video where you will clearly be able to see if the video is synced up. ffmpeg -i bigclip.mp4 -c copy -ss 00:01:55 -to 00:02:00 Small.mp4 Now we will use the following script #!/bin/sh # fixaudiodelay.sh Offset="${2}" inputFile="${1}" outputFile="${inputFile%%.*}-delayed${Offset}.mp4" out="${3:-$outputFile}" ffmpeg -i "${inputFile}" -itsoffset "${Offset}" \ -i "${inputFile}" -map 0:v -map 1:a -c copy "${out}" The script will take parameter 1 is the clip, and parameter 2 is the audio offset. We can use `seq` to generate a list of offsets to try and `xargs` to run them. seq -2.0 .1 2.0 | xargs -n1 ./fixaudiodelay.sh Small.mp4 The result is 41 clips with .1 second offset difference. Play them all and find the best offset. Then when you could use `./fixaudiodelay.sh BigClip.mp4 -1.7` (or whatever was the best offset) to correct the entire file. Problem 2 - Perfect splitting ----------------------------- The second problem I had with gui editors, is that many home videos are completely different scenes butted up against each other on the tape. When transferring these to a new modern format, we want our audience to be able to skip the scenes. With the gui editors, again we have the problem of accuracy along with the inability to at once, save all the clips from the single file. Say you have 4 distinct clips in a file. How can you mark each clip as a separate file then press encode and walk away? You can't you would have to create 3 separate projects and encode each one separately. Solving it with ffmpeg is easier than you might think. When I showed cutting a clip earlier, you can use the `-ss` parameter to declare where to start from in the clip, and the `-to` parameter to declare the end. How I've solved it is like this. 1. Create a track file which lists all the clips start, end and titles. I chose to separate each clip by a line, and each parameter by a `-` dash. Eg 00:00:00-00:10:05-SnowTrip 00:10:05.6-00:13:02-PlayingAtThePark 2. I came up with the start and end positions, simply by marking down the times while watching the clip using mpv or vlc. However, the proof is in the pudding, so I use ffmpeg with some parameters to produce test video files. These won't be good enough quality to upload to the web, but are sufficient for verifying the time stamps and are very quick to encode and see the results. **Note** _You can't use the `copy` codec when cutting clips. As the keyframes are not recreated_ while IFS=- read START END TITLE do OUTFILE="${TITLE}-Test.mp4" ffmpeg -nostdin -i BigClip.mp4 -c:v libx264 \ -c:a aac -ss $START -to $END -preset ultrafast \ $OUTFILE done < tracks.txt 3. After viewing the resulting files, I can make minute adjustments to the track file so the clips are perfect. Then I adjust for a better file for the web by changing the preset to `veryslow` and adding the following parameters -crf 23 -movflags faststart 4. Additionally in some cases, I add some video filters. I've found the following work well:
| Desired affect | Parameter |
| Increase volume | -filter:a "volume=2.0" |
| Deinterlace | -vf "yadif" |
| Archival Quality | Replace libx264 with libx265 |