Sometimes you have a video that won't play easily on your system. One example that comes immediately to mind is when you have a .mkv (Matroska) video on a Mac. Google around, and you'll learn you need to download a particular player, or a QuickTime plug-in called Perian. There are lots of players and even though Perian is discontinued, you could certainly download what you need to play your file. But there's another easy option you could try that won't require a new player or plug-in! You can use transmuxing to change the video container, resulting in a playable video. Another use case might be editing. Many editing tools won't let you use an .mkv file, requiring .mp4 or similar instead. You may want to do the conversion without losing video quality, then convert back. In this situation, transmuxing can help you preserve video quality, while still making your video usable for your project.
What is transmuxing?
Transmuxing is where you change the video container without re-encoding the entire video. It's fast, maintains the current quality of your video and often doesn't use a lot of processing power. Sometimes it's the solution to all your problems. And sometimes it makes more problems. But today, we'll learn a little bit about how to transmux using FFmpeg. Then for Python users, we'll go over how to do the same FFmpeg commands using the ffmpeg-python library.
Installation
Ffmpeg CLI can be a pain to install. If you have a Mac, there's an easy way to install with homebrew though, and we detail that in the start of the Live Stream to the Browser with FFMPEG CLI and Python.
After you have it installed, test it works by checking the version:
ffmpeg -version
Getting started with FFprobe
Something you can try to see what happens, is to change the ending of your video file. Some containers are interchangeable, and you can get away with just changing the file ending manually, though this isn't best practice. It also won't work to move from .mkv to any of mov, mp4, m4a, 3gp, 3g2, or mj2. Typically, whatever file formats are listed when you ffprobe your video are the endings you can manually change your file ending to.
After you have FFprobe installed, run this command on your video:
ffprobe video.mp4
Instead of video.mp4 put the complete title of your video file. As an example, I tried examining a video I have called test_vid.mov. Here's what the results look like:
ffprobe version 4.4 Copyright (c) 2007-2021 the FFmpeg developers
built with Apple clang version 12.0.5 (clang-1205.0.22.9)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.4_2 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-avresample --enable-videotoolbox
libavutil 56. 70.100 / 56. 70.100
libavcodec 58.134.100 / 58.134.100
libavformat 58. 76.100 / 58. 76.100
libavdevice 58. 13.100 / 58. 13.100
libavfilter 7.110.100 / 7.110.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test_vid.mov':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.83.100
Duration: 00:00:13.35, start: 0.000000, bitrate: 344 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x360, 341 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
From this we can see the different file formats (mov, mp4, m4a, 3gp, 3g2, mj2), and that it's encoded using the h264 codec.
Here's another example, for a file called giant.mkv:
ffprobe version 4.4 Copyright (c) 2007-2021 the FFmpeg developers
built with Apple clang version 12.0.5 (clang-1205.0.22.9)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.4_2 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-avresample --enable-videotoolbox
libavutil 56. 70.100 / 56. 70.100
libavcodec 58.134.100 / 58.134.100
libavformat 58. 76.100 / 58. 76.100
libavdevice 58. 13.100 / 58. 13.100
libavfilter 7.110.100 / 7.110.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
Input #0, matroska,webm, from 'giant.mkv':
Metadata:
title : Jamaica.Inn.1939.720p.BluRay.x264-x0r[FEATURETTE-Shipwrecked in a Studio: A Video Essy with Donald Spoto]
encoder : libebml v1.3.0 + libmatroska v1.4.1
creation_time : 2015-05-25T15:34:54.000000Z
Duration: 00:13:06.77, start: 0.097000, bitrate: 2211 kb/s
Chapters:
Chapter #0:0: start 0.000000, end 785.614000
Metadata:
title : Chapter 1
Stream #0:0(eng): Video: h264 (High), yuv420p(tv, bt709, progressive), 1280x720 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 180k tbc (default)
Metadata:
BPS : 2049790
BPS-eng : 2049790
DURATION : 00:13:06.765000000
DURATION-eng : 00:13:06.765000000
NUMBER_OF_FRAMES: 18863
NUMBER_OF_FRAMES-eng: 18863
NUMBER_OF_BYTES : 201587950
NUMBER_OF_BYTES-eng: 201587950
_STATISTICS_WRITING_APP: mkvmerge v7.4.0 ('Circles') 64bit built on Dec 12 2014 15:04:11
_STATISTICS_WRITING_APP-eng: mkvmerge v7.4.0 ('Circles') 64bit built on Dec 12 2014 15:04:11
_STATISTICS_WRITING_DATE_UTC: 2015-05-25 15:34:54
_STATISTICS_WRITING_DATE_UTC-eng: 2015-05-25 15:34:54
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:1(eng): Audio: ac3, 48000 Hz, stereo, fltp, 160 kb/s (default)
Metadata:
title : Stereo
BPS : 160000
BPS-eng : 160000
DURATION : 00:13:06.720000000
DURATION-eng : 00:13:06.720000000
NUMBER_OF_FRAMES: 24585
NUMBER_OF_FRAMES-eng: 24585
NUMBER_OF_BYTES : 15734400
NUMBER_OF_BYTES-eng: 15734400
_STATISTICS_WRITING_APP: mkvmerge v7.4.0 ('Circles') 64bit built on Dec 12 2014 15:04:11
_STATISTICS_WRITING_APP-eng: mkvmerge v7.4.0 ('Circles') 64bit built on Dec 12 2014 15:04:11
_STATISTICS_WRITING_DATE_UTC: 2015-05-25 15:34:54
_STATISTICS_WRITING_DATE_UTC-eng: 2015-05-25 15:34:54
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
This one contains streams of data for video and audio. We can see its file formats are matroska or webm and it's also encoded using the h264 codec.
We can convert these files to one another using transmuxing as long as we want to keep using the h.264 codec. If we wanted to use one of these with an h.265 codec, then we'd need to transcode.
Transmuxing
The command to transmux is simple and it looks like this:
ffmpeg -find_stream_info -i YOUR_VIDEO.mkv -map 0 -codec copy -codec:s mov_text NEW_VIDEO.mp4
You're copying the codecs, and you're just changing the file format. You can move back and forth without losing video quality. By adding -map 0, you let ffmpeg know you want to keep all the streams and data in your original video.
Transmuxing with ffmpeg-python
You might want to use ffmpeg with python. In that case you'll need to do the following:
- Install ffmpeg-python, with this command:
pip install ffmpeg-python
- Import it into your code with import ffmpeg.
- The basic code sample is really simple, here's all you're doing:
` import ffmpeg
( ffmpeg .input('giant.mkv') .output('output_giant.mov') .run() ) `
The movie will contain your metadata and be playable!
Conclusion
You can transmux between files that used the same codec for compression. If you want to compress with a different codec, you'll have to do transcoding. Transmuxing can be helpful when you need a different format, want to preserve quality and you are okay with using the same codec.
Erikka Innes
Developer Evangelist
Follow our latest news by subscribing to our newsletter
Create your free account
Start building with video now