VAST.TS Library
The VAST.TS library provides MPEG-2 Transport Stream (TS) functionality for VASTreaming applications. It supports UDP multicast streaming, TS over HTTP delivery, and file-based operations including playback and recording with automatic file rotation.
MPEG-2 Transport Stream is widely used as the container format by various streaming protocols, including HLS, SRT, and RTP. The VAST.TS library provides the underlying TS muxing and demuxing capabilities used by these protocol implementations.
Overview
| Feature | Description |
|---|---|
| UDP Multicast | Receive and send TS streams over UDP multicast |
| TS over HTTP | Deliver TS streams to HTTP clients |
| File Playback | Read and play TS files with seeking support |
| File Recording | Write TS files with automatic file rotation |
| Format Parsing | Full MPEG-2 TS demuxing and muxing |
Requirements
- .NET: .NET 6.0 or later
- Dependencies: VAST.Common
Supported Codecs
Video Codecs
| Codec | Stream Type | Notes |
|---|---|---|
| H.264/AVC | 0x1B | Full support with NAL unit handling |
| H.265/HEVC | 0x24 | Full support with NAL unit handling |
| MPEG-1 | 0x01 | Standard MPEG-1 video |
| MPEG-2 | 0x02 | Standard MPEG-2 video |
Audio Codecs
| Codec | Stream Type | Notes |
|---|---|---|
| AAC (ADTS) | 0x0F | MPEG-2 AAC audio |
| AAC (LATM) | 0x11 | MPEG-4 AAC audio |
| MP1 | 0x03/0x04 | MPEG-1/2 Layer I |
| MP2 | 0x03/0x04 | MPEG-1/2 Layer II |
| MP3 | 0x03/0x04 | MPEG-1/2 Layer III |
| AC-3 | 0x81 | Dolby Digital |
| E-AC-3 | 0x87 | Enhanced AC-3 |
Data Streams
The TS muxer/demuxer includes custom support for text and binary data streams, enabling metadata passthrough via TS streaming or file storage.
| Stream Type | Content Type | Description |
|---|---|---|
| Text | Text/XML | UTF-8 encoded text data (e.g., ONVIF metadata) |
| Binary | Binary | Raw binary data streams |
This feature is useful for:
- Passing ONVIF metadata alongside video/audio streams
- Recording metadata to TS files for later retrieval
- Streaming custom application data through TS infrastructure
UDP Multicast Source
The TsSource receives MPEG-2 Transport Streams over UDP multicast.
URI Format
udp://<multicast-ip>:<port>?vast-local-ip=<binding-ip>&vast-program-pid=<pid>
| Parameter | Description |
|---|---|
multicast-ip |
Multicast group IP address |
port |
UDP port number |
vast-local-ip |
Optional local interface IP to bind to |
vast-program-pid |
Optional program PID filter (decimal or hex with 0x prefix) |
Usage
var source = new VAST.TS.TsSource();
source.Uri = "udp://239.0.0.1:1234";
source.NewStream += (sender, e) =>
{
Console.WriteLine($"Stream {e.StreamIndex}: {e.MediaType.ContentType}");
};
source.NewSample += (sender, e) =>
{
// Process received media sample
ProcessSample(e.Sample);
};
source.StateChanged += (sender, state) =>
{
if (state == MediaState.Opened)
{
source.Start();
}
};
source.Open();
Program Filtering
When a transport stream contains multiple programs, use the vast-program-pid parameter to select a specific program:
// Select program with PMT PID 0x100
source.Uri = "udp://239.0.0.1:1234?vast-program-pid=0x100";
UDP Multicast Sink
The TsSink sends MPEG-2 Transport Streams over UDP multicast.
URI Format
udp://<multicast-ip>:<port>?vast-local-ip=<binding-ip>&vast-ttl=<ttl>&vast-mtu=<mtu>
| Parameter | Description |
|---|---|
multicast-ip |
Multicast group IP address |
port |
UDP port number |
vast-local-ip |
Optional local interface IP to bind to |
vast-ttl |
Optional time-to-live for multicast packets |
vast-mtu |
Optional MTU size for packet combining |
Usage
var sink = new VAST.TS.TsSink();
sink.Uri = "udp://239.0.0.1:1234?vast-ttl=32";
sink.AddStream(0, videoMediaType);
sink.AddStream(1, audioMediaType);
sink.StateChanged += (sender, state) =>
{
if (state == MediaState.Opened)
{
sink.Start();
}
};
sink.Open();
...
// Push media samples
sink.PushMedia(0, videoSample);
sink.PushMedia(1, audioSample);
sink.Stop();
MTU and Packet Combining
When vast-mtu is specified, the sink combines multiple TS packets into single UDP datagrams up to the MTU size for improved network efficiency:
// Combine packets up to 1316 bytes (7 TS packets)
sink.Uri = "udp://239.0.0.1:1234?vast-mtu=1316";
TS File Source
The TsFileSource reads MPEG-2 Transport Stream files with full interactive playback support.
Features
| Feature | Support |
|---|---|
| Seeking | Frame-accurate seeking via keyframe index |
| Playback Rate | Variable speed playback |
| Looping | Continuous loop playback |
| Pause/Resume | Full pause and resume support |
| Transcoding | On-the-fly transcoding to user specified format |
Usage
var source = new VAST.TS.TsFileSource();
source.Uri = "video.ts";
source.NewStream += (sender, e) =>
{
Console.WriteLine($"Stream {e.StreamIndex}: {e.MediaType.ContentType}");
Console.WriteLine($"Duration: {source.Duration}");
};
source.NewSample += (sender, e) =>
{
ProcessSample(e.Sample);
};
source.StateChanged += (sender, state) =>
{
if (state == MediaState.Opened)
{
source.Start();
}
};
source.Open();
Seeking and Playback Control
// Seek to position
source.Position = TimeSpan.FromSeconds(30);
// Change playback rate
source.PlaybackRate = 2.0; // 2x speed
// Pause
source.Pause();
// Resume
source.Start();
Playback Rates
| Rate | Description |
|---|---|
| double.MinValue | As fast as possible in backward direction (no pacing) |
| -32 to -1 | Rewind (backward playback) |
| 0 to 1 (exclusive) | Slow motion |
| 1 | Normal speed |
| 1 to 32 | Fast forward |
| double.MaxValue | As fast as possible (no pacing) |
Loop Mode
Enable continuous looping for playlist-like behavior:
source.Loop = true;
source.Uri = "video.ts";
source.Open();
Note
When Loop is enabled, seeking and pause are not available.
Program PID Filtering
Select a specific program when the TS file contains multiple programs:
// Filter by program PID
var source = new VAST.TS.TsFileSource(programPid: 0x100);
source.Uri = "multi-program.ts";
source.Open();
On-the-fly Decoding
Request decoded output format for a stream:
source.StateChanged += async (sender, state) =>
{
if (state == MediaState.Opened)
{
// Request decoded video output
var decodedType = new MediaType
{
ContentType = ContentType.Video,
CodecId = Codec.Uncompressed,
PixelFormat = PixelFormat.NV12
};
await source.SetDesiredOutputType(0, decodedType);
source.Start();
}
};
TS File Sink
The TsFileSink writes MPEG-2 Transport Stream files with automatic file rotation support.
Usage
var sink = new VAST.TS.TsFileSink();
sink.Uri = "recording.ts";
sink.AddStream(0, videoMediaType);
sink.AddStream(1, audioMediaType);
sink.StateChanged += (sender, state) =>
{
if (state == MediaState.Opened)
{
sink.Start();
}
};
sink.Open();
...
// Push media samples
sink.PushMedia(0, videoSample);
sink.PushMedia(1, audioSample);
sink.Stop();
File Rotation
Automatically split recordings into multiple files:
var sink = new VAST.TS.TsFileSink();
sink.RotationPeriod = 3600; // Rotate every hour (seconds)
int fileNumber = 0;
sink.NextUri = () => $"recording_{fileNumber++:D4}.ts";
sink.UriRotated += (sender, e) =>
{
Console.WriteLine($"Completed: {e.Uri}");
Console.WriteLine($"Duration: {e.Finished - e.Started}");
};
sink.AddStream(0, videoMediaType);
sink.AddStream(1, audioMediaType);
sink.Open();
File rotation occurs at keyframes to ensure each file starts with a valid GOP.
Writing to Stream
Write TS data to a custom stream instead of a file:
var memoryStream = new MemoryStream();
var sink = new VAST.TS.TsFileSink();
sink.Stream = memoryStream;
sink.AddStream(0, videoMediaType);
sink.StateChanged += (sender, state) =>
{
if (state == MediaState.Opened)
{
sink.Start();
}
};
sink.Open();
...
sink.PushMedia(0, videoSample);
sink.Stop();
// Access the TS data
byte[] tsData = memoryStream.ToArray();
Delayed Start
Use delayed start when the first media sample may arrive after a significant delay:
sink.Start(delayedStart: true);
// File will be created/recreated when first sample arrives
// Empty file is automatically deleted if no samples received
TS over HTTP Server
The TS over HTTP server delivers Transport Streams to HTTP clients for browser-based playback and streaming applications.
Integration with StreamingServer
Note
TsHttpServer is not available as a standalone server. It operates as part of the VAST.Network.StreamingServer infrastructure and is instantiated by the StreamingServer automatically when enabled.
var server = new VAST.Network.StreamingServer();
// Enable TS over HTTP
server.EnableTsHttp = true;
server.TsHttpServerParameters = new VAST.TS.TsHttpServerParameters
{
TsHttpPath = "/ts/"
};
server.Start();
Client Access
Clients connect via HTTP GET requests:
http://server:port/ts/stream-name
The server responds with a continuous TS stream using chunked transfer encoding.
Troubleshooting
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| No streams detected | Invalid TS format | Verify file/stream is valid MPEG-2 TS |
| Multicast not received | Network/firewall issue | Check multicast routing, firewall rules |
| Audio/video out of sync | Timestamp discontinuity | Check source for timestamp jumps |
| Seeking inaccurate | Missing keyframe index | Ensure file has regular keyframes |
| File rotation not working | No keyframes | Rotation occurs at keyframes only |
Debugging
Enable debug logging to diagnose issues:
VAST.Common.Log.Level = VAST.Common.Log.LogLevel.Debug;
See Also
- Supported Platforms - Platform compatibility matrix
- VAST.Common Library - Core media types and interfaces
- VAST.HLS Library - HLS Streaming
- VAST.Network Library - Network streaming infrastructure
- VAST.RTSP Library - RTSP/RTP Streaming
- VAST.SRT Library - SRT Streaming