Repository navigation
HomeKit Secure Video - #2130
HomeKit Secure Video #2130skrashevich wants to merge 16 commits into
Conversation
…nctionality - Introduced HKSV configuration options in homekit.go, allowing for motion detection and doorbell features. - Implemented API endpoints for triggering motion detection and doorbell events. - Enhanced server.go to handle HKSV sessions and manage motion detection states. - Created new accessory types for HKSV and doorbell in accessory.go. - Added support for audio recording configurations in ch207.go. - Defined new services for motion detection and doorbell in services_hksv.go. - Implemented opack encoding/decoding for HDS protocol in opack.go and protocol.go. - Updated OpenAPI documentation to reflect new endpoints and features. - Extended schema.json to include HKSV configuration options.
… and add motion detector functionality
…g GOP buffering The HKSV recording was failing because: 1. The dataSend.data message structure was wrong - `packets` was a flat integer instead of an array of objects with `data` and `metadata` fields matching the HAP-NodeJS specification 2. Each video/audio frame was sent as a separate mediaFragment, but Home Hub expects GOP-based fragments (~2-4 seconds of accumulated data) 3. Large fragments were not chunked (max 256 KiB per chunk) Changes: - Fix HDS dataSend.data message structure to use proper packets array with nested data/metadata (dataType, dataSequenceNumber, dataChunkSequenceNumber, isLastDataChunk, dataTotalSize) - Add 256 KiB chunking for large media fragments - Buffer moof+mdat pairs in hksvConsumer and flush on keyframe boundaries (GOP-based fragmentation) - Pre-start consumer at pair-verify for instant init segment delivery - Add write-response support to HAP PUT handler for ch131 DataStream setup - Fix HAP service linking to match HAP-NodeJS reference - Add default SelectedCameraRecordingConfiguration (ch209) value - Start continuous motion generator at pair-verify with dedup protection
|
It's not ready to merge yet, but it is already fully functional and ready for testing by any user |
…sumer HDS protocol tests (15 tests, 4 benchmarks): - Message structure for SendMediaInit and SendMediaFragment - Multi-chunk splitting for fragments > 256KB - Chunk boundary handling and sequence preservation - WriteEvent/WriteResponse/WriteRequest round-trip - opack helper functions HKSV consumer tests (14 tests, 3 benchmarks): - Consumer creation and field initialization - GOP buffer flush with sequence numbering - Activate with init segment and seqNum=2 - Activate timeout and error handling - Stop safety (double-stop, deactivation) - WriteTo blocking until Stop Also fixes broken hds_test.go (undefined Client → NewConn).
Replace time.Now() calls in hot path with frame-based timing: - Pre-compute triggerLevel (integer comparison instead of float division) - Calibrate hold/cooldown budgets from FPS (default 30fps) - Periodic FPS recalibration every 150 frames for accuracy - Active motion path: 47ns → 3.6ns (13x faster) Update schema.json with detect mode and motion_threshold. Add threshold tuning guide to README.
|
I’m going to jump on trying this right away. I’ve been hoping for this for a while!! |
- Implemented MotionDetector for detecting motion based on H.264 P-frame sizes. - Introduced adjustable sensitivity threshold for motion detection. - Added tests for various scenarios including motion detection, hold time, cooldown, and baseline adaptation. - Created hksvSession to manage HDS DataStream connections for HKSV recording. - Updated schema.json to include a new speaker option for 2-way audio support.
|
@skrashevich first initial attempt for this was partially successful. I was able to add the camera and the hksv settings were enabled in the home app settings (when/what to record). I set it up to record all motion but it seems that part was not working. No recordings were ever triggered. I am using the basic “continuous” motion config, have not tried to get the motion api hooked up yet. |
Try to update to the latest version of this PR It’s a known bug, I hope i fixed it in c567831 |
Will try this afternoon if possible! Thanks |
In any case, try to re-pair the camera in HomeKit. |
|
Worked with the latest commit! I currently use the same cameras via scrypted for this use case. So I can easily do a side by side on functionality. Great work so far, this is a game changer in my opinion. When this is stable, I can’t wait to try to integrate it directly into thingino on camera (thingino optionally supports go2rtc) |
Although my motion detector implementation is very "cheap" in terms of CPU, I'm not sure if the camera's processor can handle it |
With motion set to continuous is it needed? |
No. Continuous is an emulation of a motion sensor that just reports motion event every 30 seconds. |
seems like two way audio is broken now though. the talk button has disappeared. (cam in go2rtc via onvif) |
homekit:
camera1:
hksv: true
speaker: true # RTFM ! |
|
Very nice! Do ONVIF motion events trigger the motion for HKSV or do we need a third party program to hit that API? |
Currently -- no. I don't have cameras with ONVIF motion detector for such development and testing. |
|
@jaysoffian thanks for confirming that I'm curious if anyone has actually confirmed if 2way works. Not just confirm that the Talk button is there but actually confirm that sound comes out of the speaker. It's a doorbell so 2way is kind of important for this one. I'd love to ditch the Reolink app and use pure HKSV for the doorbell. |
|
@noelhibbard Thanks for the info on the flv stream. Scrypted works really well with the Reolink Doorbell (including two-way audio with HK), so I continue to use it for that, and use go2rtc for my other cameras. You can point go2rtc at Scrypted's rebroadcast link if you want to get the Reolink into go2rtc. Just offering that as an option in case you haven't explored it. |
|
This is a really exciting enhancement, however I havent been able to get two way audio working either, I get the button but no sound comes through to camera - works fine in frigate however. |
|
Managed to get 2-way audio working in #2259 |
|
I installed the latest version (dev), but the camera still isn't recording in Homekit. Here's my Homekit config: |
|
undefined error=read tcp 192.168.1.240:1984->192.168.1.137:54495: read: connection reset by peer stream=domonap_11 caller=github.com/AlexxIT/go2rtc/pkg/hksv/hksv.go:346 |
|
With ‘motion: continuous’ recording works? |
It doesn't work in any mode, maybe my camera doesn't allow me to do it |
|
Show the entire go2rtc config (don't forget to delete the passwords) Are you sure you have an active iCloud subscription that allows you to record from cameras, and their number is not exceeded? |
streams: |
|
Icloud+ 2tb, only 4 cameras |
|
|
|
16:45:11.348 ERR [hksv] motion detector add consumer failed error="streams: failed to unmarshal SDP: sdp: syntax error at pos 1: "0", exec/rtsp\n[in#0 @ 0x7f8c220360] method DESCRIBE failed: 404 (Not Found)\n[in#0 @ 0x7f8c19a520] Error opening input: Server returned 404 Not Found\nError opening input file rtsp://127.0.0.1:8554/domonap_entrance?video&audio&source=ffmpeg:domonap_entrance%23video%3Dh264%23audio%3Daac%23audio%3Dopus.\nError opening input files: Server returned 404 Not Found\n" stream=domonap_entrance |
|
Independent validation report, in case it is useful for moving this along. Built and exercised this branch on hardware unrelated to the author's setup, and it works end to end. Environment
ResultsPairing, live view, and HKSV recording all worked. Recording is passthrough — no transcode:
Fragments once per second at ~67 KB (≈536 kbps), sequential, with an Two things worth noting for anyone else reproducing it: HomeKit negotiated 1280x720@30 against the 1080p10 source and accepted the mismatch without transcoding; and running on the host rather than in Docker made the mDNS advertisement work alongside the system's existing Bonjour responder without any Two small findings1. if cfg.Pin == "" {
cfg.Pin = "27041991"
}That is the same value used throughout Suggestion: generate a random pin on first run and persist it like the other pairing fields, or log a warning when falling back. 2. Benign on an aborted Neither blocks anything. Thanks for the work on this — the standalone |
|
Follow-up to my validation above. This has been running in production for several days now across three more cameras, and one real defect turned up. I have a fix for it if you want it. HAP is served on the API port, but the auth middleware doesn't exempt it local_auth isn't the deciding factor here, which is easy to get wrong when debugging. An iPhone is never on loopback, so the LAN path is blocked either way. The hard part is that nothing looks broken until the very end. The accessory registers, advertises over mDNS, and hands back a valid setup code. Then the Home app just can't add it, and nothing in the logs points at auth. The obvious workaround isn't a good one either. Turning off API auth leaves the snapshot and stream API open to everything on the LAN, on a security camera, and it breaks any healthcheck that asserts a 401. Fix pair-setup is guarded by the setup PIN via SRP Two other things from production use One trap for anyone tuning this: motion: status is logged at TRC and samples 1 frame in 150, so it shows the noise floor and never the spikes that actually fire. motion: ON is DBG. So log: { homekit: debug } is the level you want when tuning. trace just floods. |
|
@dppeak , in your testing, did you happen to test two way audio? That part seams to be broken. |
No. The three cameras I have (two are the same model) report no audio capability at all. Alarm.com returns SupportsDownstreamAudio, SupportsUpstreamAudio and SupportsFullDuplex as false for all three, so there was nothing for me to test. |
|
Running this in production across 9 cameras (mixed brands) with HKSV Confirms #2301 (wrong AAC codec enum, stray Also needed #2438's fixes: TLV8 separator, TLV8 truncating past 255 Two more things:
Worth flagging for anyone else testing: with Branch is up at https://github.com/Mo3he/go2rtc/tree/hksv if useful. |
PREPARED, NOT DEPLOYED. This is on a branch so main keeps building the current working image; nothing changes until this merges and the NAS is rebuilt. The branch is our previous pin plus 25 commits and zero behind, so nothing is given up. Verified locally against this exact SHA: builds clean, go vet clean, HKSV and HAP suites pass, and a package-level diff of the full suite against 506cfa7 shows zero regressions and two packages fixed. Those two matter because they fail on the commit being replaced. pkg/hap/tlv8 emits the separator between repeated tags as 0xff where it must be 0x00, and pkg/hap/camera covers the advertised HKSV recording configuration. 506cfa7 shipped both tests already failing, so we have been running with them red. patches/go2rtc-hap-auth-exempt.patch is deleted rather than kept, because the exemption is now in the pinned source. Mo3he implemented it in 6f76ea9a from our report on AlexxIT/go2rtc#2130, and did it better: the two pairing paths are registered through a new api.HandleFuncNoAuth using hap.PathPairSetup and PathPairVerify constants, instead of hardcoding the strings in the middleware. The reasoning stays in INVARIANTS.md and in a Dockerfile comment, so nobody re-adds a patch or tidies the exemption away upstream. Recorded in SECURITY_AUDIT.md as a supply-chain change, because the maintainer changed. Also noted there that not all 25 commits are HKSV work: one is a merge from upstream master carrying unrelated changes. Re-checked at the new SHA rather than assumed: go.mod still requires go 1.24.0 so the toolchain digest pin is unchanged, and main.go is still the module-root build target with no ./cmd/go2rtc. NOT verified: the docker build itself. The daemon is not running on this Mac, and an arm64 build would not prove the linux/amd64 NAS build anyway. The Go build was verified natively with the exact command the Dockerfile runs.
|
Thanks for this, and for the auth fix. I reported that one and you implemented it better than my patch did: registering the paths through Some independent verification, in case it is useful for deciding what to do with #2130. I compared your The part worth flagging: I ran the full suite on both commits and diffed the failing package lists. Zero packages pass on
Both fail on The other eight failing packages are identical on both commits, so they look environmental or pre-existing rather than anything you introduced. On the running side, this is early: I rebuilt today. Pairings survived the swap with no re-pair needed, and the accessory that is currently online is streaming and recording normally. Two of my three cameras are off the network at the moment for reasons unrelated to any of this, so I cannot claim three-camera validation today. Is the plan to fold these fixes into #2130, or would they land better as separate PRs against it? Happy to help test either way. My interest is straightforward: I would like to stop building a pinned fork. |
|
Been going back and forth on this, but the fixes belong here rather |
|
Forgive me but how does this pull differ from #2343 and vice versa? |
|
They're implementing two different Apple specs, so they aren't really competing versions of the same thing. #2130 does HKSV the way it has worked since it shipped: live view over classic SRTP RTP, and recordings muxed to fMP4 and sent to the home hub over HDS (HomeKit Data Stream). That's what #2343 implements the newer HomeKit Secure Video Open Source Compatibility Guide (Developer Preview, capabilities 17.99). Live view moves to WebRTC negotiated over HAP, and recording becomes CMAF segments POSTed to a publishing point the controller hands you, over mTLS with a client cert you CSR for. Hence The practical difference today is maturity. #2130 has been open since March and I've had three cameras paired against a fork of it and watched HKSV clips land in iCloud from all three, so that path is proven end to end. #2343's own test plan still has all four on-device boxes unchecked, and it depends on Apple accepting the accessory and providing a live publishing point. They do both touch |
That's really interesting thank you for explaining it. #2130 seems like the one for me to test now - just wiping 5 x MotionEye installs and then I'll see what happens with this branch. |
I tested your fork and talk back is working perfect but it doesn't include the HKSV changes add in #2130. It would be great if your fixes made it into #2130. Edit: I rolled both of Mo3he's PRs and your PR into one build and it's working well. |



Summary
Add HomeKit Secure Video (HKSV) support — go2rtc can now expose any camera as an HKSV-compatible device for Apple Home, recording video clips to iCloud when motion is detected.
Key features
continuous— always report motion, Home Hub decides what to recorddetect— automatic P-frame size analysis using EMA baseline (no CPU-heavy decoding needed)api— external trigger via HTTP API (for Frigate, ONVIF events, etc.)category_id: doorbellwith ring event APIpkg/hksv/has zerointernal/imports, can be used in any Go projectNew packages
pkg/hksv/pkg/hap/hds/pkg/hap/camera/services_hksv.go,ch207.go)New API endpoints
POST /api/homekit/motion?id=— trigger motion detectionDELETE /api/homekit/motion?id=— clear motion detectionPOST /api/homekit/doorbell?id=— trigger doorbell ring eventConfiguration
Binary size impact