How-to Use Matroska In/Out with FFmpeg
In this guide, we’ll cover tips and tricks to improve your encoding experience using Matroska In/Out with your FFmpeg scripts/settings. Be warned, the topic is broad, so there’s quite a bit to go through!
This guide contains advanced knowledge, so if you’re confused or get stuck, feel free to contact us.
Requirements
- MistServer installed and running
- FFmpeg installed
Steps in this Guide
- When to Use Encoding
- Why Matroska In/Out and FFmpeg?
- Setup and Usage
- Best Practices & Tips
- Examples
- Troubleshooting
1. When to Use Encoding
Here’s a brief explanation: You will likely want to use encoding when your media is incompatible with your end user’s setup or when the source material you are working with is too high quality and the bandwidth costs would bleed you dry.
The two main components of media delivery are the codec (compression method)
and the protocol
. MistServer covers the protocol part with efficient transmuxing, so you’re set there. However, encoding is needed when you want to change aspects like the resolution
, framerate
, bitrate
, keyframe interval
, or codec
. This is particularly important when the original media isn’t compatible with your intended use or end user.
Important Notice
Encoding will always impact the quality of your stream. You cannot upscale low-quality content and expect high-quality results. In most cases, the best you’ll achieve is matching your input quality.
2. Why Matroska In/Out and FFmpeg?
We provide minimal encoding through FFmpeg, but for more customization, you’ll need to write your own script. Matroska In/Out with FFmpeg (or GStreamer) offers more flexibility. While there is no immediate advantage of one tool over the other, this guide will focus on FFmpeg for simplicity.
3. Setup and Usage
If you have basic knowledge of FFmpeg, the setup is simple. You’ll need to write a script or command that reads from standard input, applies your desired encoding settings, and outputs to Matroska format:
ffmpeg -i - CODEC_OPTIONS -f matroska -
By default, all video and audio tracks are passed to FFmpeg. If you want to use specific tracks or remove certain audio or video tracks, you can do so by specifying optional parameters. You can also have your processing command activate only if specific codecs are missing like AAC
.
MistServer Optional Parameters
- Undo masks on process exit/fail: Determines if source/output track masks should be undone if encoding stops or fails.
- Target stream: Directs the encoded output to another stream within MistServer.
- Source/Output track mask: Controls which processes have access to the incoming and created quality.
- Track inhibitor(s): Uses track selectors to prevent startup if specific tracks are present.
- Source selectors: Determines which audio, video, or metadata tracks should be passed.
Core of CODEC_OPTIONS for FFmpeg
Selection of Audio or Video
FFmpeg primarily works with three track types: video, audio, and metadata. We’ll focus on video and audio here since metadata has limited support in live streams.
You can select the desired track type and number using this syntax: -c:TYPE:NUMBER
, where types are:
v = video
a = audio
If there are multiple tracks, use numbers starting from 0
for the first track. If there’s only one track, you can skip specifying the number.
Examples:
-c:v h264
— Video using H264 software encoding-c:v h264_nvenc
— Video using Nvidia NVENC H264-c:a opus
— Audio using Opus-c:a aac
— Audio using AAC
Video Settings
You’ll want to configure a few key video settings. Always refer to the FFmpeg documentation for codec-specific options.
- Resolution:
-s:v XxY
(e.g.,-s:v 1920x1080
) - Bitrate:
-b:v value
(e.g.,-b:v 2000k
) - Keyframe interval:
-g:v frames_between_keyframes
(e.g.,-g:v 25
) - Framerate:
-r:v framerate
(e.g.,-r:v 30
)
Sometimes a filter like -filter:v fps=30 is more effective than setting framerate directly.
Audio Settings
Audio settings are simpler, but still important:
- Bitrate:
-b:a value
(e.g.,-b:a 128k
) - Channels: -
ac:a value
(e.g.,-ac:a 2 for stereo
) - Sample Rate:
-ar:a value
(e.g.,-ar:a 48000
)
4. Best Practices & Tips
CPU vs Hardware
While FFmpeg works with software encoding by default, hardware encoding is generally faster and more efficient, especially for low-latency or multiple concurrent streams. Most CPUs support hardware encoding, so it’s worth checking if your system can use it.
Check FFmpeg's hardware options or run ffmpeg -encoders
to see available encoders.
Mapping and Multi-process Setup
FFmpeg decodes video/audio before re-encoding, so it’s resource-efficient to process all tracks at once. You can map the same audio/video track multiple times and apply different encoding settings to each one.
ffmpeg -i STREAM/FILE -map v:0 -map v:0 -map v:0 -map a:0 -map a:0 .....
This example maps the first video track three times and the first audio track twice. To then use as 3 separate video tracks (-c:v:0
, -c:v:1
and -c:v:2
) with one audio track when you get to the CODEC_OPTIONS
part of the syntax.
Useful FFmpeg Flags/Tips
Most of these will be shown in practise at our given examples!
Usage of '
or "
will require a script!
MistServer does not handle commands correctly should they include/requre the usage of '
or "
. The solution here would be to convert your command to a bash
script and then using this script instead of the command itself.
Removing Header
FFmpeg always fills in a huge chunk of header information. This is passed in standard out and will end up into MistServer as well. MistServer should ignore this, but it could cause erros in an input when something restarts/reconnects. Causing unintended restarts on the encoder process.
Add the following to the input side of FFmpeg
:
-hide_banner
Removing debug messages
Likewise error messages are passed onto MistServer as well, which can mess up with the input process as well.
Add the following to the input side of FFmpeg
:
-loglevel quiet
This wil remove these debug/error messages. However keep in mind that if you test your FFmpeg command/script outside of MistServer this will hide valueble debug information as well!
Forcing keyframe interval sync
When adding extra video qualities you will likely want keyframes to match, as this is important for proper adaptive bitrate playback for protocols such as HLS or DASH.
-force_key_frames source
This option is set at the end of your CODEC_OPTIONS
.
Matroska cluster size
While normally the Matroska cluster size should be at a size to always contain a keyframe, we've found when reading Matroska progressively setting the cluster time limit to 0 actually stabilizes the ingest quite a lot.
-cluster_time_limit 0
This option is set at the end of your CODEC_OPTIONS
.
Bframes
Without going into too much detail bframes are a method of giving encoding instructions in both the past or future on how to handle frames. This saves you some bandwidth, but on lower latency can cause weird playback behaviour. If you are not concerned with bandwidth I would always recommend removing them.
-bf 0
This option is set at the end of your CODEC_OPTIONS
.
Presets / Tuning
Presets are a big method to reduce CPU/hardware usage. Setting a preset tells FFmpeg how much variance in quality is allowed in favor for speed. Every encoder comes with its own presets and should be looked up. In general the faster the preset, the less resources needed and the better the latency of the encode, but you also take a hit in quality. For the default H264 encoder within FFmpeg the following are available:
ultrafast
superfast
veryfast
faster
fast
medium – default preset
slow
slower
veryslow
Generally these are passed at the end of CODEC_OPTIONS
-preset veryfast
Every encoder has different presets, look them up! For some encoders tuning should be used instead
-strict experimental
Also known as -strict -2
This sets 2 values for FFmpeg:
strict
: strictly conform to all the things in the spec no matter what consequences.
experimental
: allow non standardized experimental things.
This sounds scary, but if your codec just isn't working for "some reason". Chances are you needed to add this setting. FFmpeg has a lot of different versions and you might be using one where a codec isn't fully released yet.