Video Snippets 🔗

Posted by MĂ©dĂ©ric Ribreux 🗓 In kb/snippets/

#video #snippets


When you want to deal with a movie collection, you need some good tools to manipulate video files. Most of the time, command-line tools like ffmpeg, mkvmerge, etc. are better than GUI tools with limited options and parameters. This page is a way to easily remember the different uses of those tools...

Merge video files and subtitles in a single file

You get video files on the web and very often, there is no subtitles. You have to find yourself subtitles files (.srt for example), test them as they can be bad synchronized with the movie and you have to tell your video player to use this file... For me it is a real pain in the ass because watching a movie should just be a "launch the video, period" operation, nothing more.

After fighting with lots of srt files for subtitles, I've found that Mastroska container can incorporate srt files. Inserting those files is very easy with a command-line tool called mkvmerge which can be found in mkvtoolnix Debian package.

Here is the way to build an mkv file from an avi (or mp4) and an srt file:

mkvmerge -o new_movie.mkv the_movie.avi

And there you have it!

Change the aspect ratio for bad encoded movies

Sometimes I grab movie files with very bad aspect ratios. The easy workaround is to use VLC or mpv and change the aspect ratio in the interface. But each time you launch the movie, you have to test and find the real aspect ratio. This is also a real pain in the ass... but you can change this by using gentlemen tools.

Just ask mkvmerge to change the declared aspect ratio in the Matroska container:

mkvmerge -o My_Movie.mkv --aspect-ratio 0:16/9 the_movie.avi

Everything is done with aspect-ratio option. 0 means that we are declaring the aspect ratio for the track 0 (which is often the video track you want to correct). 16/9 is a way to declare a 16/9 ratio. You can use float numbers too:

mkvmerge -o My_Movie.mkv --aspect-ratio 0:2.35 the_movie.avi

Just use VLC or mpv to find the best aspect ratio and then, use mkvmerge to build a nice "just launch the video" movie!

Concatenate videos

Want to append a video at the end of another one? The answer is still mkvmerge with a + !!!

mkvmerge -o My_Movie.mkv part_1.avi +part_2.avi +part_3.avi

Extract the audio stream from a video

This time you have to use ffmpeg.

Use ffprobe to find the real audio format:

ffprobe MyMovie.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'MyMovie.mp4':
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2014-11-25 17:23:00
  Duration: 00:51:22.98, start: 0.000000, bitrate: 247 kb/s
    Stream #0.0(und): Video: h264 (High), yuv420p, 1280x720 [PAR 1:1 DAR 16:9], 222 kb/s, 29.97 fps, 30k tbn, 59.94 tbc (default)
    Stream #0.1(und): Audio: aac, 44100 Hz, stereo, fltp, 191 kb/s (default)
      creation_time   : 2014-11-25 17:23:12

You can find that the audio codec is AAC. Now, you can extract the stream into a m4a container like this:

ffmpeg -i MyMovie.mp4 -vn -acodec copy MyMusic.m4a


Be sure to use m4a for file container because some music players don't handle raw AAC streams.

Extract subtitles from an mkv file

The best way to extract subtitles from an mkv file is probably to use mkvinfo and mkvextract from mkvtoolnix.

First, find what is the "channel" of the subtitles:

mkvinfo myvideo.mkv
+ EntĂȘte EBML
|+ Version EBML : 1
|+ Version EBML lue : 1
|+ Longueur maximale de l'identifiant EBML : 4
|+ Longueur maximale de la taille EBML : 8
|+ Type de document : matroska
|+ Version du type de document : 2
|+ Version lue du type de document : 2
+ Segment, taille 98931722
|+ TĂȘte de positionnement (sous-entrĂ©es ignorĂ©es)
|+ EbmlVoid (taille : 187)
|+ EbmlVoid (taille : 4096)
|+ Informations de segment
| + UID de segment : 0xf5 0xfa 0xbc 0x1b 0x23 0x7f 0x01 0x7a 0xa7 0x8f 0x66 0x7b 0xa8 0x11 0x2f 0x6b
| + Application de multiplexage : libmkv 0.6.5
| + Écriture de l'application : HandBrake 0.9.9
| + Échelle de code temporel : 1000000
| + Durée : 1325.366s (00:22:05.365)
|+ Pistes du segment
| + Une piste
|  + Numéro de piste : 1 (identifiant de piste pour mkvmerge & mkvextract : 0)
| + Une piste
|  + Numéro de piste : 3 (identifiant de piste pour mkvmerge & mkvextract : 2)
|  + UID de piste : 7080
|  + Type de piste : subtitles
|  + Signal de laçage : 0
|  + Identifiant du codec : S_TEXT/UTF8
|  + Langue : eng
|  + Signal par défaut : 1
|+ Grappe

