From 493fa1ef6a1478e39c6a18f075c1434e43007242 Mon Sep 17 00:00:00 2001 From: seydx Date: Thu, 5 Jun 2025 11:33:03 +0300 Subject: [PATCH] add api endpoints and change config syntax --- internal/streams/api.go | 62 +++++++++++++++++++++++++++++++++++++ internal/streams/preload.go | 26 +++++++++------- internal/streams/streams.go | 11 ++++--- pkg/preload/producer.go | 6 ++-- 4 files changed, 85 insertions(+), 20 deletions(-) diff --git a/internal/streams/api.go b/internal/streams/api.go index 061e61c2..c0c6744b 100644 --- a/internal/streams/api.go +++ b/internal/streams/api.go @@ -122,3 +122,65 @@ func apiStreamsDOT(w http.ResponseWriter, r *http.Request) { api.Response(w, dot, "text/vnd.graphviz") } + +func apiPreload(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + src := query.Get("src") + query.Del("src") + + videoQuery := query.Get("video") + audioQuery := query.Get("audio") + micQuery := query.Get("microphone") + + if src == "" { + http.Error(w, "no source", http.StatusBadRequest) + return + } + + switch r.Method { + case "PUT": + // check if stream exists + if stream := Get(src); stream == nil { + http.Error(w, "stream not found", http.StatusNotFound) + return + } + + // check if consumer exists + if cons, ok := preloads[src]; ok { + cons.Stop() + delete(preloads, src) + } + + var rawQuery string + if videoQuery != "" { + rawQuery += "video=" + videoQuery + "#" + } + if audioQuery != "" { + rawQuery += "audio=" + audioQuery + "#" + } + if micQuery != "" { + rawQuery += "microphone=" + micQuery + } + + if err := app.PatchConfig([]string{"preload", src}, rawQuery); err != nil { + log.Error().Err(err).Str("src", src).Msg("Failed to patch config for PUT") + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + Preload(src, rawQuery) + + case "DELETE": + if cons, ok := preloads[src]; ok { + cons.Stop() + delete(preloads, src) + } + + if err := app.PatchConfig([]string{"preload", src}, nil); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + } + + default: + http.Error(w, "", http.StatusMethodNotAllowed) + } +} diff --git a/internal/streams/preload.go b/internal/streams/preload.go index c811cc5c..7314df55 100644 --- a/internal/streams/preload.go +++ b/internal/streams/preload.go @@ -2,13 +2,15 @@ package streams import ( "net/url" - "strings" "github.com/AlexxIT/go2rtc/pkg/preload" ) -func (s *Stream) Preload(query url.Values) error { - cons := preload.NewPreload(query) +var preloads = map[string]*preload.Preload{} + +func (s *Stream) Preload(name string, query url.Values) error { + cons := preload.NewPreload(name, query) + preloads[name] = cons if err := s.AddConsumer(cons); err != nil { return err @@ -17,14 +19,16 @@ func (s *Stream) Preload(query url.Values) error { return nil } -func Preload(src string) { - name, rawQuery, _ := strings.Cut(src, "#") - query := ParseQuery(rawQuery) - - if stream := Get(name); stream != nil { - if err := stream.Preload(query); err != nil { - log.Error().Err(err).Caller().Send() - } +func Preload(src string, rawQuery string) { + // skip if exists + if _, ok := preloads[src]; ok { return } + + if stream := Get(src); stream != nil { + query := ParseQuery(rawQuery) + if err := stream.Preload(src, query); err != nil { + log.Error().Err(err).Caller().Send() + } + } } diff --git a/internal/streams/streams.go b/internal/streams/streams.go index 7bbccace..8f07ea12 100644 --- a/internal/streams/streams.go +++ b/internal/streams/streams.go @@ -14,9 +14,9 @@ import ( func Init() { var cfg struct { - Streams map[string]any `yaml:"streams"` - Publish map[string]any `yaml:"publish"` - Preload []string `yaml:"preload"` + Streams map[string]any `yaml:"streams"` + Publish map[string]any `yaml:"publish"` + Preload map[string]string `yaml:"preload"` } app.LoadConfig(&cfg) @@ -29,6 +29,7 @@ func Init() { api.HandleFunc("api/streams", apiStreams) api.HandleFunc("api/streams.dot", apiStreamsDOT) + api.HandleFunc("api/preload", apiPreload) if cfg.Publish == nil && cfg.Preload == nil { return @@ -44,8 +45,8 @@ func Init() { } if cfg.Preload != nil { - for _, src := range cfg.Preload { - Preload(src) + for name, rawQuery := range cfg.Preload { + Preload(name, rawQuery) } } }) diff --git a/pkg/preload/producer.go b/pkg/preload/producer.go index 811cf2e4..05a50d52 100644 --- a/pkg/preload/producer.go +++ b/pkg/preload/producer.go @@ -9,11 +9,10 @@ import ( type Preload struct { core.Connection - Closed core.Waiter } -func NewPreload(query url.Values) *Preload { +func NewPreload(name string, query url.Values) *Preload { medias := core.ParseQuery(query) for _, value := range query["microphone"] { @@ -49,11 +48,10 @@ func NewPreload(query url.Values) *Preload { return &Preload{ Connection: core.Connection{ ID: core.NewID(), - FormatName: "preload", Medias: medias, Protocol: "native", RemoteAddr: "localhost", - UserAgent: "go2rtc", + UserAgent: "go2rtc/preload", }, } }