go2rtc icon indicating copy to clipboard operation
go2rtc copied to clipboard

Implement Unifi Protect-complaint output

Open kiler129 opened this issue 2 years ago • 6 comments

Let me preface this suggestion with acknowledging that I am not sure if this is even possible.

The unifi ecosystem is pretty nifty, but the hardware prices are very steep. Their NVR offering is pretty reasonable, but cameras are not. It would be great if go2rtc could support bringing standard RTMP/RTSP cameras into Unifi Protect. UI doesn't seem to be interested in supporting 3rd-party cameras, most likely for business reasons.

There's at least one project (unifi-cam-proxy) implementing that functionality, but it would be great to have it "under one roof" within the swiss-army-knife go2rtc :)

kiler129 avatar Sep 04 '23 18:09 kiler129

Well. unifi-cam-proxy project does many interesting things about passing motion data from different camera brands to Unifi platform. I don't see the point in repeating all this code yet.

AlexxIT avatar Sep 09 '23 14:09 AlexxIT

Please let me know if the problem is relevant

AlexxIT avatar May 28 '24 14:05 AlexxIT

I would have loved to see this feature!

simone-desantis avatar May 28 '24 15:05 simone-desantis

Unfortunately I don't have any Unifi equipment. I don't expect to have any. Maybe someone else would like to add support.

AlexxIT avatar May 28 '24 15:05 AlexxIT

For reference for anyone looking to do this, the protocol doesn’t new to be reverse engineered or anything. UniFi now supports ONVIF.

https://help.ui.com/hc/en-us/articles/26301104828439-Third-Party-Cameras-in-UniFi-Protect

ViViDboarder avatar Oct 29 '24 05:10 ViViDboarder

I am digging through the wireshark diffs now, more to go but two things have jumped out at me so far.

  1. 🚩go2rtc returns unsupported action when unifi protect sends GetVideoSources.

A working response looks like this and appears straight forward to implement here.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
    xmlns:i0="http://www.onvif.org/ver10/device/wsdl" xmlns:tns="http://tempuri.org/"
    xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
    xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema">
    <soap:Body>
        <trt:GetVideoSourcesResponse xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
            xmlns="http://www.onvif.org/ver10/media/wsdl">
            <trt:VideoSources token="video_src_token">
                <trt:Framerate>29.97003</trt:Framerate>
                <trt:Resolution>
                    <trt:Width>1280</trt:Width>
                    <trt:Height>720</trt:Height>
                </trt:Resolution>
            </trt:VideoSources>
        </trt:GetVideoSourcesResponse>
    </soap:Body>
</soap:Envelope>
  1. ❓go2rtc's GetProfilesResponse is missing the VideoSourceConfiguration block in the profile.

It's unclear if it is required but a working response looks like this:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
    xmlns:i0="http://www.onvif.org/ver10/device/wsdl" xmlns:tns="http://tempuri.org/"
    xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
    xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema">
    <soap:Body>
        <trt:GetProfilesResponse xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
            xmlns="http://www.onvif.org/ver10/media/wsdl">
            <trt:Profiles token="main_stream">
                <trt:Name>MainStream</trt:Name>
                <trt:VideoSourceConfiguration token="video_src_config_token">
                    <trt:Name>VideoSource</trt:Name>
                    <trt:UseCount>2</trt:UseCount>
                    <trt:SourceToken>video_src_token</trt:SourceToken>
                    <trt:Bounds x="0" y="0" width="1280" height="720"></trt:Bounds>
                </trt:VideoSourceConfiguration>
                <trt:VideoEncoderConfiguration token="encoder_hq_config_token">
                    <trt:Name>CardinalHqCameraConfiguration</trt:Name>
                    <trt:UseCount>1</trt:UseCount>
                    <trt:Encoding>H264</trt:Encoding>
                    <trt:Resolution>
                        <trt:Width>1280</trt:Width>
                        <trt:Height>720</trt:Height>
                    </trt:Resolution>
                    <trt:Quality>4</trt:Quality>
                    <trt:RateControl>
                        <trt:FrameRateLimit>29.97003</trt:FrameRateLimit>
                        <trt:EncodingInterval>1</trt:EncodingInterval>
                        <trt:BitrateLimit>5000</trt:BitrateLimit>
                    </trt:RateControl>
                    <trt:H264>
                        <trt:GovLength>29.97003</trt:GovLength>
                        <trt:H264Profile>Main</trt:H264Profile>
                    </trt:H264>
                    <trt:SessionTimeout>PT1000S</trt:SessionTimeout>
                </trt:VideoEncoderConfiguration>
            </trt:Profiles>
            <trt:Profiles token="sub_stream">
                <trt:Name>SubStream</trt:Name>
                <trt:VideoSourceConfiguration token="video_src_config_token">
                    <trt:Name>VideoSource</trt:Name>
                    <trt:UseCount>2</trt:UseCount>
                    <trt:SourceToken>video_src_token</trt:SourceToken>
                    <trt:Bounds x="0" y="0" width="1280" height="720"></trt:Bounds>
                </trt:VideoSourceConfiguration>
                <trt:VideoEncoderConfiguration token="encoder_lq_config_token">
                    <trt:Name>CardinalLqCameraConfiguration</trt:Name>
                    <trt:UseCount>1</trt:UseCount>
                    <trt:Encoding>H264</trt:Encoding>
                    <trt:Resolution>
                        <trt:Width>854</trt:Width>
                        <trt:Height>480</trt:Height>
                    </trt:Resolution>
                    <trt:Quality>4</trt:Quality>
                    <trt:RateControl>
                        <trt:FrameRateLimit>29.97003</trt:FrameRateLimit>
                        <trt:EncodingInterval>1</trt:EncodingInterval>
                        <trt:BitrateLimit>1000</trt:BitrateLimit>
                    </trt:RateControl>
                    <trt:H264>
                        <trt:GovLength>29.97003</trt:GovLength>
                        <trt:H264Profile>Main</trt:H264Profile>
                    </trt:H264>
                    <trt:SessionTimeout>PT1000S</trt:SessionTimeout>
                </trt:VideoEncoderConfiguration>
            </trt:Profiles>
        </trt:GetProfilesResponse>
    </soap:Body>
</soap:Envelope>

I'll set up a go2rtc instance with main_stream and sub_stream and see how where that gets me but I expect that GetVideoSourcesResponse will need to be implemented before moving further.

It's not clear yet which of these names/tokens are arbitrary or if they are meaningful, but at least we've got an idea of where we need look.

acortelyou avatar Nov 20 '24 21:11 acortelyou