C# ONVIF协议集成实战:基于VLC的跨平台监控流处理方案
·
为什么选择ONVIF+VLC?
ONVIF协议作为安防监控领域的通用语言,能统一不同厂商设备的控制接口。但实际开发中常遇到两个头疼问题:
- WS-Security鉴权复杂:需要手动处理XML签名和加密头
- 跨平台播放器缺失:Windows的MediaFoundation在Linux上水土不服

技术选型对比
| 方案 | 跨平台性 | 解码能力 | 开发复杂度 | |---------------|----------|----------|------------| | FFmpeg | 优秀 | 极强 | 高 | | MediaFoundation| 仅Windows| 中等 | 低 | | LibVLCSharp | 优秀 | 强 | 中 |
VLC凭借其开箱即用的RTSP支持和硬件加速能力,成为我们的首选。
实战三步走
1. 设备发现
// 发送WS-Discovery探测包
var probe = new XElement("Probe",
new XAttribute(XNamespace.Xmlns + "d", "http://schemas.xmlsoap.org/ws/2005/04/discovery"),
new XAttribute(XNamespace.Xmlns + "dn", "http://www.onvif.org/ver10/network/wsdl"));
using var udpClient = new UdpClient(3702);
udpClient.Send(Encoding.UTF8.GetBytes(probe.ToString()),
IPAddress.Parse("239.255.255.250"));
2. WSSE鉴权
string GetWsseHeader(string username, string password)
{
var nonce = Guid.NewGuid().ToString("N");
var created = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
var nonceBytes = Encoding.UTF8.GetBytes(nonce);
var passwordDigest = SHA1.Create().ComputeHash(
nonceBytes.Concat(Encoding.UTF8.GetBytes(created))
.Concat(Encoding.UTF8.GetBytes(password))
.ToArray());
return $"""
<Security s:mustUnderstand="1" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username>{username}</Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">
{Convert.ToBase64String(passwordDigest)}
</Password>
<Nonce>{Convert.ToBase64String(nonceBytes)}</Nonce>
<Created>{created}</Created>
</UsernameToken>
</Security>
""";
}
3. VLC集成
var libVLC = new LibVLC("--no-xlib", "--avcodec-hw=dxva2");
var mediaPlayer = new MediaPlayer(libVLC);
// RTSP地址格式:rtsp://user:pass@ip:port/path
using var media = new Media(libVLC, new Uri(rtspUrl));
media.AddOption(":network-caching=300");
videoView.MediaPlayer = mediaPlayer;
mediaPlayer.Play(media);

性能优化技巧
- 内存管理:
- 释放资源时先调用
mediaPlayer.Stop()再Dispose -
限制同时播放的流数量(建议不超过4路1080P)
-
线程策略:
Task.Run(() => { // 每个播放器独占线程 mediaPlayer.Play(media); }).ConfigureAwait(false);
常见坑点
- TLS 1.2问题:在应用启动时添加
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; - 内存泄漏:定期检查libVLC日志中的
avformat警告
项目结构建议
ONVIFClient/
├── Services/
│ ├── DeviceDiscoverService.cs
│ ├── CameraControlService.cs
├── Models/
│ ├── CameraDevice.cs
│ ├── Config.cs
├── Views/
│ └── VideoViewWrapper.axaml
思考延伸
如何实现有人闯入时自动截图并推送告警?可以结合ONVIF的事件订阅服务: 1. 创建PullPoint订阅 2. 解析tns1:RuleEngine/CellMotionDetector/Motion事件 3. 触发MediaPlayer.TakeSnapshot()方法
完整示例代码已上传Github:https://github.com/example/onvif-vlc-demo (注:此为示意链接)
更多推荐


所有评论(0)