fix(homekit): fix HKSV recording by correcting HDS protocol and adding 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
This commit is contained in:
Sergey Krashevich
2026-03-05 06:25:00 +03:00
parent 35fd1383c8
commit 1856b7ace4
6 changed files with 322 additions and 67 deletions
+26 -6
View File
@@ -45,10 +45,12 @@ type server struct {
stream string // stream name from YAML
// HKSV fields
motionMode string // "api", "continuous", "detect"
motionThreshold float64 // ratio threshold for "detect" mode (default 2.0)
motionDetector *motionDetector
hksvSession *hksvSession
motionMode string // "api", "continuous", "detect"
motionThreshold float64 // ratio threshold for "detect" mode (default 2.0)
motionDetector *motionDetector
hksvSession *hksvSession
continuousMotion bool
preparedConsumer *hksvConsumer
}
func (s *server) MarshalJSON() ([]byte, error) {
@@ -113,9 +115,13 @@ func (s *server) Handle(w http.ResponseWriter, r *http.Request) {
s.AddConn(controller)
defer s.DelConn(controller)
// start motion detector on first Home Hub connection
if s.motionMode == "detect" {
// start motion on first Home Hub connection
switch s.motionMode {
case "detect":
go s.startMotionDetector()
case "continuous":
go s.prepareHKSVConsumer()
go s.startContinuousMotion()
}
var handler homekit.HandlerFunc
@@ -510,7 +516,21 @@ func (s *server) stopMotionDetector() {
}
}
func (s *server) startContinuousMotion() {
s.mu.Lock()
if s.continuousMotion {
s.mu.Unlock()
return
}
s.continuousMotion = true
s.mu.Unlock()
log.Debug().Str("stream", s.stream).Msg("[homekit] continuous motion started")
// delay to allow Home Hub to subscribe to events
time.Sleep(5 * time.Second)
s.SetMotionDetected(true)
ticker := time.NewTicker(30 * time.Second)