You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

ONVIF NVR通道回放技术求助:时间过滤失效与通道获取不全

问题解答

1. RecordingInformationFilter的正确用法

当前的过滤字符串格式不符合ONVIF规范,RecordingInformationFilter要求使用XPath表达式,而非自定义的逗号分隔格式。要实现时间范围过滤,需同时指定开始和结束时间,并结合录像的时间属性进行匹配:

正确的XPath过滤表达式

需同时满足两个核心条件:

  • 过滤视频轨道://Track[TrackType="Video"]
  • 时间范围匹配:../StartTime <= '{endTime}' and ../EndTime >= '{startTime}'..表示向上定位到RecordingInformation节点)

修改后的代码片段:

// 定义时间范围:10分钟前到9分钟前
var startTime = DateTime.Now.AddMinutes(-10).ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ", CultureInfo.InvariantCulture);
var endTime = DateTime.Now.AddMinutes(-9).ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ", CultureInfo.InvariantCulture);

// 组合符合规范的XPath过滤条件
searchScope.RecordingInformationFilter = $"boolean(//Track[TrackType=\"Video\"] and ../StartTime <= '{endTime}' and ../EndTime >= '{startTime}')";

补充:强制限定回放时间范围

仅通过搜索过滤还不够,获取回放URL时需在StreamSetup中添加回放配置参数,直接指定播放的时间范围:

Replay.StreamSetup streamSetup = new Replay.StreamSetup();
streamSetup.Stream = Replay.StreamType.RTPUnicast;
streamSetup.Transport = new Replay.Transport();
streamSetup.Transport.Protocol = Replay.TransportProtocol.RTSP;

// 添加回放时间范围控制
streamSetup.ReplayConfiguration = new Replay.ReplayConfiguration();
streamSetup.ReplayConfiguration.PlaybackSpeed = 1.0F;
streamSetup.ReplayConfiguration.PlaybackMode = Replay.PlaybackMode.Normal;
streamSetup.ReplayConfiguration.Range = new Replay.TimeRange();
streamSetup.ReplayConfiguration.Range.StartTime = DateTime.Parse(startTime).ToUniversalTime();
streamSetup.ReplayConfiguration.Range.EndTime = DateTime.Parse(endTime).ToUniversalTime();

2. 全通道回放URL获取方法

仅获取到通道1的回放,原因在于SearchScope未覆盖所有通道的录制源,或者搜索逻辑仅匹配了通道1的录制令牌。

解决步骤

  1. 先获取所有通道的录制源:调用GetRecordings接口获取NVR上所有通道的录制信息,而非直接通过FindRecordings过滤
  2. 逐个通道匹配时间范围:对每个通道的录制令牌,单独检查是否存在目标时间范围内的录像

修改后的核心代码:

// 获取所有通道的录制源信息
var allRecordings = searchClient.GetRecordings(null, 0, 100);

foreach (var recording in allRecordings.RecordingInformation)
{
    // 针对当前通道的录制令牌,单独设置时间过滤规则
    Search.SearchScope singleChannelScope = new Search.SearchScope();
    singleChannelScope.RecordingTokens = new string[] { recording.RecordingToken };
    singleChannelScope.RecordingInformationFilter = $"boolean(//Track[TrackType=\"Video\"] and ../StartTime <= '{endTime}' and ../EndTime >= '{startTime}')";

    // 搜索该通道下符合时间条件的录像
    var searchToken = searchClient.FindRecordings(singleChannelScope, 100, "PT30S");
    var searchResults = searchClient.GetRecordingSearchResults(searchToken, 0, 10, "PT30S");

    if (searchResults != null && searchResults.RecordingInformation.Length > 0)
    {
        // 获取该通道的回放URL
        string replayUrl = replayClient.GetReplayUri(streamSetup, recording.RecordingToken);
        Console.WriteLine($"通道[{recording.Source.Name}]回放URL: {replayUrl}");
    }
}

额外提示

部分NVR的RecordingTokenRecordingInformation.Source.Name会包含通道标识(如channel1通道1),可通过这些字段直接区分不同通道。

3. 直播流URL与通道、码流的关联区分

由于不同品牌NVR的RTSP URL格式不统一,推荐通过以下两种方式实现关联:

方式1:通过ONVIF标准接口关联(推荐)

调用GetProfiles接口获取每个通道的媒体配置文件,每个配置文件对应一个码流(主/子码流各有独立的Profile),其中包含:

  • Token: 配置文件令牌,调用GetStreamUri时传入该令牌即可获取对应码流的URL
  • Name: 配置文件名称(通常包含通道和码流类型,如Channel 1 Main通道1子码流
  • VideoEncoderConfiguration: 码流参数(分辨率、码率,可通过参数高低区分主/子码流)

示例代码逻辑:

MediaPortClient mediaClient = new MediaPortClient(customBinding, new EndpointAddress("http://" + deviceIp + ":" + port + "/onvif/media_service"));
mediaClient.Endpoint.Behaviors.Add(passwordDigestBehavior);

var profiles = mediaClient.GetProfiles();
foreach (var profile in profiles)
{
    // 区分主/子码流:通过名称或分辨率判断
    bool isMainStream = profile.Name.Contains("Main") || profile.VideoEncoderConfiguration.Resolution.Width >= 1920;
    string streamType = isMainStream ? "主码流" : "子码流";
    string channelName = profile.Source.Name;

    // 获取对应码流的URL
    var streamUri = mediaClient.GetStreamUri(new Media.StreamSetup { Stream = Media.StreamType.RTPUnicast, Transport = new Media.Transport { Protocol = Media.TransportProtocol.RTSP } }, profile.Token);
    Console.WriteLine($"通道[{channelName}] {streamType} URL: {streamUri.Uri}");
}

方式2:解析URL特征字段(兼容方案)

如果必须通过URL解析,可提取各品牌URL中的通用特征:

  • 通道标识:URL中包含channel=1ch01stream1等字段
  • 码流标识:URL中包含mainsubhighlow101(通道1+主码流)、102(通道1+子码流)等字段

例如:

  • 海康NVR主码流:rtsp://admin:xxx@192.168.1.1:554/Streaming/Channels/101
  • 海康NVR子码流:rtsp://admin:xxx@192.168.1.1:554/Streaming/Channels/102

内容的提问来源于stack exchange,提问作者S. Lui

火山引擎 最新活动