diff --git a/internal/webrtc/client.go b/internal/webrtc/client.go index 9f21f4e9..106b603e 100644 --- a/internal/webrtc/client.go +++ b/internal/webrtc/client.go @@ -41,7 +41,7 @@ func streamsHandler(rawURL string) (core.Producer, error) { // https://aws.amazon.com/kinesis/video-streams/ // https://docs.aws.amazon.com/kinesisvideostreams-webrtc-dg/latest/devguide/what-is-kvswebrtc.html // https://github.com/orgs/awslabs/repositories?q=kinesis+webrtc - return kinesisClient(rawURL, query, "webrtc/kinesis", &kinesisClientOpts{}) + return kinesisClient(rawURL, query, "webrtc/kinesis", nil) } else if format == "openipc" { return openIPCClient(rawURL, query) } else if format == "switchbot" { diff --git a/internal/webrtc/kinesis.go b/internal/webrtc/kinesis.go index 42f76dce..b11d1d31 100644 --- a/internal/webrtc/kinesis.go +++ b/internal/webrtc/kinesis.go @@ -34,12 +34,10 @@ func (k kinesisResponse) String() string { return fmt.Sprintf("type=%s, payload=%s", k.Type, k.Payload) } -type kinesisClientOpts struct { - SessionDescriptionModifier func(*pion.SessionDescription) ([]byte, error) - MediaModifier func() ([]*core.Media, error) -} - -func kinesisClient(rawURL string, query url.Values, format string, opts *kinesisClientOpts) (core.Producer, error) { +func kinesisClient( + rawURL string, query url.Values, format string, + sdpOffer func(prod *webrtc.Conn, query url.Values) (any, error), +) (core.Producer, error) { // 1. Connect to signalign server conn, _, err := websocket.DefaultDialer.Dial(rawURL, nil) if err != nil { @@ -113,34 +111,33 @@ func kinesisClient(rawURL string, query url.Values, format string, opts *kinesis } }) - medias := []*core.Media{ - {Kind: core.KindVideo, Direction: core.DirectionRecvonly}, - {Kind: core.KindAudio, Direction: core.DirectionRecvonly}, - } - if opts.MediaModifier != nil { - medias, err = opts.MediaModifier() - if err != nil { + var payload any + + if sdpOffer == nil { + medias := []*core.Media{ + {Kind: core.KindVideo, Direction: core.DirectionRecvonly}, + {Kind: core.KindAudio, Direction: core.DirectionRecvonly}, + } + + // 4. Create offer + var offer string + if offer, err = prod.CreateOffer(medias); err != nil { + return nil, err + } + + // 5. Send offer + payload = pion.SessionDescription{ + Type: pion.SDPTypeOffer, + SDP: offer, + } + } else { + if payload, err = sdpOffer(prod, query); err != nil { return nil, err } } - // 4. Create offer - offer, err := prod.CreateOffer(medias) - if err != nil { - return nil, err - } - - // 5. Send offer req.Action = "SDP_OFFER" - sessionDescription := pion.SessionDescription{ - Type: pion.SDPTypeOffer, - SDP: offer, - } - if opts.SessionDescriptionModifier != nil { - req.Payload, _ = opts.SessionDescriptionModifier(&sessionDescription) - } else { - req.Payload, _ = json.Marshal(sessionDescription) - } + req.Payload, _ = json.Marshal(payload) if err = conn.WriteJSON(req); err != nil { return nil, err } @@ -234,5 +231,5 @@ func wyzeClient(rawURL string) (core.Producer, error) { "ice_servers": []string{string(kvs.Servers)}, } - return kinesisClient(kvs.URL, query, "webrtc/wyze", &kinesisClientOpts{}) + return kinesisClient(kvs.URL, query, "webrtc/wyze", nil) } diff --git a/internal/webrtc/switchbot.go b/internal/webrtc/switchbot.go index 09d0c5b1..5ece88ae 100644 --- a/internal/webrtc/switchbot.go +++ b/internal/webrtc/switchbot.go @@ -1,62 +1,40 @@ package webrtc import ( - "encoding/json" "net/url" - "strings" "github.com/AlexxIT/go2rtc/pkg/core" - pion "github.com/pion/webrtc/v3" + "github.com/AlexxIT/go2rtc/pkg/webrtc" ) -// SessionDescription is used to expose local and remote session descriptions. -type SwitchBotSessionDescription struct { - Type string `json:"type"` - SDP string `json:"sdp"` - Resolution SwitchBotResolution `json:"resolution"` - PlayType int `json:"play_type"` -} - func switchbotClient(rawURL string, query url.Values) (core.Producer, error) { - return kinesisClient(rawURL, query, "webrtc/switchbot", &kinesisClientOpts{ - SessionDescriptionModifier: func(sd *pion.SessionDescription) ([]byte, error) { - resolution, ok := parseSwitchBotResolution(query.Get("resolution")) - if !ok { - resolution = SwitchBotResolutionSD - } - json, err := json.Marshal(SwitchBotSessionDescription{ - Type: sd.Type.String(), - SDP: sd.SDP, - Resolution: resolution, - PlayType: 0, - }) - return json, err - }, - MediaModifier: func() ([]*core.Media, error) { - return []*core.Media{ - {Kind: core.KindVideo, Direction: core.DirectionRecvonly}, - //{Kind: core.KindAudio, Direction: core.DirectionRecvonly}, - //{Kind: core.KindAudio, Direction: core.DirectionSendRecv}, - //{Kind: "Data", Direction: core.DirectionSendRecv}, - }, nil - }, + return kinesisClient(rawURL, query, "webrtc/switchbot", func(prod *webrtc.Conn, query url.Values) (any, error) { + medias := []*core.Media{ + {Kind: core.KindVideo, Direction: core.DirectionRecvonly}, + } + + offer, err := prod.CreateOffer(medias) + if err != nil { + return nil, err + } + + v := struct { + Type string `json:"type"` + SDP string `json:"sdp"` + Resolution int `json:"resolution"` + PlayType int `json:"play_type"` + }{ + Type: "offer", + SDP: offer, + } + + switch query.Get("resolution") { + case "hd": + v.Resolution = 0 + case "sd": + v.Resolution = 1 + } + + return v, nil }) } - -type SwitchBotResolution int - -const ( - SwitchBotResolutionHD SwitchBotResolution = 0 - SwitchBotResolutionSD = 1 -) - -func parseSwitchBotResolution(str string) (SwitchBotResolution, bool) { - var ( - resolutionMap = map[string]SwitchBotResolution{ - "hd": SwitchBotResolutionHD, - "sd": SwitchBotResolutionSD, - } - ) - c, ok := resolutionMap[strings.ToLower(str)] - return c, ok -}