demo live stream

This commit is contained in:
2026-04-23 23:49:10 +01:00
parent bee7869af4
commit 285533c13e
9 changed files with 837 additions and 16 deletions

View File

@@ -1,11 +1,22 @@
package main
import (
"context"
"errors"
"io"
"net/http"
"github.com/gorilla/websocket"
"github.com/pocketbase/pocketbase/core"
)
var liveWSUpgrader = websocket.Upgrader{
CheckOrigin: func(_ *http.Request) bool {
return true
},
}
func registerAPI(se *core.ServeEvent) {
group := se.Router.Group("/api/cctv")
@@ -31,11 +42,73 @@ func registerAPI(se *core.ServeEvent) {
})
group.GET("/live/{streamId}", func(e *core.RequestEvent) error {
return e.BadRequestError("Use /api/cctv/live/ws/{streamId} for live streaming", nil)
})
group.GET("/live/ws/{streamId}", func(e *core.RequestEvent) error {
streamId := e.Request.PathValue("streamId")
if streamId == "" {
return e.BadRequestError("Missing stream ID", nil)
}
ingestService.SubscribeLive(e.Request.Context(), streamId)
return nil
conn, err := liveWSUpgrader.Upgrade(e.Response, e.Request, nil)
if err != nil {
return e.InternalServerError("Failed to upgrade websocket connection", err)
}
defer conn.Close()
ctx, cancel := context.WithCancel(e.Request.Context())
defer cancel()
stream, err := ingestService.SubscribeLive(ctx, streamId)
if err != nil {
writeLiveWSError(conn, err.Error())
return nil
}
clientDone := make(chan struct{})
go func() {
defer close(clientDone)
for {
if _, _, err := conn.ReadMessage(); err != nil {
return
}
}
}()
for {
select {
case <-ctx.Done():
return nil
case <-clientDone:
return nil
case chunk, ok := <-stream:
if !ok {
writeLiveWSError(conn, "live stream ended")
return nil
}
if chunk == nil {
continue
}
payload, err := io.ReadAll(chunk)
if err != nil {
writeLiveWSError(conn, "failed to read stream chunk")
return nil
}
if err := conn.WriteMessage(websocket.BinaryMessage, payload); err != nil {
if errors.Is(err, websocket.ErrCloseSent) {
return nil
}
return nil
}
}
}
})
}
func writeLiveWSError(conn *websocket.Conn, msg string) {
payload := make([]byte, len(msg)+1)
payload[0] = 0x03
copy(payload[1:], []byte(msg))
_ = conn.WriteMessage(websocket.BinaryMessage, payload)
}