VAST.ONVIF Library
The VAST.ONVIF library provides a client implementation for communicating with ONVIF-compliant IP cameras and video encoders. It supports device discovery, media profile retrieval, streaming URI extraction, PTZ camera control, snapshot capture, and event subscriptions.
Overview
| Feature | Description |
|---|---|
| Device Discovery | Find ONVIF devices on the network using WS-Discovery |
| Device Information | Retrieve manufacturer, model, firmware, serial, and MAC address |
| Media Profiles | Enumerate available media profiles with video/audio configuration |
| Streaming URIs | Get RTSP URIs for all supported transport modes |
| PTZ Control | Pan, tilt, zoom control for PTZ-capable cameras |
| Snapshots | Capture still images from cameras |
| Event Subscription | Subscribe to pullpoint notifications for motion detection, I/O events |
Requirements
- .NET: .NET 6.0 or later
- Dependencies: VAST.Common
Device Discovery
The OnvifDiscovery class discovers ONVIF devices on the network using the WS-Discovery protocol.
Basic Discovery
// Discover devices with 5-second timeout
var devices = await VAST.ONVIF.OnvifDiscovery.SearchAsync(5000);
foreach (var device in devices)
{
Console.WriteLine($"Found: {device.IPAddress}");
Console.WriteLine($" MAC: {device.MacAddress}");
Console.WriteLine($" ONVIF Address: {device.OnvifAddress}");
}
Network Interface Selection
By default, discovery runs on all active network interfaces. To specify interfaces manually:
// Clear auto-detected interfaces
VAST.ONVIF.OnvifDiscovery.Nics.Clear();
// Add specific interface
VAST.ONVIF.OnvifDiscovery.Nics.Add(new VAST.ONVIF.NetworkInterface
{
IPAddress = "192.168.1.100"
});
var devices = await VAST.ONVIF.OnvifDiscovery.SearchAsync(5000);
Vendor Filtering
Filter discovery results by MAC address prefix to find devices from specific manufacturers:
// Filter for Axis cameras (MAC prefix)
VAST.ONVIF.OnvifDiscovery.VendorMacFilter = "00:40:8C";
var devices = await VAST.ONVIF.OnvifDiscovery.SearchAsync(5000);
Discovered Device Information
The DiscoveredDevice class contains:
| Property | Description |
|---|---|
IPAddress |
Device IP address |
MacAddress |
Device MAC address |
OnvifAddress |
ONVIF service endpoint URL |
UpnpServiceAddress |
UPnP service URL (if available) |
Model |
Device model name |
FirmwareVersion |
Device firmware version |
ONVIF Client
The library provides two client implementations for different ONVIF profiles:
| Client | ONVIF Profile | Description |
|---|---|---|
| OnvifClient1 | Profile S (Media) | Standard streaming profile for live video |
| OnvifClient2 | Profile T (Media2) | Advanced profile with H.265 support and recording playback |
Both clients share the same base interface (IOnvifClient) and provide identical functionality for device information, streaming URIs, PTZ control, and snapshots. Use OnvifClient2 for newer cameras that support ONVIF Profile T, or when you need access to recording search and replay features.
Connecting to a Device
VAST.ONVIF.IOnvifClient client = null;
try
{
// First let's try OnvifClient2 (Profile T / Media2)
client = new VAST.ONVIF.OnvifClient2(
"http://192.168.1.100:80/onvif/device_service",
"admin",
"password"
);
await client.OpenAsync();
}
catch (Exception)
{
// OnvifClient2 failed, fall back to OnvifClient1 (Profile S)
try
{
client = new VAST.ONVIF.OnvifClient1(
"http://192.168.1.100:80/onvif/device_service",
"admin",
"password"
);
await client.OpenAsync();
}
catch (Exception ex)
{
Console.WriteLine($"Connection failed: {ex.Message}");
client = null;
}
}
if (client != null)
{
Console.WriteLine($"Manufacturer: {client.Manufacturer}");
Console.WriteLine($"Model: {client.Model}");
Console.WriteLine($"Firmware: {client.Firmware}");
Console.WriteLine($"Serial: {client.Serial}");
Console.WriteLine($"MAC: {client.MACAddress}");
}
Device Properties
After calling OpenAsync(), the following properties are available:
| Property | Description |
|---|---|
IP |
Device IP address |
Port |
Device port number |
Manufacturer |
Device manufacturer name |
Model |
Device model name |
Firmware |
Firmware version |
Serial |
Serial number |
HwID |
Hardware identifier |
MACAddress |
MAC address |
StreamingUris |
List of available streaming URIs |
CameraControl |
PTZ camera control interface |
Media Profiles and Streaming URIs
After connecting, the client retrieves all available media profiles and their streaming URIs.
Accessing Streaming URIs
await client.OpenAsync();
foreach (var uri in client.StreamingUris)
{
Console.WriteLine($"Profile: {uri.Profile.Name}");
Console.WriteLine($" URI: {uri.Uri}");
Console.WriteLine($" Transport: {uri.RtpTransportType} ({uri.RtpTransportCast})");
// Access media type information
foreach (var stream in uri.Profile.Streams)
{
if (stream.ContentType == VAST.Common.ContentType.Video)
{
Console.WriteLine($" Video: {stream}");
}
else if (stream.ContentType == VAST.Common.ContentType.Audio)
{
Console.WriteLine($" Audio: {stream}");
}
}
}
Transport Types
Each media profile may provide multiple streaming URIs with different transport configurations:
| Transport | Cast | Description |
|---|---|---|
| UDP | Unicast | Standard RTP over UDP (default) |
| UDP | Multicast | RTP multicast streaming |
| TCP Interleaved | Unicast | RTP interleaved over RTSP TCP connection |
| HTTP Tunnel | Unicast | RTP tunneled over HTTP for firewall traversal |
Using Streaming URIs with RTSP Source
await client.OpenAsync();
// Get the first available streaming URI
var streamUri = client.StreamingUris.FirstOrDefault();
if (streamUri != null)
{
var rtspSource = new VAST.RTSP.RtspClientSource();
rtspSource.Uri = streamUri.Uri;
rtspSource.StateChanged += (sender, state) =>
{
if (state == MediaState.Opened)
{
rtspSource.Start();
}
};
rtspSource.Open();
}
PTZ Camera Control
For PTZ-capable cameras, the CameraControl property provides access to pan, tilt, and zoom functionality through the ICameraControl interface.
Checking PTZ Support
await client.OpenAsync();
if (client.CameraControl != null)
{
Console.WriteLine("PTZ is supported");
if (client.CameraControl.IsPanTiltSupported)
{
Console.WriteLine(" Pan/Tilt supported");
}
if (client.CameraControl.IsZoomSupported)
{
Console.WriteLine(" Zoom supported");
}
}
Continuous Movement
var ptz = client.CameraControl;
// Start continuous pan/tilt movement
// Speed values range from -1.0 to +1.0
ptz.SetPanTiltSpeed(0.5f, 0.0f); // Pan right at half speed
// Stop movement
ptz.StopPanTilt();
// Continuous zoom
ptz.SetZoomSpeed(0.3f); // Zoom in slowly
// Stop zoom
ptz.StopSmoothZoom();
Absolute Positioning
var ptz = client.CameraControl;
// Move to absolute position
// Pan/tilt values typically range from -1.0 to +1.0
ptz.SetPanTilt(0.5f, -0.2f);
// Set absolute zoom level (ptz.MinZoom to ptz.MaxZoom)
ptz.CurrentZoom = 0.5f;
Presets
var ptz = client.CameraControl;
// Store current position as preset
// Preset number -1 means home position
ptz.StorePreset(1);
// Recall preset with movement speed
ptz.RecallPreset(1, 0.5f);
Snapshot Capture
Capture still images from cameras that support the ONVIF snapshot feature.
await client.OpenAsync();
try
{
using (var stream = await client.TakeSnapshot())
{
// Save to file
using (var fileStream = File.Create("snapshot.jpg"))
{
await stream.CopyToAsync(fileStream);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Snapshot failed: {ex.Message}");
}
Resource Cleanup
Always dispose of the client when finished to release event subscriptions and network resources:
var client = new VAST.ONVIF.OnvifClient1(uri, username, password);
try
{
await client.OpenAsync();
// Use client...
}
finally
{
client.Dispose();
}
Or use the using pattern:
using (var client = new VAST.ONVIF.OnvifClient1(uri, username, password))
{
await client.OpenAsync();
// Use client...
}
Troubleshooting
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Discovery finds no devices | Firewall blocking WS-Discovery | Allow UDP port 3702 |
| Authentication failure | Wrong credentials or time sync | Verify credentials; check device time |
| No streaming URIs | Incorrect credentials | Profiles require authentication |
| PTZ not available | Camera not PTZ-capable | Check CameraControl is not null |
| Connection timeout | Wrong port or IP | Verify device address and port |
Time Synchronization
ONVIF authentication uses WS-Security with timestamp validation. If the client and device clocks differ significantly, authentication may fail. The library automatically detects and compensates for time differences, but large discrepancies (>5 seconds) may cause issues.
HTTPS Support
The client supports both HTTP and HTTPS connections:
// HTTP connection (default port 80)
var client = new VAST.ONVIF.OnvifClient1(
"http://192.168.1.100/onvif/device_service",
"admin", "password");
// HTTPS connection (default port 443)
var client = new VAST.ONVIF.OnvifClient1(
"https://192.168.1.100/onvif/device_service",
"admin", "password");
See Also
- Supported Platforms - Platform compatibility matrix
- VAST.Common Library - Core media types and interfaces
- VAST.Network Library - Network streaming infrastructure
- VAST.RTSP Library - RTSP streaming with ONVIF URIs