Add ability to restart broadcast

This commit is contained in:
John Nguyen 2023-05-21 15:43:08 +10:00
parent a5830dc440
commit acc3c286a1
10 changed files with 60 additions and 27 deletions

View file

@ -1,4 +1,4 @@
ARG BASE_IMAGE=m1k1o/neko:base
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest
FROM $BASE_IMAGE
ARG SRC_URL="https://download.mozilla.org/?product=firefox-latest&os=linux64&lang=en-US"

View file

@ -33,13 +33,6 @@ RUN go mod download
COPY server/ .
RUN ./build
FROM ghcr.io/m1k1o/neko/intel-firefox:latest
RUN set -eux; apt-get update; \
apt-get install -y --no-install-recommends intel-media-va-driver-non-free i965-va-driver-shaders; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
FROM cave-firefox:latest
COPY --from=server /src/bin/neko /usr/bin/neko

View file

@ -10,10 +10,16 @@ services:
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./bin/firefox:/home/neko/.mozilla/firefox
- ./bin/home/neko:/home/neko
devices:
- /dev/dri/renderD128:/dev/dri/renderD128
- /dev/dri/card0:/dev/dri/card0
- /dev/dri:/dev/dri
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
privileged: true
environment:
NEKO_SCREEN: 1920x1080@60
@ -23,4 +29,5 @@ services:
NEKO_ICELITE: 1
NEKO_BROADCAST_URL: rtmp://ome.thuan.au:1935/app/stream-neko
NEKO_NAT1TO1: 192.168.0.34
NEKO_HWENC:
NEKO_HWENC: NVENC
NEKO_VIDEO_CODEC: h264

View file

@ -17,6 +17,7 @@ type BroacastManagerCtx struct {
pipeline *gst.Pipeline
pipelineMu sync.Mutex
pipelineFn func(url string) (string, error)
pipelineRestart chan bool
url string
started bool
@ -31,6 +32,7 @@ func broadcastNew(pipelineFn func(url string) (string, error), defaultUrl string
return &BroacastManagerCtx{
logger: logger,
pipelineFn: pipelineFn,
pipelineRestart: make(chan bool),
url: defaultUrl,
started: defaultUrl != "",
}
@ -71,6 +73,10 @@ func (manager *BroacastManagerCtx) Started() bool {
return manager.started
}
func (manager *BroacastManagerCtx) GetRestart() chan bool {
return manager.pipelineRestart
}
func (manager *BroacastManagerCtx) Url() string {
manager.mu.Lock()
defer manager.mu.Unlock()

View file

@ -53,6 +53,25 @@ func (manager *CaptureManagerCtx) Start() {
}
}
go func() {
for {
_, ok := <-manager.broadcast.GetRestart()
if !ok {
return
}
if !manager.broadcast.Started() {
return
}
manager.broadcast.destroyPipeline()
err := manager.broadcast.createPipeline()
if err != nil && !errors.Is(err, types.ErrCapturePipelineAlreadyExists) {
manager.logger.Panic().Err(err).Msg("unable to recreate broadcast pipeline")
}
}
}()
go func() {
for {
before, ok := <-manager.desktop.GetScreenSizeChangeChannel()

View file

@ -30,7 +30,7 @@ import (
*/
const (
videoSrc = "ximagesrc display-name=%s show-pointer=true use-damage=false ! video/x-raw,framerate=%d/1 ! vaapipostproc ! queue ! "
videoSrc = "ximagesrc display-name=%s show-pointer=true use-damage=false ! video/x-raw,framerate=%d/1 ! videoconvert ! queue ! "
audioSrc = "pulsesrc device=%s ! audio/x-raw,channels=2 ! audioconvert ! "
)
@ -47,7 +47,8 @@ func NewBroadcastPipeline(device string, display string, pipelineSrc string, url
// replace display
pipelineStr = strings.Replace(pipelineStr, "{display}", display, -1)
} else {
pipelineStr = fmt.Sprintf("flvmux name=mux ! rtmpsink location='%s live=1' %s audio/x-raw,channels=2 ! audioconvert ! voaacenc ! mux. %s video/x-raw,format=NV12 ! vaapih264enc rate-control=cbr bitrate=%d keyframe-period=180 quality-level=7 ! h264parse ! mux.", url, audio, video, 8000)
birate := 8000
pipelineStr = fmt.Sprintf("flvmux name=mux ! rtmpsink location='%s live=1 subscribe=stream-neko buffer=1200000' %s audio/x-raw,channels=2 ! audioconvert ! voaacenc ! mux. %s video/x-raw,format=NV12 ! nvh264enc name=encoder rc-lookahead=20 preset=2 gop-size=120 temporal-aq=true bitrate=%d vbv-buffer-size=%d rc-mode=cbr bframes=0 ! h264parse config-interval=-1 ! mux.", url, audio, video, birate, birate)
}
return pipelineStr, nil

View file

@ -14,6 +14,7 @@ type BroadcastManager interface {
Start(url string) error
Stop()
Started() bool
GetRestart() chan bool
Url() string
}

View file

@ -14,6 +14,7 @@ const (
OP_KEY_DOWN = 0x03
OP_KEY_UP = 0x04
OP_KEY_CLK = 0x05
OP_RESTART_BROADCAST = 0x06
)
type PayloadHeader struct {

View file

@ -121,6 +121,9 @@ func (ws *WebSocketHandler) connectUpstream() {
ws.logger.Debug().Msgf("key up %d", payload.Key)
}
case webrtc.OP_RESTART_BROADCAST:
ws.logger.Info().Msg("Restarting broadcast")
ws.capture.Broadcast().GetRestart() <- true
}
}
}

View file

@ -66,6 +66,7 @@ func New(sessions types.SessionManager, desktop types.DesktopManager, capture ty
conf: conf,
sessions: sessions,
desktop: desktop,
capture: capture,
webrtc: webrtc,
state: state,
upgrader: websocket.Upgrader{
@ -88,6 +89,7 @@ type WebSocketHandler struct {
upgrader websocket.Upgrader
sessions types.SessionManager
desktop types.DesktopManager
capture types.CaptureManager
webrtc types.WebRTCManager
state *state.State
conf *config.WebSocket