MBR¶
media.transcode.mbr
The Sapsan transcoder changes codecs, bitrate, and resolution and prepares a multibitrate ladder (MBR). Several output renditions can use a single source video track: it is decoded once, and the resulting frames are passed to the output encoders.
Each output is described by a rule: which source track to select and what to produce from it. Selection can be based on language or content type so that the configuration keeps working after the input track layout changes. This matters when switching between primary and backup sources: their track numbers and codecs may differ.
How Sapsan builds an aligned ladder¶
Multibitrate transcoding creates several renditions of the same video. They differ in frame size and bitrate and may use different codecs, but must show the same picture at the same moment. Sapsan processes them as a single video pipeline with a shared timeline.
One decode for all renditions¶
Each source video track has one decoder for all its output renditions. An incoming compressed frame is decoded once; the resulting picture is passed to scaling and encoding for each rendition. For three output renditions, Sapsan decodes the input once and performs three output encodes.
Adding renditions adds work for the output encoders and image transformations. The cost of decoding the source is not multiplied by the number of renditions. This is especially important for demanding input video: the shared decoder serves the entire ladder.
Matching timestamps for corresponding frames¶
Each source picture receives the same presentation timestamp, PTS, in all its output renditions. The timestamps themselves match, not just the nominal frame rate. The player can match corresponding pictures across renditions at the same media time.
For example, at 25 frames/s, presentation times in seconds look like this:
| Picture | 1080p H.264 | 720p HEVC | 360p AV1 |
|---|---|---|---|
| First | 2.000 | 2.000 | 2.000 |
| Next | 2.040 | 2.040 | 2.040 |
| Another | 2.080 | 2.080 | 2.080 |
For renditions of one source track, the server uses the precision of the source timeline: source PTS values are not rounded to integer frame numbers just for encoding. Different encoder processing speeds do not give the renditions independent clocks either.
DTS defines decoding order and depends on how each encoder reorders frames. With B-frames, DTS may differ from PTS and between codecs. The shared PTS identifies the same picture across renditions.
Synchronized keyframes¶
With aligned GOP settings, keyframes in different renditions fall at the same presentation times. The player receives aligned switching points: after choosing another rendition, it continues from the same time position. The segmenter can place segment boundaries at matching keyframes.
For an aligned ladder, set the same gop_size and gop_structure on its video outputs. For example, at 25 frames/s with gop_size: 50, the scheduled keyframe interval is two seconds for every rendition. In the example below, both renditions use one source track and the same GOP structure.
Combining tracks into a shared output stream¶
Encoders may take different amounts of time to prepare a frame, especially when using different codecs or B-frames. Sapsan combines video encoder results and audio tracks on the shared media timeline: the output interleaver buffers frames and orders them by DTS. The completion time of an individual encode therefore does not determine frame order for the entire stream.
A shared decoder, matching PTS values, and aligned keyframes give the player a ladder prepared for adaptive playback. It can select a suitable bitrate while preserving the video's time position. Source audio/video synchronization also matters: ordering output frames does not by itself correct an incorrect audio offset in the input signal.
Configuration¶
Configuration is managed through the central API. The examples use YAML object notation; for example, source: {content: audio} is sent in JSON as "source": {"content": "audio"}. Tagged YAML notation is also supported: source: !content audio.
Suppose a stream receives these signal variants:
| Input | Video | Audio |
|---|---|---|
| Primary, MPEG-TS over UDP | v1, HEVC, 1920×1080 |
a1: English MPEG Audio, eng; a2: Russian AC-3, rus |
| Backup, HLS | v3, H.264, 1280×720 |
a4: Russian AAC, rus |
The rules below select video and Russian audio by their properties. No separate transcoder configuration is needed for the backup input:
streams:
- name: tv1
inputs:
- udp: {host: 239.0.0.1, port: 5000}
- hls: {url: https://backup.example.com/tv1/index.m3u8}
transcoder:
output:
- source: {best_quality: video}
codec: {set: h264}
bitrate: 2800000
params:
video:
gop_size: 50
gop_structure: ibbbp
resize: {fit: {width: 1920, height: 1080}}
- source: {best_quality: video}
codec: {set: h264}
bitrate: 1200000
params:
video:
gop_size: 50
gop_structure: ibbbp
resize: {fit: {width: 1280, height: 720}}
- source: {language: rus}
codec: {set: aac}
bitrate: 128000
Video from either input produces two H.264 renditions, and the selected Russian audio track is prepared for AAC delivery. The primary input's English track does not match the audio rule. LSI switches the inputs; the source rules select tracks from the input that is already active.
Selecting the source track¶
source |
How tracks are selected in a live stream |
|---|---|
{exact: v1} or {exact: a2} |
One track with the specified input ID. This is a logical Sapsan ID, not an MPEG-TS PID. |
{content: video} or {content: audio} |
All tracks of the specified type. One rule can create multiple outputs. |
{best_quality: video} or {best_quality: audio} |
One track of the specified type with the highest declared bandwidth. |
{language: rus} |
All audio tracks whose language is exactly rus, regardless of codec or ID. |
{language_codec: [rus, aac]} |
All audio tracks with both language rus and codec aac. |
{codecs: [pcma, pcmu]} |
All tracks whose codec belongs to the specified nonempty set. |
The language comes from the source metadata. The value is matched exactly: rus and ru are different strings. Without a language tag, a language rule does not match. If the input has several Russian tracks, language: rus selects each one; for narrower selection, combine language with codec or use a specific ID.
best_quality compares declared bitrate, not resolution or visual quality. Missing bandwidth is treated as zero; ties select the last matching track in the current input description. Selection happens when the transcoder is configured. Updating the bitrate estimate alone does not automatically switch between tracks.
Each rule runs independently. Several rules using the same source create several output renditions. The rules language: rus and content: audio both process the Russian track; this does not mean “Russian, or any audio if Russian is absent.”
What changes when switching inputs¶
When the input track layout or significant parameters change, Sapsan matches the rules against the new track description and reconfigures processing. Changes to track IDs and order, codecs, and decoding parameters are considered. For audio, language is also considered.
In the example above, language: rus selects a2 on the primary input and a4 on the backup. The rule exact: a2 selects nothing on the backup input. The rule language_codec: [rus, ac3] deliberately restricts processing to Russian AC-3 and does not match the backup AAC.
Output track numbers may change when the input changes. In particular, an already suitable AAC-LC track may pass through without re-encoding and retain its input ID; this is an optimization applied after source selection. Reconfiguring decoders and encoders can also cause a transition in the output. Selection rules accommodate different source layouts but do not by themselves guarantee seamless switching.
Transcoding all audio tracks¶
For a multilingual TV channel, you can preserve the full available language set and convert the audio to AAC:
transcoder:
output:
- source: {best_quality: video}
codec: {set: h264}
bitrate: 2000000
- source: {content: audio}
codec: {set: aac}
bitrate: 128000
If the primary input has two audio tracks, the audio rule processes both. If the backup has only one, the output has one. This selection processes the available source audio tracks; it does not enforce a fixed number of outputs.
Language selection uses the input metadata. In the current live path, the language tag is not copied to re-encoded audio; passthrough preserves it. Keep this in mind when checking language labels in the player.
Transcoding only specified codecs¶
For sources whose audio may arrive as PCMA, PCMU, or AAC, you can configure G.711 conversion separately from AAC passthrough:
transcoder:
output:
- source: {best_quality: video}
codec: {set: h264}
bitrate: 2000000
- source: {codecs: [pcma, pcmu]}
codec: {set: aac}
bitrate: 128000
- source: {codecs: [aac]}
codec: same
The codec-set rule selects both PCMA and PCMU without depending on the audio track number. Another rule preserves existing AAC without re-encoding. If G.711 and AAC are both present, both rules run. A codec outside these sets, such as AC-3, is not selected by this example's audio rules.
If no track matches¶
In the live transcoder, a rule with no matches creates no output track. For example, the absence of rus does not select English audio or generate silence. Other matching rules continue producing their outputs.
The configuration model includes if_missing, but the live path does not implement its fail, blank, and substitute modes. Do not rely on them to substitute a missing track when sources switch.
The examples above include actual encoding. If all rules use only codec: same, the entire stream enters passthrough mode; such a configuration cannot filter tracks using source.
Codecs and parameters¶
codec: {set: h264}— transcode to the specified codec. Parameter details are described in video encoding.codec: samepreserves source frames without re-encoding.- Aligned ladder: outputs using different codecs from one video track maintain aligned timestamps and keyframes.
gop_sizeandgop_structure: control GOP length and structure for aligned MBR segments.- G.711 audio: conversion to AAC or Opus while preserving the timeline is also described in audio encoding.
- Auxiliary tracks: supported subtitle and JPEG preview tracks may be preserved through passthrough. Check the final stream layout, not just the encoding rules.
Resizing¶
resize |
Behavior |
|---|---|
{scale: {width: 1280, height: 720}} |
Scales to the exact specified dimensions. |
{fit: {width: 1280, height: 720}} |
Fits the image while preserving its aspect ratio, adding padding if needed. |
{crop: {width: 1280, height: 720}} |
Crops the image to the specified dimensions. |
Verification¶
Check the input metadata and final track layout in the stream statistics. Then open the master playlist http://server/streaming/v/tv1/index.m3u8 and check the output renditions and audio languages.
Switch the stream to the backup and check it separately: which video was selected, how many audio tracks were produced, and whether the required languages were preserved. To diagnose reconfiguration, use the encode backend selected input tracks messages and the input-to-output mapping table encode backend stream mapping in the streamer logs.