I see that the ONVIF Device Manager finds the stream URL of compatible cameras. But how is it done? Is there a method for finding RTSP paths of ONVIF cameras?
3 Answers
According to the ONVIF Core Specification, an ONVIF-compliant device has its device management entry point fixed to:
http://${HOST}:${PORT}/onvif/device_service
This endpoint is used for device interactions using SOAP actions/operations/commands.
A further specification, the ONVIF Media Service Specification, defines operations for querying a device's supported profiles.
The GetProfiles command provides an overview about all profiles a device has to offer. Here is an example GetProfiles invocation using curl (and xmllint for prettyprinting the response):
curl -X POST http://192.168.178.22:8080/onvif/device_service\
-H 'Content-Type: application/soap+xml; charset=utf-8'\
-H 'SOAPAction: "http://www.onvif.org/ver10/media/wsdl/GetProfiles"'\
-d '
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsdl="http://www.onvif.org/ver10/media/wsdl">
<soap:Header/>
<soap:Body>
<wsdl:GetProfiles/>
</soap:Body>
</soap:Envelope>
' | xmllint --format -
My ONVIF device responds to this command with the following (abbreviated):
<SOAP-ENV:Envelope ...>
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<trt:GetProfilesResponse>
<trt:Profiles token="h264_ulaw_1920x1080" fixed="true">
<tt:Name>h264_ulaw_1920x1080</tt:Name>
<tt:VideoSourceConfiguration token="1920x1080_Config">
<tt:Name>1920x1080_Config</tt:Name>
<tt:UseCount>1</tt:UseCount>
<tt:SourceToken>1920x1080</tt:SourceToken>
<tt:Bounds x="0" y="0" width="1920" height="1080"/>
</tt:VideoSourceConfiguration>
<tt:AudioSourceConfiguration token="MicrophoneConfig">
<tt:Name>MicrophoneConfig</tt:Name>
<tt:UseCount>1</tt:UseCount>
<tt:SourceToken>Microphone</tt:SourceToken>
</tt:AudioSourceConfiguration>
<tt:VideoEncoderConfiguration token="h264">
<tt:Name>h264</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>0</tt:Quality>
<tt:RateControl>
<tt:FrameRateLimit>30</tt:FrameRateLimit>
<tt:EncodingInterval>1</tt:EncodingInterval>
<tt:BitrateLimit>2000</tt:BitrateLimit>
</tt:RateControl>
<tt:H264>
<tt:GovLength>150</tt:GovLength>
<tt:H264Profile>Baseline</tt:H264Profile>
</tt:H264>
<tt:Multicast>
<tt:Address>
<tt:Type>IPv4</tt:Type>
<tt:IPv4Address>192.168.178.22:8080</tt:IPv4Address>
</tt:Address>
<tt:Port>8080</tt:Port>
<tt:TTL>30</tt:TTL>
<tt:AutoStart>false</tt:AutoStart>
</tt:Multicast>
<tt:SessionTimeout>PT00H00M30S</tt:SessionTimeout>
</tt:VideoEncoderConfiguration>
<tt:AudioEncoderConfiguration token="AudioEncoder">
<tt:Name>AudioEncoder</tt:Name>
<tt:UseCount>0</tt:UseCount>
<tt:Encoding>G711</tt:Encoding>
<tt:Bitrate>1</tt:Bitrate>
<tt:SampleRate>8000</tt:SampleRate>
<tt:Multicast>
<tt:Address>
<tt:Type>IPv4</tt:Type>
<tt:IPv4Address>192.168.178.22:8080</tt:IPv4Address>
</tt:Address>
<tt:Port>8080</tt:Port>
<tt:TTL>30</tt:TTL>
<tt:AutoStart>false</tt:AutoStart>
</tt:Multicast>
<tt:SessionTimeout>PT00H00M30S</tt:SessionTimeout>
</tt:AudioEncoderConfiguration>
</trt:Profiles>
<trt:Profiles token="jpeg_ulaw_1920x1080" fixed="true">
<!-- -->
</trt:Profiles>
<trt:Profiles token="h264_opus_1920x1080" fixed="true">
<!-- -->
</trt:Profiles>
<trt:Profiles token="jpeg_opus_1920x1080" fixed="true">
<!-- -->
</trt:Profiles>
<!-- -->
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
So the GetProfiles response contains a bunch of Profiles elements. Of notice is the token attribute value of each Profiles element, e.g. <Profiles token="h264_ulaw_1920x1080" fixed="true">. These tokens can be used for subsequent queries using the GetStreamUri command:
curl -X POST http://192.168.178.22:8080/onvif/device_service\
-H 'Content-Type: application/soap+xml; charset=utf-8'\
-H 'SOAPAction: "http://www.onvif.org/ver10/media/wsdl/GetStreamUri"'\
-d '
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsdl="http://www.onvif.org/ver10/media/wsdl"
>
<soap:Header/>
<soap:Body>
<wsdl:GetStreamUri>
<wsdl:ProfileToken>h264_ulaw_1920x1080</wsdl:ProfileToken>
</wsdl:GetStreamUri>
</soap:Body>
</soap:Envelope>
' | xmllint --format -
... to which my device responds (abbreviated):
<SOAP-ENV:Envelope ...>
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<trt:GetStreamUriResponse>
<trt:MediaUri>
<tt:Uri>rtsp://192.168.178.22:8080/h264_ulaw.sdp</tt:Uri>
<tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>
<tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>
<tt:Timeout xsi:nil="true"/>
</trt:MediaUri>
</trt:GetStreamUriResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And there we have it: the video stream URL is contained in the <Uri> element: rtsp://192.168.178.22:8080/h264_ulaw.sdp.
- 58,727
- 2,432
I'd like to point out something I noticed about the WSDL standard. I'm trying to get the python-onvif-zeep library to work, and the response my camera generates has some errors, according to a formatting website: https://jsonformatter.org/wsdl-formatter
Perhaps if the client parser expects a faithful response from the camera, errors may occur unexpectedly, such as parameters not found.
Putting the code from Abdull's answer also showed an error:
<SOAP-ENV:Envelope ...> </SOAP-ENV:Envelope>
But if you change from <SOAP-ENV:Envelope ...> to <SOAP-ENV:Envelope> the error no longer appears. It looks like HTML tags to me, which only have <tag> \ </tag>.
If you search the internet for 'onvif wsdl example', you should see XML websites, which if checked do not return errors. It seems to me that some onvif client library codes access these websites to achieve standardization, and some create a local buffer, perhaps to prevent the library from having a larger size, but it must be dependent on internet access.
To see how the WSDL codes appear, just ask the browser to show the source code instead of letting the browser show it already interpreted.
- 58,727
- 1
With the help of both the previous answers, I was able to get mine to work.
Abdul's answer is correct, but my camera required the StreamSetup element as well.
As Giacomo pointed out, viewing the wsdl in a web browser without using "view source" prettied up the output in a way that made it very hard to follow, and I needed to see the "schema" xsd as well to get it right.
What worked for me was the following (change the ip address and the profile token):
curl -i -X POST http://192.168.3.90/onvif/device_service \
-H 'Content-Type: application/soap+xml; charset=utf-8' \
-H 'SOAPAction: "http://www.onvif.org/ver10/media/wsdl/GetStreamUri"' \
-d @- << EOF
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsdl="http://www.onvif.org/ver10/media/wsdl"
xmlns:tt="http://www.onvif.org/ver10/schema">
<soap:Header/>
<soap:Body>
<wsdl:GetStreamUri>
<wsdl:StreamSetup>
<tt:Transport>RTSP</tt:Transport>
<tt:Stream>RTP-Unicast</tt:Stream>
<wsdl:Protocol>RTSP</wsdl:Protocol>
<wsdl:ProfileToken>Profile_1</wsdl:ProfileToken>
</wsdl:GetStreamUri>
</soap:Body>
</soap:Envelope>
EOF
Note the format for doing this changes between onvif ver10 and ver20 -- only the older ver10 format worked, though the output of the camera mentioned ver20 in connection with ptz functions.



