install go2rtc on bob

This commit is contained in:
2026-04-04 19:36:14 +02:00
parent f0b56e63d1
commit ccf88187b8
537 changed files with 69213 additions and 0 deletions
@@ -0,0 +1,69 @@
package isapi
import (
"encoding/json"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/pion/rtp"
)
func (c *Client) GetMedias() []*core.Media {
return c.medias
}
func (c *Client) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {
return nil, core.ErrCantGetTrack
}
func (c *Client) AddTrack(media *core.Media, _ *core.Codec, track *core.Receiver) error {
if c.sender == nil {
c.sender = core.NewSender(media, track.Codec)
c.sender.Handler = func(packet *rtp.Packet) {
if c.conn == nil {
return
}
c.send += len(packet.Payload)
_, _ = c.conn.Write(packet.Payload)
}
}
c.sender.HandleRTP(track)
return nil
}
func (c *Client) Start() (err error) {
if err = c.Open(); err != nil {
return
}
return
}
func (c *Client) Stop() (err error) {
if c.sender != nil {
c.sender.Close()
}
if c.conn != nil {
_ = c.Close()
return c.conn.Close()
}
return nil
}
func (c *Client) MarshalJSON() ([]byte, error) {
info := &core.Connection{
ID: core.ID(c),
FormatName: "isapi",
Protocol: "http",
Medias: c.medias,
Send: c.send,
}
if c.conn != nil {
info.RemoteAddr = c.conn.RemoteAddr().String()
}
if c.sender != nil {
info.Senders = []*core.Sender{c.sender}
}
return json.Marshal(info)
}
+164
View File
@@ -0,0 +1,164 @@
package isapi
import (
"errors"
"io"
"net"
"net/http"
"net/url"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/tcp"
)
// Deprecated: should be rewritten to core.Connection
type Client struct {
core.Listener
url string
channel string
conn net.Conn
medias []*core.Media
sender *core.Sender
send int
}
func Dial(rawURL string) (*Client, error) {
// check if url is valid url
u, err := url.Parse(rawURL)
if err != nil {
return nil, err
}
u.Scheme = "http"
u.Path = ""
client := &Client{url: u.String()}
if err = client.Dial(); err != nil {
return nil, err
}
return client, err
}
func (c *Client) Dial() (err error) {
link := c.url + "/ISAPI/System/TwoWayAudio/channels"
req, err := http.NewRequest("GET", link, nil)
if err != nil {
return err
}
res, err := tcp.Do(req)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
tcp.Close(res)
return errors.New(res.Status)
}
b, err := io.ReadAll(res.Body)
if err != nil {
return err
}
xml := string(b)
codec := core.Between(xml, `<audioCompressionType>`, `<`)
switch codec {
case "G.711ulaw":
codec = core.CodecPCMU
case "G.711alaw":
codec = core.CodecPCMA
default:
return nil
}
c.channel = core.Between(xml, `<id>`, `<`)
media := &core.Media{
Kind: core.KindAudio,
Direction: core.DirectionSendonly,
Codecs: []*core.Codec{
{Name: codec, ClockRate: 8000},
},
}
c.medias = append(c.medias, media)
return nil
}
func (c *Client) Open() (err error) {
// Hikvision ISAPI may not accept a new open request if the previous one was not closed (e.g.
// using the test button on-camera or via curl command) but a close request can be sent even if
// the audio is already closed. So, we send a close request first and then open it again. Seems
// janky but it works.
if err = c.Close(); err != nil {
return err
}
link := c.url + "/ISAPI/System/TwoWayAudio/channels/" + c.channel
req, err := http.NewRequest("PUT", link+"/open", nil)
if err != nil {
return err
}
res, err := tcp.Do(req)
if err != nil {
return
}
tcp.Close(res)
ctx, pconn := tcp.WithConn()
req, err = http.NewRequestWithContext(ctx, "PUT", link+"/audioData", nil)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("Content-Length", "0")
res, err = tcp.Do(req)
if err != nil {
return err
}
c.conn = *pconn
// just block until c.conn closed
b := make([]byte, 1)
_, _ = c.conn.Read(b)
tcp.Close(res)
return nil
}
func (c *Client) Close() (err error) {
link := c.url + "/ISAPI/System/TwoWayAudio/channels/" + c.channel
req, err := http.NewRequest("PUT", link+"/close", nil)
if err != nil {
return err
}
res, err := tcp.Do(req)
if err != nil {
return err
}
tcp.Close(res)
return nil
}
//type XMLChannels struct {
// Channels []Channel `xml:"TwoWayAudioChannel"`
//}
//type Channel struct {
// ID string `xml:"id"`
// Enabled string `xml:"enabled"`
// Codec string `xml:"audioCompressionType"`
//}