Overview
The Video SDK supports inserting subtitle tracks into MPEG transport stream outputs, including file output and network delivery over UDP or SRT. Subtitles are generated from text subtitle files (ASS or SRT) and can be encoded as bitmap DVB subtitles, as DVB Teletext, or as both in the same output.
Note: Subtitle insertion may require the Closed Caption plugin license.
Subtitle output types
| Output type | Writer codec | Kind | Notes |
|---|---|---|---|
| DVB subtitles | subtitle::codec='dvbsub' |
Bitmap | Supports rendering options such as background, outline and alpha values. |
| DVB Teletext subtitles | subtitle::codec='dvbtxt' |
Text | Formatting may be limited by the Teletext output format. Character sets and the page layout are configured in step 5. |
The same output can contain both subtitle output types at the same time. For example, one subtitle track can be encoded as DVB Teletext with subtitle::codec='dvbtxt', while another subtitle track can be encoded as bitmap DVB subtitles with subtitle.1::codec='dvbsub'.
Input subtitle formats
| Format | Description | When to use |
|---|---|---|
.ass |
Advanced SubStation Alpha | Recommended when the formatting should be stored in the subtitle file itself. ASS files support text formatting through the ASS style header. The sample includes an example.ass file and loads it by default. |
.srt |
SubRip | Plain subtitle text. The formatting is configured with the writer properties (step 4). |
The reader loads subtitle files directly through the external_subtitle property. Multiple subtitle tracks can be attached to the reader at the same time. Each subtitle track can be assigned its own stream ID, output codec, and language metadata.
Ready-to-use samples
| SDK | Path |
|---|---|
| MPlatform | C:\Program Files (x86)\Medialooks\MPlatform SDK\Samples Basic\C#\Subtitle Insertion Sample x64 |
| MFormats | C:\Program Files (x86)\Medialooks\MFormats SDK\Subtitle Insertion Sample x64 |
How to generate and insert subtitle tracks
The subtitle insertion process consists of the following steps:
| Step | What you do | Main properties |
|---|---|---|
| 1 | Prepare or generate subtitle tracks in .ass or .srt format. |
- |
| 2 | Attach one or more subtitle files directly to the reader and assign a stream ID to each track. |
external_subtitle, external_subtitle.stream_id, experimental.out_subtitle_packets
|
| 3 | Configure the writer subtitle codec, stream ID and language metadata. |
subtitle::codec, subtitle::stream_id, subtitle::metadata::language
|
| 4 | Optionally configure the subtitle formatting. |
subtitle::font, subtitle::font_size, subtitle::outline and others |
| 5 | Optionally configure the Teletext character sets, the Teletext layout and the DVB subtitle type. |
subtitle::teletext_primary_charset, subtitle::teletext_bottom_row, subtitle::subtitling_type
|
| 6 | Start the writer and play or process the source (see the MPlatform and MFormats examples). | - |
1. Prepare ASS or SRT subtitle files
The sample can load existing .ass or .srt subtitle files. It can also generate temporary subtitle files from the subtitle editor UI.
ASS is the default subtitle format because it allows the sample to store text formatting in the subtitle file header.
ASS generation example
string subFile = Path.Combine(Path.GetTempPath(), "temp_subtitle_track_0.ass");
File.WriteAllText(
subFile,
AssSubtitleHelper.BuildAss(
track.Subtitles,
styleSettings,
"DVB Subtitle Inserter"));
SRT generation example
string subFile = Path.Combine(Path.GetTempPath(), "temp_subtitle_track_0.srt");
using var writer = new StreamWriter(subFile);
foreach (var subtitle in track.Subtitles)
{
writer.WriteLine(subtitle.Index);
writer.WriteLine($"{subtitle.StartTime} --> {subtitle.EndTime}");
writer.WriteLine(subtitle.Text);
writer.WriteLine();
}
The generated subtitle file is then passed directly to the reader. No VobSub conversion is required. If a subtitle file contains non-Latin text, save it in UTF-8.
2. Attach subtitle files to the reader
Subtitle files are attached by setting the reader properties below. For a single subtitle track, use external_subtitle.
| Property | Description |
|---|---|
external_subtitle |
Path to the .ass or .srt file of the first subtitle track. |
external_subtitle.stream_id |
Stream ID of the first subtitle track. The writer uses it to find this track. |
external_subtitle.N, external_subtitle.stream_id.N
|
Path and stream ID of the subtitle track with the index N (1, 2, ...). |
experimental.out_subtitle_packets |
Set to 2 to enable subtitle packet output from the reader, so the writer can receive and encode the attached subtitle tracks. |
subtitle_track |
Subtitle track selection. The examples use 0. |
external_process |
The examples set it to false. |
One subtitle track
string subtitleFile = @"C:\Subtitles\example.ass";
string readerConfig =
"subtitle_track=0 experimental.out_subtitle_packets=2 external_process=false " +
$"external_subtitle='{subtitleFile}'";
Several subtitle tracks
For multiple subtitle tracks, use indexed external_subtitle properties. Each subtitle track can also be assigned a stream ID with external_subtitle.stream_id.
string subPath1 = @"C:\Subtitles\english.ass";
string subPath2 = @"C:\Subtitles\greek.ass";
string readerConfig =
"external_process=false subtitle_track=0 experimental.out_subtitle_packets=2 " +
"external_subtitle.stream_id=117 " +
$"external_subtitle='{subPath1}' " +
"external_subtitle.stream_id.1=118 " +
$"external_subtitle.1='{subPath2}'";
The stream ID connects a specific reader subtitle track to the corresponding writer subtitle configuration. For example, the subtitle track assigned to external_subtitle.stream_id=117 can later be configured in the writer with subtitle::stream_id=117.
3. Configure writer subtitle tracks
The writer configuration defines how each subtitle track should be encoded in the output stream.
| Property | Description |
|---|---|
subtitle::codec |
dvbsub encodes the track as bitmap DVB subtitles, dvbtxt encodes it as DVB Teletext subtitles. |
subtitle::stream_id |
Stream ID of the reader subtitle track that this writer track encodes (see external_subtitle.stream_id). |
subtitle::metadata::language |
Language of the track as a three-letter code, for example eng or ell. For DVB Teletext, mul (multiple languages) lets you control the character sets (see step 5). |
Multiple subtitle tracks are configured with indexed subtitle properties. The index in the reader and writer property names is the same:
| Track | Reader: file | Reader: stream ID | Writer: codec | Writer: stream ID | Writer: language |
|---|---|---|---|---|---|
| First | external_subtitle |
external_subtitle.stream_id |
subtitle::codec |
subtitle::stream_id |
subtitle::metadata::language |
| Second | external_subtitle.1 |
external_subtitle.stream_id.1 |
subtitle.1::codec |
subtitle.1::stream_id |
subtitle.1::metadata::language |
| Track N | external_subtitle.N |
external_subtitle.stream_id.N |
subtitle.N::codec |
subtitle.N::stream_id |
subtitle.N::metadata::language |
Use dvbsub when the output track should be encoded as bitmap DVB subtitles:
subtitle::codec='dvbsub'
Use dvbtxt when the output track should be encoded as DVB Teletext subtitles:
subtitle::codec='dvbtxt'
Single bitmap DVB subtitle track
format='mpegts'
video::codec='libopenh264'
audio::codec='aac'
video::b='5M'
mux_buffers=0
subtitle::codec='dvbsub'
subtitle::stream_id=117
subtitle::metadata::language='eng'
video::maxrate='5M'
program::title='Medialooks DVB subtitles test'
Single DVB Teletext subtitle track
format='mpegts'
video::codec='libopenh264'
audio::codec='aac'
video::b='5M'
mux_buffers=0
subtitle::codec='dvbtxt'
subtitle::stream_id=117
subtitle::metadata::language='eng'
video::maxrate='5M'
program::title='Medialooks DVB Teletext test'
Two subtitle tracks
In the example below, the first subtitle track is written as DVB Teletext and the second subtitle track is written as bitmap DVB subtitles.
format='mpegts'
video::codec='libopenh264'
audio::codec='aac'
video::b='5M'
mux_buffers=0
subtitle::codec='dvbtxt'
subtitle::stream_id=117
subtitle::metadata::language='eng'
subtitle.1::codec='dvbsub'
subtitle.1::stream_id=118
subtitle.1::metadata::language='ell'
video::maxrate='5M'
program::title='Medialooks subtitle test'
4. Configure subtitle formatting in the writer
Basic subtitle text formatting can also be configured directly in the writer configuration. These properties are useful for common styling options such as font, font size, colors, background, and outline.
Formatting support depends on the selected subtitle output type. Bitmap DVB subtitles can use rendering options such as background, outline, and alpha values. DVB Teletext subtitle formatting may be limited by the Teletext output format.
| Property | Value | Example | Notes |
|---|---|---|---|
subtitle::font |
Font name | 'Arial' |
|
subtitle::font_size |
Font size | 26 |
|
subtitle::font_color |
Color as a hex value | 'FFFFFF' |
|
subtitle::background |
true or false
|
true |
|
subtitle::background_color |
Color as a hex value | '000000' |
|
subtitle::background_alpha |
Alpha value | 128 |
|
subtitle::outline |
true or false
|
true |
|
subtitle::outline_color |
Color as a hex value | '000000' |
|
subtitle::outline_thickness |
Outline thickness | 2 |
|
subtitle::outline_alpha |
Alpha value | 255 |
For bitmap DVB subtitles. |
format='mpegts'
video::codec='libopenh264'
audio::codec='aac'
video::b='5M'
mux_buffers=0
subtitle::codec='dvbsub'
subtitle::stream_id=117
subtitle::metadata::language='eng'
subtitle::font='Arial'
subtitle::font_size=26
subtitle::font_color='FFFFFF'
subtitle::background=true
subtitle::background_color='000000'
subtitle::background_alpha=128
subtitle::outline=true
subtitle::outline_color='000000'
subtitle::outline_thickness=2
subtitle::outline_alpha=255
video::maxrate='5M'
program::title='Medialooks subtitle test'
For indexed subtitle tracks, use the same indexed prefix as for other subtitle properties. For example, formatting for the second subtitle track can be set with subtitle.1::font, subtitle.1::font_size, and subtitle.1::font_color.
subtitle.1::codec='dvbsub'
subtitle.1::stream_id=118
subtitle.1::metadata::language='ell'
subtitle.1::font='Arial'
subtitle.1::font_size=26
subtitle.1::font_color='FFFFFF'
subtitle.1::outline=true
subtitle.1::outline_color='000000'
subtitle.1::outline_thickness=2
ASS headers are still supported and are useful when custom formatting is required in the subtitle file itself. For standard output formatting, the writer subtitle formatting properties can be used directly in the encoder configuration.
5. Advanced options
These options are optional. They apply to DVB Teletext (dvbtxt) or to DVB subtitles (dvbsub), as shown in the table. For indexed tracks, use the indexed prefix, for example subtitle.1::teletext_bottom_row.
| Property | Applies to | Description |
|---|---|---|
subtitle::teletext_primary_charset |
dvbtxt |
The primary character set: latin, cyrillic_russian_bulgarian, arabic or hebrew. Any other value makes the writer fail to start. If you do not set it, the set is chosen from subtitle::metadata::language: Russian (rus) and Bulgarian (bul) use Cyrillic, other languages use Latin. If the language is empty or mul, the set is detected from the first subtitle that contains supported letters and then stays the same until the writer is restarted. |
subtitle::teletext_secondary_charset |
dvbtxt |
The secondary character set, with the same possible values. If you do not set it, the secondary set is added automatically for subtitles that mix two alphabets (for example Latin and Cyrillic). If you set both sets, they must be different. |
subtitle::teletext_bottom_row |
dvbtxt |
The bottom row of the Teletext page that the subtitle text uses, from 1 to 23. The subtitle block keeps its height of up to three lines and ends at this row. Without the property, the subtitles use the rows 21 to 23. One line is placed in the last row, two lines in the last two rows, and so on; more than three lines are cut to the last three. |
subtitle::data_identifier |
dvbtxt |
The data identifier byte at the start of the Teletext data. The default value is 0x10. |
subtitle::subtitling_type |
dvbsub |
The subtitling type byte of the DVB subtitle descriptor in the PMT, for example 0x24 or 0x25. If subtitle::metadata::language contains several languages separated by commas, a descriptor with the same type is written for each language. For compatibility, subtitle::data_identifier works as an alias of this property when the codec is dvbsub. If you set both, subtitle::subtitling_type is used. |
subtitle::default_font |
dvbsub |
The default font used to render the bitmap DVB subtitles, for example 'Times New Roman'. |
subtitle::canvas_width, subtitle::canvas_height
|
dvbsub |
Optional width and height of the canvas on which the bitmap DVB subtitles are rendered, for example subtitle::canvas_height=576. |
Example: one Teletext track with Latin and Cyrillic text, with the subtitles on the rows 11 to 13:
format='mpegts' mux_buffers=0
subtitle::codec='dvbtxt'
subtitle::stream_id=117
subtitle::metadata::language='mul'
subtitle::teletext_primary_charset='latin'
subtitle::teletext_secondary_charset='cyrillic_russian_bulgarian'
subtitle::teletext_bottom_row=13
video::codec='libopenh264'
video::maxrate='5M'
audio::codec='aac'
Example: one bitmap DVB subtitle track with the subtitling type, the default font and the canvas height set:
format='mpegts' mux_buffers=0
subtitle::codec='dvbsub'
subtitle::stream_id=76
subtitle::metadata::language='eng'
subtitle::subtitling_type=0x24
subtitle::default_font='Times New Roman'
subtitle::canvas_height=576
video::codec='libopenh264'
video::maxrate='5M'
audio::codec='aac'
MPlatform full example
The following example opens a source file, attaches two external subtitle tracks, configures the writer, and starts subtitle insertion.
string sourceFile = @"C:\Media\input.ts";
string outputUrl = @"C:\Media\output.ts";
string subPath1 = @"C:\Subtitles\english.ass";
string subPath2 = @"C:\Subtitles\greek.ass";
string readerConfig =
"external_process=false subtitle_track=0 experimental.out_subtitle_packets=2 " +
"external_subtitle.stream_id=117 " +
$"external_subtitle='{subPath1}' " +
"external_subtitle.stream_id.1=118 " +
$"external_subtitle.1='{subPath2}'";
string writerConfig =
"format='mpegts' video::codec='libopenh264' audio::codec='aac' " +
"video::b='5M' mux_buffers=0 " +
"subtitle::codec='dvbtxt' subtitle::stream_id=117 subtitle::metadata::language='eng' " +
"subtitle::font='Arial' subtitle::font_size=26 subtitle::font_color='FFFFFF' " +
"subtitle.1::codec='dvbsub' subtitle.1::stream_id=118 subtitle.1::metadata::language='ell' " +
"subtitle.1::font='Arial' subtitle.1::font_size=26 subtitle.1::font_color='FFFFFF' " +
"subtitle.1::outline=true subtitle.1::outline_color='000000' subtitle.1::outline_thickness=2 " +
"video::maxrate='5M' program::title='Medialooks subtitle test'";
MFileClass file = null;
MWriterClass writer = null;
try
{
file = new MFileClass();
writer = new MWriterClass();
file.FileNameSet(sourceFile, readerConfig);
writer.WriterNameSet(outputUrl, writerConfig);
writer.ObjectStart(file);
file.FilePlayStart();
// Keep the application running while the source is being processed.
}
finally
{
if (writer != null)
Marshal.ReleaseComObject(writer);
if (file != null)
Marshal.ReleaseComObject(file);
}
MFormats full example
In MFormats SDK, read frames from MFReader and pass them to MFWriter. The example below shows the main processing pattern.
string sourceFile = @"C:\Media\input.ts";
string outputUrl = @"C:\Media\output.ts";
string subPath1 = @"C:\Subtitles\english.ass";
string subPath2 = @"C:\Subtitles\greek.ass";
string readerConfig =
"external_process=false subtitle_track=0 experimental.out_subtitle_packets=2 " +
"external_subtitle.stream_id=117 " +
$"external_subtitle='{subPath1}' " +
"external_subtitle.stream_id.1=118 " +
$"external_subtitle.1='{subPath2}'";
string writerConfig =
"format='mpegts' video::codec='libopenh264' audio::codec='aac' " +
"video::b='5M' mux_buffers=0 " +
"subtitle::codec='dvbtxt' subtitle::stream_id=117 subtitle::metadata::language='eng' " +
"subtitle::font='Arial' subtitle::font_size=26 subtitle::font_color='FFFFFF' " +
"subtitle.1::codec='dvbsub' subtitle.1::stream_id=118 subtitle.1::metadata::language='ell' " +
"subtitle.1::font='Arial' subtitle.1::font_size=26 subtitle.1::font_color='FFFFFF' " +
"subtitle.1::outline=true subtitle.1::outline_color='000000' subtitle.1::outline_thickness=2 " +
"video::maxrate='5M' program::title='Medialooks subtitle test'";
MFReaderClass reader = null;
MFWriterClass writer = null;
try
{
reader = new MFReaderClass();
writer = new MFWriterClass();
reader.ReaderOpen(sourceFile, readerConfig);
writer.WriterSet(outputUrl, 1, writerConfig);
while (true)
{
MFFrame frame = null;
try
{
reader.SourceFrameGet(-1, out frame, "");
if (frame == null)
break;
writer.ReceiverFramePut(frame, 0, "");
}
finally
{
if (frame != null)
Marshal.ReleaseComObject(frame);
}
}
reader.ReaderClose();
}
finally
{
if (writer != null)
Marshal.ReleaseComObject(writer);
if (reader != null)
Marshal.ReleaseComObject(reader);
}
If the output has no subtitles
| Check | What to do |
|---|---|
| Subtitle packets from the reader | Set experimental.out_subtitle_packets=2 in the reader properties. |
| Stream IDs | The external_subtitle.stream_id value must be the same as subtitle::stream_id of the writer track (and with the same index for the other tracks). |
| Non-Latin text | Save the subtitle file in UTF-8. For Teletext, check the language and the character sets in step 5. |
| Missing or invalid subtitle file | If an external subtitle file cannot be loaded, the other streams of the output are still muxed. Check the path in external_subtitle. |
| License | Subtitle insertion may require the Closed Caption plugin license. |
ASS subtitle formatting
ASS subtitles support text formatting through the ASS style header. The sample exposes the main ASS formatting options in the UI. Color values can be entered manually as hex values or selected through the built-in WPF color picker.
| Where to configure the formatting | When to use |
|---|---|
ASS style header (the [V4+ Styles] section of the .ass file) |
When the formatting should be stored directly in the subtitle file, or when custom ASS styling is required. |
Writer properties (subtitle::font and others, step 4) |
For standard output formatting, with .ass and .srt files. |
The user can configure the following settings in the sample. They are written into the ASS [V4+ Styles] section:
| Setting | ASS style field |
|---|---|
| Font family | Fontname |
| Font size | Fontsize |
| Text color | PrimaryColour |
| Outline color | OutlineColour |
| Shadow/background color | BackColour |
| Bold, italic, underline |
Bold, Italic, Underline
|
| Outline size | Outline |
| Shadow size | Shadow |
| Subtitle alignment | Alignment |
| Left, right and bottom margins |
MarginL, MarginR, MarginV
|
[Script Info]
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.709
PlayResX: 1920
PlayResY: 1080
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,26,&H00FFFFFF,&H00FFFFFF,&H00000000,&H80000000,0,0,0,0,100,100,0,0,1,2,1,2,20,20,20,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:02.50,Default,,0,0,0,,Welcome to the Example ASS Subtitle File!
When an ASS file is loaded, the sample reads the Default style from the ASS header and applies it to the formatting UI and preview.
ASS style generation example
public class SubtitleStyleSettings
{
public string FontName { get; set; } = "Arial";
public float FontSize { get; set; } = 26f;
public string PrimaryColor { get; set; } = "#FFFFFF";
public string OutlineColor { get; set; } = "#000000";
public string BackColor { get; set; } = "#000000";
public bool Bold { get; set; }
public bool Italic { get; set; }
public bool Underline { get; set; }
public int Outline { get; set; } = 2;
public int Shadow { get; set; } = 1;
public int Alignment { get; set; } = 2;
public int LeftMargin { get; set; } = 20;
public int RightMargin { get; set; } = 20;
public int BottomMargin { get; set; } = 20;
}
After completing these steps, the output transport stream can contain embedded bitmap DVB subtitles, DVB Teletext subtitles, or both, depending on the writer subtitle codec configuration.
Still have questions?
Tell us what didn’t work or what you’d like clarified.