feat: RTMP URL

This commit is contained in:
Rob Watson 2025-01-21 20:26:04 +01:00
parent 0cf9a3db42
commit 8c12683a3c
5 changed files with 38 additions and 16 deletions

View File

@ -4,4 +4,5 @@ package domain
type AppState struct {
ContainerRunning bool
IngressLive bool
IngressURL string
}

11
main.go
View File

@ -43,7 +43,7 @@ func run(ctx context.Context) error {
if err != nil {
return fmt.Errorf("start media server: %w", err)
}
state.ContainerRunning = true
applyServerState(srv.State(), state)
ui, err := terminal.StartActor(ctx, terminal.StartActorParams{Logger: logger.With("component", "ui")})
if err != nil {
@ -61,8 +61,7 @@ func run(ctx context.Context) error {
return nil
case serverState, ok := <-srv.C():
if ok {
state.ContainerRunning = serverState.ContainerRunning
state.IngressLive = serverState.IngressLive
applyServerState(serverState, state)
updateUI()
} else {
logger.Info("State channel closed, shutting down...")
@ -71,3 +70,9 @@ func run(ctx context.Context) error {
}
}
}
func applyServerState(serverState mediaserver.State, appState *domain.AppState) {
appState.ContainerRunning = serverState.ContainerRunning
appState.IngressLive = serverState.IngressLive
appState.IngressURL = serverState.IngressURL
}

View File

@ -13,12 +13,16 @@ import (
"git.netflux.io/rob/termstream/container"
)
const imageNameMediaMTX = "bluenviron/mediamtx"
const (
imageNameMediaMTX = "bluenviron/mediamtx"
rtmpPath = "live"
)
// State contains the current state of the media server.
type State struct {
ContainerRunning bool
IngressLive bool
IngressURL string
}
// action is an action to be performed by the actor.
@ -79,7 +83,9 @@ func StartActor(ctx context.Context, params StartActorParams) (*Actor, error) {
if err != nil {
return nil, fmt.Errorf("run container: %w", err)
}
actor.state.ContainerRunning = true
actor.state.IngressURL = "rtmp://localhost:1935/" + rtmpPath
go actor.actorLoop(containerDone)
@ -192,7 +198,7 @@ func (s *Actor) fetchIngressStateFromServer() (bool, error) {
}
for _, conn := range resp.Items {
if conn.Path == "live" && conn.State == "publish" {
if conn.Path == rtmpPath && conn.State == "publish" {
return true, nil
}
}

View File

@ -47,7 +47,10 @@ func TestMediaServerStartStop(t *testing.T) {
"container not in RUNNING state",
)
require.False(t, actor.State().IngressLive)
state := actor.State()
assert.False(t, state.IngressLive)
assert.Equal(t, "rtmp://localhost:1935/live", state.IngressURL)
launchFFMPEG(t, "rtmp://localhost:1935/live")
require.Eventually(
t,

View File

@ -48,7 +48,7 @@ func StartActor(ctx context.Context, params StartActorParams) (*Actor, error) {
flex := tview.NewFlex().
SetDirection(tview.FlexRow).
AddItem(serverBox, 7, 0, false).
AddItem(serverBox, 9, 0, false).
AddItem(destBox, 0, 1, false)
container := tview.NewFlex().
@ -127,20 +127,27 @@ func generateServerStatus(state domain.AppState) string {
var s strings.Builder
s.WriteString("\n")
s.WriteString("Container status: ")
s.WriteString("[grey]Container status: ")
if state.ContainerRunning {
s.WriteString("[green]running[white]")
s.WriteString("[green]running")
} else {
s.WriteString("[red]stopped[white]")
s.WriteString("[red]stopped")
}
s.WriteString("\n\n")
s.WriteString("Ingress stream: ")
if state.IngressLive {
s.WriteString("[green]on-air[white]")
} else {
s.WriteString("[yellow]off-air[white]")
s.WriteString("[grey]RTMP URL: ")
if state.IngressURL != "" {
s.WriteString("[white:grey]" + state.IngressURL)
}
s.WriteString("\n\n")
s.WriteString("[grey:black]Ingress stream: ")
if state.IngressLive {
s.WriteString("[green]on-air")
} else {
s.WriteString("[yellow]off-air")
}
s.WriteString("\n\n\n")
return s.String()
}