ONVIF 摄像头视频流获取 - 步骤与Python例程

1.基本流程

  1. 加入组播udp接口,查询子网内在线的ONVIF摄像头的设备地址:
    设备地址形如:http://192.168.0.6/onvif/device_service
    这一步,参看上一篇发文:[ONVIF系列 - 01] 简介 - 设备发现 - 相关工具-CSDN博客
  2. 查询mediaService Uri地址
    mediaService地址形如:
    http://192.168.0.6/onvif/Media
  3. 查询用户的Profiles,得到一个我们需要的Profile
    Profile形如:Profile_1
  4. 发出查询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&amp;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&amp;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&amp;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>

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子正

thanks, bro...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值