1.基本流程
- 加入组播udp接口,查询子网内在线的ONVIF摄像头的设备地址:
设备地址形如:http://192.168.0.6/onvif/device_service
这一步,参看上一篇发文:[ONVIF系列 - 01] 简介 - 设备发现 - 相关工具-CSDN博客 - 查询mediaService Uri地址
mediaService地址形如:
http://192.168.0.6/onvif/Media - 查询用户的Profiles,得到一个我们需要的Profile
Profile形如:Profile_1 - 发出查询Profile详情请求给ONVIF mediaServiceUri得到最终的媒体流Uri:
形如:rtsp://192.168.0.6:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_1
1.1 Python代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 获取当前脚本文件所在目录的父目录,并构建相对路径
import os
import sys
current_dir = os.path.dirname(os.path.abspath(__file__))
project_path = os.path.join(current_dir, '..')
sys.path.append(project_path)
sys.path.append(current_dir)
import asyncio
import aiohttp
import xml.etree.ElementTree as ET
from httpx import AsyncClient, DigestAuth
import httpx
# ONVIF 设备服务 URL
device_service_url = 'http://192.168.0.6/onvif/device_service'
username = 'xxxxx'
password = 'xxxxxxx'
async def get_device_information(session, url):
headers = {'Content-Type': 'application/soap+xml'}
body = """<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
<s:Header/>
<s:Body>
<tds:GetServices>
<tds:IncludeCapability>false</tds:IncludeCapability>
</tds:GetServices>
</s:Body>
</s:Envelope>"""
try:
response = httpx.post(url, headers=headers, data=body, auth=DigestAuth(username, password))
return response.text
except Exception as e:
print(f'An error occurred: {e}')
return None
def parse_media_service_url(device_response):
media_service_url = None
root = ET.fromstring(device_response)
ns = {'soap': 'http://www.w3.org/2003/05/soap-envelope', 'tds': 'http://www.onvif.org/ver10/device/wsdl'}
services = root.find('.//tds:GetServicesResponse', namespaces=ns)
#print(services)
# 查找 <tds:XAddr> 元素
for s in services:
ns1 = s.find('.//tds:Namespace', namespaces=ns)
if(ns1 is not None):
print('........ns................',ns1.text)
if('media' in ns1.text) and ('ver10' in ns1.text):
addr = s.find('.//tds:XAddr', namespaces = ns)
if(addr is not None):
#print('........addr................',addr)
media_service_url = addr.text
return media_service_url
async def get_media_profiles(session, media_service_url):
headers = {'Content-Type': 'application/soap+xml'}
body = """<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:media="http://www.onvif.org/ver10/media/wsdl">
<soapenv:Header/>
<soapenv:Body>
<media:GetProfiles/>
</soapenv:Body>
</soapenv:Envelope>"""
try:
response = httpx.post(media_service_url, headers=headers, data=body, auth=DigestAuth(username, password))
return response.text
except Exception as e:
print(f'An error occurred: {e}')
return None
def parse_media_profile(profile_response):
profile_token = None
root = ET.fromstring(profile_response)
ns = {'trt': 'http://www.onvif.org/ver10/media/wsdl', 'tt': 'http://www.onvif.org/ver10/schema'}
profiles = root.find('.//trt:GetProfilesResponse', namespaces=ns)
# 查找 <tds:XAddr> 元素
for s in profiles:
profile_token = s.get('token')
print(profile_token)
break
return profile_token
async def get_video_stream_url(session, media_service_url, profileToken):
headers = {'Content-Type': 'application/soap+xml'}
body = """<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:t="http://www.onvif.org/ver10/media">
<s:Body>
<t:GetStreamUri>
<t:StreamSetup>
<t:Stream>RTP-Unicast</t:Stream>
<t:Transport>
<t:Protocol>RTSP</t:Protocol>
</t:Transport>
</t:StreamSetup>
<t:ProfileToken>YourProfileToken</t:ProfileToken>
</t:GetStreamUri>
</s:Body>
</s:Envelope>"""
try:
src_sub_str = '<t:ProfileToken>YourProfileToken</t:ProfileToken>'
real_sub_str = f'<t:ProfileToken>{profileToken}</t:ProfileToken>'
body = body.replace(src_sub_str, real_sub_str)
response = httpx.post(media_service_url, headers=headers, data=body, auth=DigestAuth(username, password))
return response.text
except Exception as e:
print(f'An error occurred: {e}')
return None
def parse_video_stream_url(media_response):
root = ET.fromstring(media_response)
ns = {'soap': 'http://www.w3.org/2003/05/soap-envelope', 'trt': 'http://www.onvif.org/ver10/media/wsdl','tt': 'http://www.onvif.org/ver10/schema'}
uri = root.find('.//trt:GetStreamUriResponse//trt:MediaUri//tt:Uri', namespaces=ns) #//trt:MediaUri
if uri is not None:
return uri.text
return None
async def main():
async with httpx.AsyncClient() as session:
device_response = await get_device_information(session, device_service_url)
#print(device_response)
print('>>>>>>>>>>>>>>>>>>>>>>>>>>>step1 get media soap addr')
media_service_url = parse_media_service_url(device_response)
print(media_service_url)
if not media_service_url:
print("Media service URL not found")
return
profile_response = await get_media_profiles(session, media_service_url)
#print(profile_response)
print('>>>>>>>>>>>>>>>>>>>>>>>>>>>step2 get profile token')
profile = parse_media_profile(profile_response)
#print(profile)
if not profile:
print("Media profile not found")
media_response = await get_video_stream_url(session, media_service_url, profile)
print(media_response)
print('>>>>>>>>>>>>>>>>>>>>>>>>>>>step3 get stream url')
video_stream_url = parse_video_stream_url(media_response)
print("Video Stream URL:", video_stream_url)
# 运行异步主函数
if __name__ == '__main__':
asyncio.run(main())
1.2 代码说明
1.2.1 权限控制
soap消息如果涉及权限控制,asyncio需要借助httpx才能进行——就是ONVIF,Post Soap消息时涉及的auth=DigestAuth()。
1.2.2 soap消息
soap消息是一个xml, 我们使用ET.fromstring(device_response)来进行处理。
1.2.3 xml解析的名字空间
xml解析中一个重要的概念是ns,名字空间,如果我们需要的信息被包裹为:
<trt:GetStreamUriResponse><trt:MediaUri><tt:Uri>rtsp://192.168.0.6:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_1</tt:Uri>
<tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>
<tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>
<tt:Timeout>PT60S</tt:Timeout>
</trt:MediaUri>
</trt:GetStreamUriResponse>
注意xml元素的被冒号:分割的前导部分,比如trt,tt,这些元素在进行解析前需要预先声明:
ns = {'soap': 'http://www.w3.org/2003/05/soap-envelope', 'tds': 'http://www.onvif.org/ver10/device/wsdl'}
1.2.4 xml元素的逐级搜索
xml解析类似json,可以先拿到一个分支节点,再以分支节点为搜索起点,继续搜索,比如:
def parse_media_service_url(device_response):
media_service_url = None
root = ET.fromstring(device_response)
ns = {'soap': 'http://www.w3.org/2003/05/soap-envelope', 'tds': 'http://www.onvif.org/ver10/device/wsdl'}
services = root.find('.//tds:GetServicesResponse', namespaces=ns)
#print(services)
# 查找 <tds:XAddr> 元素
for s in services:
ns1 = s.find('.//tds:Namespace', namespaces=ns)
if(ns1 is not None):
print('........ns................',ns1.text)
if('media' in ns1.text) and ('ver10' in ns1.text):
addr = s.find('.//tds:XAddr', namespaces = ns)
if(addr is not None):
#print('........addr................',addr)
media_service_url = addr.text
return media_service_url
1.2.5 xml元素的按照路径信息一次定位
def parse_video_stream_url(media_response):
root = ET.fromstring(media_response)
ns = {'soap': 'http://www.w3.org/2003/05/soap-envelope', 'trt': 'http://www.onvif.org/ver10/media/wsdl','tt': 'http://www.onvif.org/ver10/schema'}
uri = root.find('.//trt:GetStreamUriResponse//trt:MediaUri//tt:Uri', namespaces=ns) #//trt:MediaUri
if uri is not None:
return uri.text
return None
2交互过程的回应帧和特征信息
2.1查询onvif device uri得到media services uri
2.1.1 查询帧
headers = {'Content-Type': 'application/soap+xml'}
body = """<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
<s:Header/>
<s:Body>
<tds:GetServices>
<tds:IncludeCapability>false</tds:IncludeCapability>
</tds:GetServices>
</s:Body>
</s:Envelope>"""
2.1.2 回应帧( 片段)
<tds:Service><tds:Namespace>http://www.onvif.org/ver10/media/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.6/onvif/Media</tds:XAddr>
<tds:Version><tt:Major>2</tt:Major>
<tt:Minor>60</tt:Minor>
</tds:Version>
</tds:Service>
回应帧中可能有多个media services接口,选择版本最低的就行:
........ns................ http://www.onvif.org/ver10/device/wsdl
........ns................ http://www.onvif.org/ver10/media/wsdl
........ns................ http://www.onvif.org/ver10/events/wsdl
........ns................ http://www.onvif.org/ver20/imaging/wsdl
........ns................ http://www.onvif.org/ver10/deviceIO/wsdl
........ns................ http://www.onvif.org/ver20/analytics/wsdl
........ns................ http://www.onvif.org/ver20/media/wsdl
2.2 查询media sevices uri Profiles得到所需Profile
2.2.1 查询帧
headers = {'Content-Type': 'application/soap+xml'}
body = """<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:media="http://www.onvif.org/ver10/media/wsdl">
<soapenv:Header/>
<soapenv:Body>
<media:GetProfiles/>
</soapenv:Body>
</soapenv:Envelope>"""
2.2.2 回应帧(片段)
<trt:GetProfilesResponse><trt:Profiles token="Profile_1" fixed="true"><tt:Name>mainStream</tt:Name>
<tt:VideoSourceConfiguration token="VideoSourceToken"><tt:Name>VideoSourceConfig</tt:Name>
<tt:UseCount>2</tt:UseCount>
<tt:SourceToken>VideoSource_1</tt:SourceToken>
<tt:Bounds x="0" y="0" width="1920" height="1080"></tt:Bounds>
</tt:VideoSourceConfiguration>
<tt:VideoEncoderConfiguration token="VideoEncoderToken_1"><tt:Name>VideoEncoder_1</tt:Name>
<tt:UseCount>1</tt:UseCount>
<tt:Encoding>H264</tt:Encoding>
<tt:Resolution><tt:Width>1920</tt:Width>
<tt:Height>1080</tt:Height>
</tt:Resolution>
<tt:Quality>3.000000</tt:Quality>
<tt:RateControl><tt:FrameRateLimit>10</tt:FrameRateLimit>
<tt:EncodingInterval>1</tt:EncodingInterval>
<tt:BitrateLimit>1024</tt:BitrateLimit>
</tt:RateControl>
<tt:H264><tt:GovLength>20</tt:GovLength>
<tt:H264Profile>Main</tt:H264Profile>
</tt:H264>
2.3 查询 media services uri得到流媒体uri
2.3.1 查询帧
headers = {'Content-Type': 'application/soap+xml'}
body = """<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:t="http://www.onvif.org/ver10/media">
<s:Body>
<t:GetStreamUri>
<t:StreamSetup>
<t:Stream>RTP-Unicast</t:Stream>
<t:Transport>
<t:Protocol>RTSP</t:Protocol>
</t:Transport>
</t:StreamSetup>
<t:ProfileToken>YourProfileToken</t:ProfileToken>
</t:GetStreamUri>
</s:Body>
</s:Envelope>"""
2.3.2 回应帧(片段)
<trt:GetStreamUriResponse><trt:MediaUri><tt:Uri>rtsp://192.168.0.6:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_1</tt:Uri>
<tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>
<tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>
<tt:Timeout>PT60S</tt:Timeout>
</trt:MediaUri>
</trt:GetStreamUriResponse>
附录A 与ONVIF视频流地址获取相关的摄像头回应帧
1. MediaService Uri查询回应
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl" xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12" xmlns:http="http://schemas.xmlsoap.org/wsdl/http" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2" xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:trc="http://www.onvif.org/ver10/recording/wsdl" xmlns:tse="http://www.onvif.org/ver10/search/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tnshik="http://www.hikvision.com/2011/event/topics" xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl" xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema" xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl" xmlns:tr2="http://www.onvif.org/ver20/media/wsdl" xmlns:axt="http://www.onvif.org/ver20/analytics"><env:Body><tds:GetServicesResponse><tds:Service><tds:Namespace>http://www.onvif.org/ver10/device/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.6/onvif/device_service</tds:XAddr>
<tds:Version><tt:Major>17</tt:Major>
<tt:Minor>12</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service><tds:Namespace>http://www.onvif.org/ver10/media/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.6/onvif/Media</tds:XAddr>
<tds:Version><tt:Major>2</tt:Major>
<tt:Minor>60</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service><tds:Namespace>http://www.onvif.org/ver10/events/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.6/onvif/Events</tds:XAddr>
<tds:Version><tt:Major>2</tt:Major>
<tt:Minor>60</tt:Minor>
</tds:Version>
2.Profiles 查询回应
消息中对我们需要的部分做了标注
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl" xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12" xmlns:http="http://schemas.xmlsoap.org/wsdl/http" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2" xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:trc="http://www.onvif.org/ver10/recording/wsdl" xmlns:tse="http://www.onvif.org/ver10/search/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tnshik="http://www.hikvision.com/2011/event/topics" xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl" xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema" xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl" xmlns:tr2="http://www.onvif.org/ver20/media/wsdl" xmlns:axt="http://www.onvif.org/ver20/analytics"><env:Body><trt:GetProfilesResponse><trt:Profiles token="Profile_1" fixed="true"><tt:Name>mainStream</tt:Name>
<tt:VideoSourceConfiguration token="VideoSourceToken"><tt:Name>VideoSourceConfig</tt:Name>
<tt:UseCount>2</tt:UseCount>
<tt:SourceToken>VideoSource_1</tt:SourceToken>
<tt:Bounds x="0" y="0" width="1920" height="1080"></tt:Bounds>
</tt:VideoSourceConfiguration>
<tt:VideoEncoderConfiguration token="VideoEncoderToken_1"><tt:Name>VideoEncoder_1</tt:Name>
<tt:UseCount>1</tt:UseCount>
<tt:Encoding>H264</tt:Encoding>
<tt:Resolution><tt:Width>1920</tt:Width>
<tt:Height>1080</tt:Height>
</tt:Resolution>
<tt:Quality>3.000000</tt:Quality>
<tt:RateControl><tt:FrameRateLimit>10</tt:FrameRateLimit>
<tt:EncodingInterval>1</tt:EncodingInterval>
<tt:BitrateLimit>1024</tt:BitrateLimit>
</tt:RateControl>
<tt:H264><tt:GovLength>20</tt:GovLength>
<tt:H264Profile>Main</tt:H264Profile>
</tt:H264>
<tt:Multicast><tt:Address><tt:Type>IPv4</tt:Type>
<tt:IPv4Address>0.0.0.0</tt:IPv4Address>
</tt:Address>
<tt:Port>8860</tt:Port>
<tt:TTL>128</tt:TTL>
<tt:AutoStart>false</tt:AutoStart>
</tt:Multicast>
<tt:SessionTimeout>PT5S</tt:SessionTimeout>
</tt:VideoEncoderConfiguration>
<tt:VideoAnalyticsConfiguration token="VideoAnalyticsToken"><tt:Name>VideoAnalyticsName</tt:Name>
<tt:UseCount>2</tt:UseCount>
<tt:AnalyticsEngineConfiguration><tt:AnalyticsModule Name="MyCellMotionModule" Type="tt:CellMotionEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="60"/>
<tt:ElementItem Name="Layout"><tt:CellLayout Columns="22" Rows="18"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/>
<tt:Scale x="0.090909" y="0.111111"/>
</tt:Transformation>
</tt:CellLayout>
</tt:ElementItem>
</tt:Parameters>
</tt:AnalyticsModule>
<tt:AnalyticsModule Name="MyLineDetectorModule" Type="tt:LineDetectorEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="50"/>
<tt:ElementItem Name="Transformation"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/>
<tt:Scale x="0.002000" y="0.002000"/>
</tt:Transformation>
</tt:ElementItem>
<tt:ElementItem Name="Field"><tt:PolygonConfiguration><tt:Polygon><tt:Point x="0" y="0"/>
<tt:Point x="0" y="1000"/>
<tt:Point x="1000" y="1000"/>
<tt:Point x="1000" y="0"/>
</tt:Polygon>
</tt:PolygonConfiguration>
</tt:ElementItem>
</tt:Parameters>
</tt:AnalyticsModule>
<tt:AnalyticsModule Name="MyFieldDetectorModule" Type="tt:FieldDetectorEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="50"/>
<tt:ElementItem Name="Transformation"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/>
<tt:Scale x="0.002000" y="0.002000"/>
</tt:Transformation>
</tt:ElementItem>
<tt:ElementItem Name="Field"><tt:PolygonConfiguration><tt:Polygon><tt:Point x="0" y="0"/>
<tt:Point x="0" y="1000"/>
<tt:Point x="1000" y="1000"/>
<tt:Point x="1000" y="0"/>
</tt:Polygon>
</tt:PolygonConfiguration>
</tt:ElementItem>
</tt:Parameters>
</tt:AnalyticsModule>
<tt:AnalyticsModule Name="MyTamperDetecModule" Type="hikxsd:TamperEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="0"/>
<tt:ElementItem Name="Transformation"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/>
<tt:Scale x="0.002841" y="0.003472"/>
</tt:Transformation>
</tt:ElementItem>
<tt:ElementItem Name="Field"><tt:PolygonConfiguration><tt:Polygon><tt:Point x="0" y="0"/>
<tt:Point x="0" y="576"/>
<tt:Point x="704" y="576"/>
<tt:Point x="704" y="0"/>
</tt:Polygon>
</tt:PolygonConfiguration>
</tt:ElementItem>
</tt:Parameters>
</tt:AnalyticsModule>
</tt:AnalyticsEngineConfiguration>
<tt:RuleEngineConfiguration><tt:Rule Name="MyMotionDetectorRule" Type="tt:CellMotionDetector"><tt:Parameters><tt:SimpleItem Name="MinCount" Value="5"/>
<tt:SimpleItem Name="AlarmOnDelay" Value="1000"/>
<tt:SimpleItem Name="AlarmOffDelay" Value="1000"/>
<tt:SimpleItem Name="ActiveCells" Value="0P8A8A=="/>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyLineDetector1" Type="tt:LineDetector"><tt:Parameters><tt:SimpleItem Name="Direction" Value="Any"/>
<tt:ElementItem Name="Segments"><tt:Polyline><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polyline>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyLineDetector2" Type="tt:LineDetector"><tt:Parameters><tt:SimpleItem Name="Direction" Value="Any"/>
<tt:ElementItem Name="Segments"><tt:Polyline><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polyline>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyLineDetector3" Type="tt:LineDetector"><tt:Parameters><tt:SimpleItem Name="Direction" Value="Any"/>
<tt:ElementItem Name="Segments"><tt:Polyline><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polyline>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyLineDetector4" Type="tt:LineDetector"><tt:Parameters><tt:SimpleItem Name="Direction" Value="Any"/>
<tt:ElementItem Name="Segments"><tt:Polyline><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polyline>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyFieldDetector1" Type="tt:FieldDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:Polygon><tt:Point x="50.000000" y="250.000000"/>
<tt:Point x="50.000000" y="1000.000000"/>
<tt:Point x="950.000000" y="1000.000000"/>
<tt:Point x="950.000000" y="250.000000"/>
</tt:Polygon>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyFieldDetector2" Type="tt:FieldDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:Polygon><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polygon>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyFieldDetector3" Type="tt:FieldDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:Polygon><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polygon>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyFieldDetector4" Type="tt:FieldDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:Polygon><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polygon>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyTamperDetectorRule" Type="hikxsd:TamperDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:PolygonConfiguration><tt:Polygon><tt:Point x="0" y="0"/>
<tt:Point x="0" y="0"/>
<tt:Point x="0" y="0"/>
<tt:Point x="0" y="0"/>
</tt:Polygon>
</tt:PolygonConfiguration>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
</tt:RuleEngineConfiguration>
</tt:VideoAnalyticsConfiguration>
<tt:Extension></tt:Extension>
</trt:Profiles>
<trt:Profiles token="Profile_2" fixed="true"><tt:Name>subStream</tt:Name>
<tt:VideoSourceConfiguration token="VideoSourceToken"><tt:Name>VideoSourceConfig</tt:Name>
<tt:UseCount>2</tt:UseCount>
<tt:SourceToken>VideoSource_1</tt:SourceToken>
<tt:Bounds x="0" y="0" width="1920" height="1080"></tt:Bounds>
</tt:VideoSourceConfiguration>
<tt:VideoEncoderConfiguration token="VideoEncoderToken_2" encoding="H265"><tt:Name>VideoEncoder_2</tt:Name>
<tt:UseCount>1</tt:UseCount>
<tt:Encoding>H264</tt:Encoding>
<tt:Resolution><tt:Width>640</tt:Width>
<tt:Height>360</tt:Height>
</tt:Resolution>
<tt:Quality>3.000000</tt:Quality>
<tt:RateControl><tt:FrameRateLimit>10</tt:FrameRateLimit>
<tt:EncodingInterval>1</tt:EncodingInterval>
<tt:BitrateLimit>512</tt:BitrateLimit>
</tt:RateControl>
<tt:H264><tt:GovLength>20</tt:GovLength>
<tt:H264Profile>Main</tt:H264Profile>
</tt:H264>
<tt:Multicast><tt:Address><tt:Type>IPv4</tt:Type>
<tt:IPv4Address>0.0.0.0</tt:IPv4Address>
</tt:Address>
<tt:Port>8866</tt:Port>
<tt:TTL>128</tt:TTL>
<tt:AutoStart>false</tt:AutoStart>
</tt:Multicast>
<tt:SessionTimeout>PT5S</tt:SessionTimeout>
</tt:VideoEncoderConfiguration>
<tt:VideoAnalyticsConfiguration token="VideoAnalyticsToken"><tt:Name>VideoAnalyticsName</tt:Name>
<tt:UseCount>2</tt:UseCount>
<tt:AnalyticsEngineConfiguration><tt:AnalyticsModule Name="MyCellMotionModule" Type="tt:CellMotionEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="60"/>
<tt:ElementItem Name="Layout"><tt:CellLayout Columns="22" Rows="18"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/>
<tt:Scale x="0.090909" y="0.111111"/>
</tt:Transformation>
</tt:CellLayout>
</tt:ElementItem>
</tt:Parameters>
</tt:AnalyticsModule>
<tt:AnalyticsModule Name="MyLineDetectorModule" Type="tt:LineDetectorEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="50"/>
<tt:ElementItem Name="Transformation"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/>
<tt:Scale x="0.002000" y="0.002000"/>
</tt:Transformation>
</tt:ElementItem>
<tt:ElementItem Name="Field"><tt:PolygonConfiguration><tt:Polygon><tt:Point x="0" y="0"/>
<tt:Point x="0" y="1000"/>
<tt:Point x="1000" y="1000"/>
<tt:Point x="1000" y="0"/>
</tt:Polygon>
</tt:PolygonConfiguration>
</tt:ElementItem>
</tt:Parameters>
</tt:AnalyticsModule>
<tt:AnalyticsModule Name="MyFieldDetectorModule" Type="tt:FieldDetectorEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="50"/>
<tt:ElementItem Name="Transformation"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/>
<tt:Scale x="0.002000" y="0.002000"/>
</tt:Transformation>
</tt:ElementItem>
<tt:ElementItem Name="Field"><tt:PolygonConfiguration><tt:Polygon><tt:Point x="0" y="0"/>
<tt:Point x="0" y="1000"/>
<tt:Point x="1000" y="1000"/>
<tt:Point x="1000" y="0"/>
</tt:Polygon>
</tt:PolygonConfiguration>
</tt:ElementItem>
</tt:Parameters>
</tt:AnalyticsModule>
<tt:AnalyticsModule Name="MyTamperDetecModule" Type="hikxsd:TamperEngine"><tt:Parameters><tt:SimpleItem Name="Sensitivity" Value="0"/>
<tt:ElementItem Name="Transformation"><tt:Transformation><tt:Translate x="-1.000000" y="-1.000000"/>
<tt:Scale x="0.002841" y="0.003472"/>
</tt:Transformation>
</tt:ElementItem>
<tt:ElementItem Name="Field"><tt:PolygonConfiguration><tt:Polygon><tt:Point x="0" y="0"/>
<tt:Point x="0" y="576"/>
<tt:Point x="704" y="576"/>
<tt:Point x="704" y="0"/>
</tt:Polygon>
</tt:PolygonConfiguration>
</tt:ElementItem>
</tt:Parameters>
</tt:AnalyticsModule>
</tt:AnalyticsEngineConfiguration>
<tt:RuleEngineConfiguration><tt:Rule Name="MyMotionDetectorRule" Type="tt:CellMotionDetector"><tt:Parameters><tt:SimpleItem Name="MinCount" Value="5"/>
<tt:SimpleItem Name="AlarmOnDelay" Value="1000"/>
<tt:SimpleItem Name="AlarmOffDelay" Value="1000"/>
<tt:SimpleItem Name="ActiveCells" Value="0P8A8A=="/>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyLineDetector1" Type="tt:LineDetector"><tt:Parameters><tt:SimpleItem Name="Direction" Value="Any"/>
<tt:ElementItem Name="Segments"><tt:Polyline><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polyline>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyLineDetector2" Type="tt:LineDetector"><tt:Parameters><tt:SimpleItem Name="Direction" Value="Any"/>
<tt:ElementItem Name="Segments"><tt:Polyline><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polyline>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyLineDetector3" Type="tt:LineDetector"><tt:Parameters><tt:SimpleItem Name="Direction" Value="Any"/>
<tt:ElementItem Name="Segments"><tt:Polyline><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polyline>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyLineDetector4" Type="tt:LineDetector"><tt:Parameters><tt:SimpleItem Name="Direction" Value="Any"/>
<tt:ElementItem Name="Segments"><tt:Polyline><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polyline>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyFieldDetector1" Type="tt:FieldDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:Polygon><tt:Point x="50.000000" y="250.000000"/>
<tt:Point x="50.000000" y="1000.000000"/>
<tt:Point x="950.000000" y="1000.000000"/>
<tt:Point x="950.000000" y="250.000000"/>
</tt:Polygon>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyFieldDetector2" Type="tt:FieldDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:Polygon><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polygon>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyFieldDetector3" Type="tt:FieldDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:Polygon><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polygon>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyFieldDetector4" Type="tt:FieldDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:Polygon><tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
<tt:Point x="0.000000" y="0.000000"/>
</tt:Polygon>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
<tt:Rule Name="MyTamperDetectorRule" Type="hikxsd:TamperDetector"><tt:Parameters><tt:ElementItem Name="Field"><tt:PolygonConfiguration><tt:Polygon><tt:Point x="0" y="0"/>
<tt:Point x="0" y="0"/>
<tt:Point x="0" y="0"/>
<tt:Point x="0" y="0"/>
</tt:Polygon>
</tt:PolygonConfiguration>
</tt:ElementItem>
</tt:Parameters>
</tt:Rule>
</tt:RuleEngineConfiguration>
</tt:VideoAnalyticsConfiguration>
<tt:Extension></tt:Extension>
</trt:Profiles>
</trt:GetProfilesResponse>
</env:Body>
</env:Envelope>
3. stream uri - Profile Desc 查询回应
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl" xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12" xmlns:http="http://schemas.xmlsoap.org/wsdl/http" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2" xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:trc="http://www.onvif.org/ver10/recording/wsdl" xmlns:tse="http://www.onvif.org/ver10/search/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tnshik="http://www.hikvision.com/2011/event/topics" xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl" xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema" xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl" xmlns:tr2="http://www.onvif.org/ver20/media/wsdl" xmlns:axt="http://www.onvif.org/ver20/analytics"><env:Body><trt:GetStreamUriResponse><trt:MediaUri><tt:Uri>rtsp://192.168.0.6:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_1</tt:Uri>
<tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>
<tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>
<tt:Timeout>PT60S</tt:Timeout>
</trt:MediaUri>
</trt:GetStreamUriResponse>
</env:Body>
</env:Envelope>