AlexxIT / go2rtc

Ultimate camera streaming application with support RTSP, RTMP, HTTP-FLV, WebRTC, MSE, HLS, MP4, MJPEG, HomeKit, FFmpeg, etc.
https://github.com/AlexxIT/Blog
MIT License
7.1k stars 509 forks source link

Implement Unifi Protect-complaint output #613

Open kiler129 opened 1 year ago

kiler129 commented 1 year ago

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 :)

AlexxIT commented 1 year ago

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 commented 6 months ago

Please let me know if the problem is relevant

simone-desantis commented 6 months ago

I would have loved to see this feature!

AlexxIT commented 6 months ago

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

ViViDboarder commented 4 weeks ago

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

acortelyou commented 1 week ago

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.