diff --git a/internal/api/api.go b/internal/api/api.go index a14cb28e..e21b9074 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -213,21 +213,23 @@ func exitHandler(w http.ResponseWriter, r *http.Request) { os.Exit(code) } -type Stream struct { - Name string `json:"name"` - URL string `json:"url"` +type Source struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + URL string `json:"url,omitempty"` + Location string `json:"location,omitempty"` } -func ResponseStreams(w http.ResponseWriter, streams []Stream) { - if len(streams) == 0 { - http.Error(w, "no streams", http.StatusNotFound) +func ResponseSources(w http.ResponseWriter, sources []Source) { + if len(sources) == 0 { + http.Error(w, "no sources", http.StatusNotFound) return } var response = struct { - Streams []Stream `json:"streams"` + Sources []Source `json:"sources"` }{ - Streams: streams, + Sources: sources, } ResponseJSON(w, response) } diff --git a/internal/dvrip/dvrip.go b/internal/dvrip/dvrip.go index 491958b4..e892b6e6 100644 --- a/internal/dvrip/dvrip.go +++ b/internal/dvrip/dvrip.go @@ -45,10 +45,10 @@ func apiDvrip(w http.ResponseWriter, r *http.Request) { return } - api.ResponseStreams(w, items) + api.ResponseSources(w, items) } -func discover() ([]api.Stream, error) { +func discover() ([]api.Source, error) { addr := &net.UDPAddr{ Port: Port, IP: net.IP{239, 255, 255, 250}, @@ -63,7 +63,7 @@ func discover() ([]api.Stream, error) { go sendBroadcasts(conn) - var items []api.Stream + var items []api.Source for _, info := range getResponses(conn) { if info.HostIP == "" || info.HostName == "" { @@ -75,7 +75,7 @@ func discover() ([]api.Stream, error) { continue } - items = append(items, api.Stream{ + items = append(items, api.Source{ Name: info.HostName, URL: "dvrip://user:pass@" + host + "?channel=0&subtype=0", }) diff --git a/internal/ffmpeg/device/device_darwin.go b/internal/ffmpeg/device/device_darwin.go index 0900cf0c..f707f6b0 100644 --- a/internal/ffmpeg/device/device_darwin.go +++ b/internal/ffmpeg/device/device_darwin.go @@ -1,12 +1,13 @@ package device import ( - "github.com/AlexxIT/go2rtc/internal/api" - "github.com/AlexxIT/go2rtc/pkg/core" "net/url" "os/exec" "regexp" "strings" + + "github.com/AlexxIT/go2rtc/internal/api" + "github.com/AlexxIT/go2rtc/pkg/core" ) func queryToInput(query url.Values) string { @@ -78,7 +79,7 @@ func initDevices() { audios = append(audios, name) } - streams = append(streams, api.Stream{ + streams = append(streams, api.Source{ Name: name, URL: "ffmpeg:device?" + kind + "=" + name, }) } diff --git a/internal/ffmpeg/device/device_linux.go b/internal/ffmpeg/device/device_linux.go index 962b5f47..3651cc33 100644 --- a/internal/ffmpeg/device/device_linux.go +++ b/internal/ffmpeg/device/device_linux.go @@ -70,7 +70,7 @@ func initDevices() { m := re.FindAllStringSubmatch(string(b), -1) for _, i := range m { size, _, _ := strings.Cut(i[4], " ") - stream := api.Stream{ + stream := api.Source{ Name: i[3] + " | " + i[4], URL: "ffmpeg:device?video=" + name + "&input_format=" + i[2] + "&video_size=" + size, } @@ -86,7 +86,7 @@ func initDevices() { err = exec.Command(Bin, "-f", "alsa", "-i", "default", "-t", "1", "-f", "null", "-").Run() if err == nil { - stream := api.Stream{ + stream := api.Source{ Name: "ALSA default", URL: "ffmpeg:device?audio=default&channels=1&sample_rate=16000audio=opus", } diff --git a/internal/ffmpeg/device/device_windows.go b/internal/ffmpeg/device/device_windows.go index b68c677b..ec25e657 100644 --- a/internal/ffmpeg/device/device_windows.go +++ b/internal/ffmpeg/device/device_windows.go @@ -1,11 +1,12 @@ package device import ( - "github.com/AlexxIT/go2rtc/internal/api" - "github.com/AlexxIT/go2rtc/pkg/core" "net/url" "os/exec" "regexp" + + "github.com/AlexxIT/go2rtc/internal/api" + "github.com/AlexxIT/go2rtc/pkg/core" ) func queryToInput(query url.Values) string { @@ -79,7 +80,7 @@ func initDevices() { name := m[1] kind := m[2] - stream := api.Stream{ + stream := api.Source{ Name: name, URL: "ffmpeg:device?" + kind + "=" + name, } diff --git a/internal/ffmpeg/device/devices.go b/internal/ffmpeg/device/devices.go index 4eaa6e87..2c0e2d91 100644 --- a/internal/ffmpeg/device/devices.go +++ b/internal/ffmpeg/device/devices.go @@ -2,12 +2,13 @@ package device import ( "errors" - "github.com/AlexxIT/go2rtc/internal/api" "net/http" "net/url" "strconv" "strings" "sync" + + "github.com/AlexxIT/go2rtc/internal/api" ) func Init(bin string) { @@ -39,13 +40,13 @@ func GetInput(src string) (string, error) { var Bin string var videos, audios []string -var streams []api.Stream +var streams []api.Source var runonce sync.Once func apiDevices(w http.ResponseWriter, r *http.Request) { runonce.Do(initDevices) - api.ResponseStreams(w, streams) + api.ResponseSources(w, streams) } func indexToItem(items []string, index string) string { diff --git a/internal/ffmpeg/hardware/hardware.go b/internal/ffmpeg/hardware/hardware.go index 2cc3b6d8..f18bded1 100644 --- a/internal/ffmpeg/hardware/hardware.go +++ b/internal/ffmpeg/hardware/hardware.go @@ -1,12 +1,13 @@ package hardware import ( - "github.com/AlexxIT/go2rtc/internal/api" - "github.com/AlexxIT/go2rtc/pkg/ffmpeg" "net/http" "os/exec" "strings" + "github.com/AlexxIT/go2rtc/internal/api" + "github.com/AlexxIT/go2rtc/pkg/ffmpeg" + "github.com/rs/zerolog/log" ) @@ -21,7 +22,7 @@ const ( func Init(bin string) { api.HandleFunc("api/ffmpeg/hardware", func(w http.ResponseWriter, r *http.Request) { - api.ResponseStreams(w, ProbeAll(bin)) + api.ResponseSources(w, ProbeAll(bin)) }) } diff --git a/internal/ffmpeg/hardware/hardware_darwin.go b/internal/ffmpeg/hardware/hardware_darwin.go index 4f59ca6a..82722a7a 100644 --- a/internal/ffmpeg/hardware/hardware_darwin.go +++ b/internal/ffmpeg/hardware/hardware_darwin.go @@ -7,8 +7,8 @@ import ( const ProbeVideoToolboxH264 = "-f lavfi -i testsrc2=size=svga -t 1 -c h264_videotoolbox -f null -" const ProbeVideoToolboxH265 = "-f lavfi -i testsrc2=size=svga -t 1 -c hevc_videotoolbox -f null -" -func ProbeAll(bin string) []api.Stream { - return []api.Stream{ +func ProbeAll(bin string) []api.Source { + return []api.Source{ { Name: runToString(bin, ProbeVideoToolboxH264), URL: "ffmpeg:...#video=h264#hardware=" + EngineVideoToolbox, diff --git a/internal/ffmpeg/hardware/hardware_linux.go b/internal/ffmpeg/hardware/hardware_linux.go index cacfb10e..3aa77862 100644 --- a/internal/ffmpeg/hardware/hardware_linux.go +++ b/internal/ffmpeg/hardware/hardware_linux.go @@ -1,8 +1,9 @@ package hardware import ( - "github.com/AlexxIT/go2rtc/internal/api" "runtime" + + "github.com/AlexxIT/go2rtc/internal/api" ) const ProbeV4L2M2MH264 = "-f lavfi -i testsrc2 -t 1 -c h264_v4l2m2m -f null -" @@ -13,9 +14,9 @@ const ProbeVAAPIJPEG = "-init_hw_device vaapi -f lavfi -i testsrc2 -t 1 -vf form const ProbeCUDAH264 = "-init_hw_device cuda -f lavfi -i testsrc2 -t 1 -c h264_nvenc -f null -" const ProbeCUDAH265 = "-init_hw_device cuda -f lavfi -i testsrc2 -t 1 -c hevc_nvenc -f null -" -func ProbeAll(bin string) []api.Stream { +func ProbeAll(bin string) []api.Source { if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" { - return []api.Stream{ + return []api.Source{ { Name: runToString(bin, ProbeV4L2M2MH264), URL: "ffmpeg:...#video=h264#hardware=" + EngineV4L2M2M, @@ -27,7 +28,7 @@ func ProbeAll(bin string) []api.Stream { } } - return []api.Stream{ + return []api.Source{ { Name: runToString(bin, ProbeVAAPIH264), URL: "ffmpeg:...#video=h264#hardware=" + EngineVAAPI, diff --git a/internal/ffmpeg/hardware/hardware_windows.go b/internal/ffmpeg/hardware/hardware_windows.go index 6a8898f2..1d95cabe 100644 --- a/internal/ffmpeg/hardware/hardware_windows.go +++ b/internal/ffmpeg/hardware/hardware_windows.go @@ -8,8 +8,8 @@ const ProbeDXVA2JPEG = "-init_hw_device dxva2 -f lavfi -i testsrc2 -t 1 -c mjpeg const ProbeCUDAH264 = "-init_hw_device cuda -f lavfi -i testsrc2 -t 1 -c h264_nvenc -f null -" const ProbeCUDAH265 = "-init_hw_device cuda -f lavfi -i testsrc2 -t 1 -c hevc_nvenc -f null -" -func ProbeAll(bin string) []api.Stream { - return []api.Stream{ +func ProbeAll(bin string) []api.Source { + return []api.Source{ { Name: runToString(bin, ProbeDXVA2H264), URL: "ffmpeg:...#video=h264#hardware=" + EngineDXVA2, diff --git a/internal/hass/hass.go b/internal/hass/hass.go index bea80370..ccf38939 100644 --- a/internal/hass/hass.go +++ b/internal/hass/hass.go @@ -72,11 +72,13 @@ func Init() { } }) - var items []api.Stream + var items []api.Source for name, url := range entities { - items = append(items, api.Stream{Name: name, URL: url}) + items = append(items, api.Source{ + Name: name, URL: "hass:" + name, Location: url, + }) } - api.ResponseStreams(w, items) + api.ResponseSources(w, items) }) // for Addon listen on hassio interface, so WebUI feature will work diff --git a/internal/nest/init.go b/internal/nest/init.go index e48224fb..a7087701 100644 --- a/internal/nest/init.go +++ b/internal/nest/init.go @@ -1,11 +1,12 @@ package nest import ( + "net/http" + "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/streams" "github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/nest" - "net/http" ) func Init() { @@ -41,15 +42,15 @@ func apiNest(w http.ResponseWriter, r *http.Request) { return } - var items []api.Stream + var items []api.Source for name, deviceID := range devices { query.Set("device_id", deviceID) - items = append(items, api.Stream{ + items = append(items, api.Source{ Name: name, URL: "nest:?" + query.Encode(), }) } - api.ResponseStreams(w, items) + api.ResponseSources(w, items) } diff --git a/internal/onvif/init.go b/internal/onvif/init.go index 01b33702..7eb1a976 100644 --- a/internal/onvif/init.go +++ b/internal/onvif/init.go @@ -1,13 +1,6 @@ package onvif import ( - "github.com/AlexxIT/go2rtc/internal/api" - "github.com/AlexxIT/go2rtc/internal/app" - "github.com/AlexxIT/go2rtc/internal/rtsp" - "github.com/AlexxIT/go2rtc/internal/streams" - "github.com/AlexxIT/go2rtc/pkg/core" - "github.com/AlexxIT/go2rtc/pkg/onvif" - "github.com/rs/zerolog" "io" "net" "net/http" @@ -15,6 +8,14 @@ import ( "os" "strconv" "time" + + "github.com/AlexxIT/go2rtc/internal/api" + "github.com/AlexxIT/go2rtc/internal/app" + "github.com/AlexxIT/go2rtc/internal/rtsp" + "github.com/AlexxIT/go2rtc/internal/streams" + "github.com/AlexxIT/go2rtc/pkg/core" + "github.com/AlexxIT/go2rtc/pkg/onvif" + "github.com/rs/zerolog" ) func Init() { @@ -121,7 +122,7 @@ func onvifDeviceService(w http.ResponseWriter, r *http.Request) { func apiOnvif(w http.ResponseWriter, r *http.Request) { src := r.URL.Query().Get("src") - var items []api.Stream + var items []api.Source if src == "" { urls, err := onvif.DiscoveryStreamingURLs() @@ -149,7 +150,7 @@ func apiOnvif(w http.ResponseWriter, r *http.Request) { u.Path = "" } - items = append(items, api.Stream{Name: u.Host, URL: u.String()}) + items = append(items, api.Source{Name: u.Host, URL: u.String()}) } } else { client, err := onvif.NewClient(src) @@ -176,19 +177,19 @@ func apiOnvif(w http.ResponseWriter, r *http.Request) { } for i, token := range tokens { - items = append(items, api.Stream{ + items = append(items, api.Source{ Name: name + " stream" + strconv.Itoa(i), URL: src + "?subtype=" + token, }) } if len(tokens) > 0 && client.HasSnapshots() { - items = append(items, api.Stream{ + items = append(items, api.Source{ Name: name + " snapshot", URL: src + "?subtype=" + tokens[0] + "&snapshot", }) } } - api.ResponseStreams(w, items) + api.ResponseSources(w, items) } diff --git a/internal/roborock/roborock.go b/internal/roborock/roborock.go index e99586d9..537ea2cd 100644 --- a/internal/roborock/roborock.go +++ b/internal/roborock/roborock.go @@ -2,11 +2,12 @@ package roborock import ( "fmt" + "net/http" + "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/streams" "github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/roborock" - "net/http" ) func Init() { @@ -84,7 +85,7 @@ func apiHandle(w http.ResponseWriter, r *http.Request) { return } - var items []api.Stream + var items []api.Source for _, device := range devices { source := fmt.Sprintf( @@ -93,8 +94,8 @@ func apiHandle(w http.ResponseWriter, r *http.Request) { Auth.UserData.IoT.User, Auth.UserData.IoT.Pass, Auth.UserData.IoT.Domain, device.DID, device.Key, ) - items = append(items, api.Stream{Name: device.Name, URL: source}) + items = append(items, api.Source{Name: device.Name, URL: source}) } - api.ResponseStreams(w, items) + api.ResponseSources(w, items) } diff --git a/internal/webtorrent/init.go b/internal/webtorrent/init.go index 083bf50b..dcb0169d 100644 --- a/internal/webtorrent/init.go +++ b/internal/webtorrent/init.go @@ -3,6 +3,9 @@ package webtorrent import ( "errors" "fmt" + "net/http" + "net/url" + "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/app" "github.com/AlexxIT/go2rtc/internal/streams" @@ -10,8 +13,6 @@ import ( "github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/webtorrent" "github.com/rs/zerolog" - "net/http" - "net/url" ) func Init() { @@ -110,13 +111,13 @@ func apiHandle(w http.ResponseWriter, r *http.Request) { } } else { // response all shares - var items []api.Stream + var items []api.Source for src, share := range shares { pwd := srv.GetSharePwd(share) source := fmt.Sprintf("webtorrent:?share=%s&pwd=%s", share, pwd) - items = append(items, api.Stream{Name: src, URL: source}) + items = append(items, api.Source{ID: src, URL: source}) } - api.ResponseStreams(w, items) + api.ResponseSources(w, items) } case "POST": diff --git a/www/add.html b/www/add.html index 339f299b..7648eed3 100644 --- a/www/add.html +++ b/www/add.html @@ -59,7 +59,7 @@
@@ -179,7 +184,7 @@ @@ -192,7 +197,7 @@ @@ -205,7 +210,7 @@ @@ -234,7 +239,7 @@ const url = new URL('api/nest?' + query.toString(), location.href); const r = await fetch(url, {cache: 'no-cache'}); - await getStreams(r, 'nest-table'); + await getSources(r, 'nest-table'); }); @@ -246,7 +251,7 @@ @@ -262,7 +267,7 @@ @@ -289,13 +294,13 @@ @@ -307,7 +312,7 @@