Onvif Profile G视频片段获取问题:GetReplayUri时间参数无效
解决Onvif GetReplayUri获取指定时间范围录像的问题
直接在RTSP URL后拼接start和end参数无效,核心原因是Onvif标准中指定回放时间范围的正确方式是在调用GetReplayUri接口时传入时间范围参数,而非事后修改URL。不同厂商的RTSP私有参数格式不统一,这种拼接方式不具备通用性,也不符合Onvif规范。
正确实现步骤
- 设置GetReplayUri请求的时间范围:
Onvif的GetReplayUri请求结构体(GetReplayUri_tmp)包含TimeRange字段(部分设备对应ReplayConfiguration下的时间参数),必须在调用接口前为其赋值合法的ISO8601格式UTC时间。 - 确保时间格式合规:
Onvif要求时间格式为YYYY-MM-DDTHH:MM:SSZ(UTC时间),不能直接传递原始时间戳或本地时间字符串。
修改后的代码示例
// 1. 初始化时间范围参数 GetReplayUri_tmp.TimeRange = new tt__DateTimeRange(); // 2. 将startTime、endTime转换为Onvif要求的ISO8601 UTC格式 // 假设startTime和endTime是秒级时间戳,需转换为UTC时间字符串 char start_str[32], end_str[32]; struct tm start_tm, end_tm; gmtime_r(&startTime, &start_tm); gmtime_r(&endTime, &end_tm); strftime(start_str, sizeof(start_str), "%Y-%m-%dT%H:%M:%SZ", &start_tm); strftime(end_str, sizeof(end_str), "%Y-%m-%dT%H:%M:%SZ", &end_tm); // 3. 为时间范围字段赋值 GetReplayUri_tmp.TimeRange->Start = soap_new_std__string(deviceReplayBindingProxy->soap, 1); *GetReplayUri_tmp.TimeRange->Start = start_str; GetReplayUri_tmp.TimeRange->End = soap_new_std__string(deviceReplayBindingProxy->soap, 1); *GetReplayUri_tmp.TimeRange->End = end_str; // 4. 调用GetReplayUri接口 AddUsernameTokenDigest(deviceReplayBindingProxy, NULL, GetUser(), GetPwd(), deltaT); if (deviceReplayBindingProxy->GetReplayUri(&GetReplayUri_tmp, GetReplayUriResponse_tmp) != SOAP_OK) { // 清理资源 soap_delete(deviceReplayBindingProxy->soap, GetReplayUri_tmp.TimeRange); return NC_INTERNAL_ERROR; } // 直接使用返回的Uri即可,无需额外拼接参数 std::string RTSP_url = GetReplayUriResponse_tmp.Uri; // 按需清理soap资源 soap_delete(deviceReplayBindingProxy->soap, GetReplayUri_tmp.TimeRange);
额外排查点
- 检查设备兼容性:部分低端SD卡设备可能不支持通过GetReplayUri直接指定时间范围,此时需先调用
SearchRecordings接口查询符合时间范围的录像片段,再通过GetReplayUri获取对应片段的流地址。 - 验证时间合法性:确保
End时间晚于Start时间,且时间范围在设备已存储录像的区间内。 - 核对soap结构体字段:不同版本的Onvif soap生成代码,结构体字段名可能略有差异(比如部分版本用
tt__TimeRange而非tt__DateTimeRange),需对照设备的Onvif文档或wsdl文件确认。
内容的提问来源于stack exchange,提问作者Massimo
相关产品推荐
相关产品推荐

