Publishing Point with Proxy Source
This use-case demonstrates how to pull a stream from a remote source and forcibly transcode it before redistribution. The ProxySource wraps an existing IMediaSource and applies per-stream transcoding — decoding the original media and re-encoding it with user-specified codec parameters.
Overview
The createProxySource() method performs the following:
- Creates a media source from a remote URI using SourceFactory
- Waits for the source to open asynchronously
- Wraps the source in a ProxySource
- Iterates over all streams and configures the desired output codec for each
- Creates the publishing point with the proxy source
When to Use ProxySource
A pull source passes compressed data through to clients without modification. Use ProxySource when you need to:
- Re-encode video to a different codec, bitrate, or profile (e.g., enforce H.264 Constrained Baseline for maximum compatibility)
- Normalize audio to a standard format (e.g., always output AAC regardless of the source codec)
- Change resolution, framerate, or keyframe interval
Creating the Original Source
VAST.Media.IMediaSource originalSource = VAST.Media.SourceFactory.Create(uri);
SourceFactory creates the appropriate source type based on the URI protocol (rtsp://, rtmp://, srt://, etc.). The source opens asynchronously — StateChanged events indicate when it is ready.
Waiting for the Source to Open
originalSource.StateChanged += (object sender, Media.MediaState e) =>
{
switch (e)
{
case VAST.Media.MediaState.Opened:
{
// source is ready — create proxy and publishing point
break;
}
case VAST.Media.MediaState.Error:
{
// handle connection error
break;
}
}
};
originalSource.Open();
The Open() call initiates the connection. Once the source enters the Opened state, its stream count and media types are available and the proxy can be created.
Creating the Proxy Source
var proxySource = new VAST.Media.ProxySource(originalSource);
proxySource.Open();
ProxySource wraps the original source. When Open() is called on a proxy whose original source is already opened, it completes synchronously.
Configuring Output Types
After opening, iterate over all streams and set the desired output type for each:
for (int i = 0; i < proxySource.StreamCount; ++i)
{
VAST.Common.MediaType inputMediaType = proxySource.GetMediaType(i);
switch (inputMediaType.ContentType)
{
case VAST.Common.ContentType.Audio:
proxySource.SetDesiredOutputType(i, new VAST.Common.MediaType
{
ContentType = VAST.Common.ContentType.Audio,
CodecId = VAST.Common.Codec.AAC,
Bitrate = 128000,
SampleRate = 44100,
Channels = 2,
}).Wait();
break;
case VAST.Common.ContentType.Video:
VAST.Common.MediaType outputMediaType = new VAST.Common.MediaType
{
ContentType = VAST.Common.ContentType.Video,
CodecId = VAST.Common.Codec.H264,
Bitrate = inputMediaType.Width * inputMediaType.Height * 3,
Width = inputMediaType.Width,
Height = inputMediaType.Height,
Framerate = inputMediaType.Framerate,
};
outputMediaType.Metadata.Add("KeyframeInterval",
((int)Math.Ceiling(inputMediaType.Framerate.ToDouble())).ToString());
outputMediaType.Metadata.Add("Profile", (0x100 | 66).ToString());
proxySource.SetDesiredOutputType(i, outputMediaType).Wait();
break;
}
}
SetDesiredOutputType is asynchronous — it initializes the decoder and encoder for the stream. Once called, the proxy decodes incoming frames and re-encodes them to the specified output type.
Video Output
The sample preserves the original resolution and framerate, but re-encodes to H.264 with:
| Parameter | Value | Description |
|---|---|---|
Bitrate |
Width * Height * 3 |
Calculated from input dimensions |
KeyframeInterval |
Framerate (rounded up) | One keyframe per second |
Profile |
0x100 \| 66 |
H.264 Constrained Baseline profile |
The KeyframeInterval and Profile are passed via the Metadata dictionary — these are encoder-specific hints that the encoding backend interprets.
Audio Output
Audio is normalized to AAC at 44.1 kHz stereo, 128 kbps, regardless of the source audio codec.
Creating the Publishing Point
this.server.CreatePublishingPoint(publishingPath, proxySource);
The sample is called with:
this.createProxySource("transcode", "rtsp://192.168.0.101/stream");
The transcoded stream is then available at rtsp://server/transcode, rtmp://server/live/transcode, http://server:8888/hls/transcode, etc.
See Also
- Sample Applications — overview of all demo projects
- .NET Server Demo — parent page with setup instructions, license key configuration, and access URL reference
- Multi-Protocol Server — overview and full publishing point table
- Initialization — server creation and protocol configuration
- Server Event Handlers — authorization, connections, and error handling
- VAST.Network Library — StreamingServer API reference