There we can find that our subtitles are on the track 3 but must be called track number 2 with the other tools.

Then, you just extract the subtitles to a .srt file like this:

mkvextract tracks myvideo.mkv

Convert a bunch of audio files into Vorbis format

I have a phone that is not able to read modern codecs like opus or aac. So, sometimes I have to convert a bunch of audio albums into Ogg Vorbis files to be able to read them on this smartphone.

I've ended to use this one-liner:

find /media/data/music/artist/ -type f -exec bash -c 'f="$1"; fname=$(basename "$f"); fname=${fname%%.*}; tdir=$(basename $(dirname "$f")); mkdir -p "$tdir"; ext="${f##*.}"; ext="${ext,,}"; if [ "$ext" != "ogg" -a "$ext" != "jpg" ]; then ffmpeg -y -loglevel panic -i "$f" -c:a libvorbis -q:a 8 "./$tdir/$fname.ogg"; else cp "$f" "./$tdir"; fi' _ {} \;

Play a horizontally flipped movie

Sometimes, movies have been horizontally flipped by people who have re-encoded them (most of the time, to reverse watermark to avoid automated copyright infringment detection tools).

To keep the best quality without having to re-encode the file, you can use an ffmpeg filter directly into mpv (and starting it from the command-line, of course):

mpv --vf=lavfi=hflip video.mp4

Read the reference for further details.

Extract part of videos

If you want an accurate cut of a video, you can use the following command:

ffmpeg -i video.mp4 -ss HOURS:MM:SS.MILLISECONDS -to HOURS:MM:SS.MILLISECONDS -c copy -copyts cut.mp4

Placing -ss after -i will take time as ffmpeg will do a precise seeking on the input video. It generaly takes 10 seconds on an hour video. But with this option, you will be able to cut the video at the very beginning of the start time. Otherwise, you will seek on the nearest key frame.

If you want a fast but not accurate cut of the video, place -ss before -i option:

ffmpeg -ss HOURS:MM:SS.MILLISECONDS -i video.mp4 -to HOURS:MM:SS.MILLISECONDS -c copy -copyts cut.mp4

Scale a video for VR with mobile phone

Sometimes, a VR video is put up for high end Virtual Reality headsets like HTC Vive Cosmos or Occulus Rift S or Valve Index. But you can also use them on your smartphone and a VR cardboard.

If your phone support h264:

ffmpeg -v error -i "input.mp4" -c:v libx264 -preset slower -crf 18 -tune film -profile:v high -x264-params mvrange=511 -maxrate 50M -bufsize 25M -vf "scale=2160x1080" -pix_fmt yuv420p -c:a copy -movflags faststart -r 50 "output_h264.mp4"

If your phone support h265/HEVC:

ffmpeg -v error -i "input.mp4" -c:v libx265 -preset slower -crf 23 -tune fastdecode -profile:v main -maxrate 50M -bufsize 25M -vf "scale=2160x1080" -pix_fmt yuv420p -c:a copy -movflags faststart -r 50 "output_h265.mp4"

Some explanations:

Scale and crop a video for VR phone

From 360 Side-By-Side to 180 Side-By-Side

It is a little complex and we have to use two crops to achieve this using only one ffmpeg command. Here is what I have used so far with mild results (don't forget to change timings, as it is written, it only serves to test the job).

For square videos:

ffmpeg -y -ss 00:00:05.000 -i vr.mp4 -to 00:00:10.000 -c:v libx264
-preset slower -crf 18 -tune film -profile:v high -x264-params
mvrange=511 -maxrate 50M -bufsize 25M -filter_complex
-map "[final]" -pix_fmt yuv420p -c:a copy -movflags faststart

For wide videos:

ffmpeg -y -ss 00:00:05.000 -i vr.mp4 -to 00:00:10.000 -c:v libx264
-preset slower -crf 18 -tune film -profile:v high -x264-params
mvrange=511 -maxrate 50M -bufsize 25M -filter_complex
-map "[final]" -pix_fmt yuv420p -c:a copy -movflags faststart

Find all libx264 options

Whenever you want to have maximum of details about a lib support in ffmpeg:

ffmpeg -h encoder=libx264