From f6416ca106447a045c190f58124b685708880f51 Mon Sep 17 00:00:00 2001 From: Maxim Date: Tue, 12 May 2026 09:42:13 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=B2=D0=B8=D0=B4=D0=B5?= =?UTF-8?q?=D0=BE=D0=BA=D0=B0=D0=BC=D0=B5=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/server/main.go | 19 ++++++++----------- scripts/go2rtc.yaml | 6 +++++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index f3b0a7e..14efac7 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -1,4 +1,3 @@ -// cmd/server/main.go package main import ( @@ -12,6 +11,7 @@ import ( "log" "net/http" "os" + "strings" "time" "gpio-monitor/internal/adapter" @@ -79,8 +79,8 @@ func (a *API) HandleHistory(w http.ResponseWriter, r *http.Request) { } func (a *API) HandleStream(w http.ResponseWriter, r *http.Request) { - // Проверяем доступность go2rtc - resp, err := http.Get("http://localhost:1984/api/streams?src=cam") + // Проверяем доступность MJPEG потока в go2rtc + resp, err := http.Get("http://localhost:1984/api/streams?src=cam_mjpeg") camAvailable := err == nil && resp.StatusCode == 200 if resp != nil { resp.Body.Close() @@ -89,17 +89,15 @@ func (a *API) HandleStream(w http.ResponseWriter, r *http.Request) { writeJSON(w, map[string]interface{}{ "cam": "/api/cam", "available": camAvailable, - "source": fmt.Sprintf("http://%s:1984/api/stream.mjpeg?src=cam", r.Host), + "source": fmt.Sprintf("http://%s:1984/api/stream.mjpeg?src=cam_mjpeg", strings.Split(r.Host, ":")[0]), }) } -// Прокси для MJPEG потока с go2rtc +// Прокси для MJPEG потока — просто ретранслирует готовый поток из go2rtc func handleCamProxy(w http.ResponseWriter, r *http.Request) { log.Printf("[cam] proxy request from %s", r.RemoteAddr) - resp, err := http.Get( - "http://127.0.0.1:1984/api/stream.mjpeg?src=cam", - ) + resp, err := http.Get("http://127.0.0.1:1984/api/stream.mjpeg?src=cam_mjpeg") if err != nil { log.Printf("[cam] go2rtc unavailable: %v", err) http.Error(w, "camera unavailable", 503) @@ -107,6 +105,7 @@ func handleCamProxy(w http.ResponseWriter, r *http.Request) { } defer resp.Body.Close() + // Прокидываем заголовки for k, vv := range resp.Header { for _, v := range vv { w.Header().Add(k, v) @@ -114,7 +113,6 @@ func handleCamProxy(w http.ResponseWriter, r *http.Request) { } w.Header().Set("Access-Control-Allow-Origin", "*") - w.WriteHeader(resp.StatusCode) flusher, ok := w.(http.Flusher) @@ -134,7 +132,6 @@ func handleCamProxy(w http.ResponseWriter, r *http.Request) { log.Printf("[cam] client disconnected") return } - flusher.Flush() } @@ -243,4 +240,4 @@ func main() { log.Println("Server started on :8080") log.Println("Camera proxy available at /api/cam") log.Fatal(http.ListenAndServe(":8080", nil)) -} +} \ No newline at end of file diff --git a/scripts/go2rtc.yaml b/scripts/go2rtc.yaml index dfe6735..0407f2d 100644 --- a/scripts/go2rtc.yaml +++ b/scripts/go2rtc.yaml @@ -1,6 +1,10 @@ streams: + # Основной поток для WebRTC (быстрый, минимальная задержка) cam: - - exec:ffmpeg -f v4l2 -input_format mjpeg -video_size 640x480 -framerate 15 -i /dev/video0 -c:v copy -f mjpeg pipe:1 + - exec:ffmpeg -f v4l2 -input_format yuyv422 -video_size 640x480 -framerate 30 -i /dev/video0 -c:v libx264 -preset ultrafast -tune zerolatency -f rawvideo pipe:1 + # MJPEG поток для браузера (оптимизирован под теги img) + cam_mjpeg: + - exec:ffmpeg -f v4l2 -input_format yuyv422 -video_size 640x480 -framerate 15 -i /dev/video0 -c:v mjpeg -q:v 8 -f mpjpeg pipe:1 api: listen: ":1984"