From 593dce6eb9b587de98386af5ed5a86e6f59362d5 Mon Sep 17 00:00:00 2001 From: Sergey Krashevich Date: Fri, 6 Mar 2026 09:07:26 +0300 Subject: [PATCH] feat(homekit): add Speaker service and enhance Consumer with backtrack audio handling --- pkg/hap/camera/accessory.go | 17 +++++++++++++++++ pkg/homekit/consumer.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/pkg/hap/camera/accessory.go b/pkg/hap/camera/accessory.go index da03d522..3925052e 100644 --- a/pkg/hap/camera/accessory.go +++ b/pkg/hap/camera/accessory.go @@ -13,6 +13,7 @@ func NewAccessory(manuf, model, name, serial, firmware string) *hap.Accessory { ServiceCameraRTPStreamManagement(), //hap.ServiceHAPProtocolInformation(), ServiceMicrophone(), + ServiceSpeaker(), }, } acc.InitIID() @@ -32,6 +33,7 @@ func NewHKSVAccessory(manuf, model, name, serial, firmware string) *hap.Accessor hap.ServiceAccessoryInformation(manuf, model, name, serial, firmware), rtpStream, ServiceMicrophone(), + ServiceSpeaker(), motionSensor, operatingMode, recordingMgmt, @@ -60,6 +62,7 @@ func NewHKSVDoorbellAccessory(manuf, model, name, serial, firmware string) *hap. hap.ServiceAccessoryInformation(manuf, model, name, serial, firmware), rtpStream, ServiceMicrophone(), + ServiceSpeaker(), motionSensor, operatingMode, recordingMgmt, @@ -75,6 +78,20 @@ func NewHKSVDoorbellAccessory(manuf, model, name, serial, firmware string) *hap. return acc } +func ServiceSpeaker() *hap.Service { + return &hap.Service{ + Type: "113", // 'Speaker' + Characters: []*hap.Character{ + { + Type: "11A", + Format: hap.FormatBool, + Value: 0, + Perms: hap.EVPRPW, + }, + }, + } +} + func ServiceMicrophone() *hap.Service { return &hap.Service{ Type: "112", // 'Microphone' diff --git a/pkg/homekit/consumer.go b/pkg/homekit/consumer.go index c1be7447..784d192e 100644 --- a/pkg/homekit/consumer.go +++ b/pkg/homekit/consumer.go @@ -26,6 +26,8 @@ type Consumer struct { videoSession *srtp.Session audioSession *srtp.Session audioRTPTime byte + + backTrack *core.Receiver // backchannel audio (HomeKit viewer → camera) } func NewConsumer(conn net.Conn, server *srtp.Server) *Consumer { @@ -44,6 +46,13 @@ func NewConsumer(conn net.Conn, server *srtp.Server) *Consumer { {Name: core.CodecOpus}, }, }, + { + Kind: core.KindAudio, + Direction: core.DirectionRecvonly, + Codecs: []*core.Codec{ + {Name: core.CodecOpus}, + }, + }, } return &Consumer{ Connection: core.Connection{ @@ -130,6 +139,26 @@ func (c *Consumer) SetConfig(conf *camera.SelectedStreamConfiguration) bool { return true } +func (c *Consumer) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) { + if codec.Kind() != core.KindAudio { + return nil, core.ErrCantGetTrack + } + + c.backTrack = core.NewReceiver(media, codec) + + c.audioSession.OnReadRTP = func(packet *rtp.Packet) { + c.backTrack.WriteRTP(packet) + c.Recv += len(packet.Payload) + } + + c.Receivers = append(c.Receivers, c.backTrack) + return c.backTrack, nil +} + +func (c *Consumer) Start() error { + return nil +} + func (c *Consumer) AddTrack(media *core.Media, codec *core.Codec, track *core.Receiver) error { var session *srtp.Session if codec.Kind() == core.KindVideo {