feat: RTMP URL
This commit is contained in:
parent
0cf9a3db42
commit
8c12683a3c
@ -4,4 +4,5 @@ package domain
|
|||||||
type AppState struct {
|
type AppState struct {
|
||||||
ContainerRunning bool
|
ContainerRunning bool
|
||||||
IngressLive bool
|
IngressLive bool
|
||||||
|
IngressURL string
|
||||||
}
|
}
|
||||||
|
11
main.go
11
main.go
@ -43,7 +43,7 @@ func run(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("start media server: %w", err)
|
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")})
|
ui, err := terminal.StartActor(ctx, terminal.StartActorParams{Logger: logger.With("component", "ui")})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -61,8 +61,7 @@ func run(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
case serverState, ok := <-srv.C():
|
case serverState, ok := <-srv.C():
|
||||||
if ok {
|
if ok {
|
||||||
state.ContainerRunning = serverState.ContainerRunning
|
applyServerState(serverState, state)
|
||||||
state.IngressLive = serverState.IngressLive
|
|
||||||
updateUI()
|
updateUI()
|
||||||
} else {
|
} else {
|
||||||
logger.Info("State channel closed, shutting down...")
|
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
|
||||||
|
}
|
||||||
|
@ -13,12 +13,16 @@ import (
|
|||||||
"git.netflux.io/rob/termstream/container"
|
"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.
|
// State contains the current state of the media server.
|
||||||
type State struct {
|
type State struct {
|
||||||
ContainerRunning bool
|
ContainerRunning bool
|
||||||
IngressLive bool
|
IngressLive bool
|
||||||
|
IngressURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
// action is an action to be performed by the actor.
|
// 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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("run container: %w", err)
|
return nil, fmt.Errorf("run container: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.state.ContainerRunning = true
|
actor.state.ContainerRunning = true
|
||||||
|
actor.state.IngressURL = "rtmp://localhost:1935/" + rtmpPath
|
||||||
|
|
||||||
go actor.actorLoop(containerDone)
|
go actor.actorLoop(containerDone)
|
||||||
|
|
||||||
@ -192,7 +198,7 @@ func (s *Actor) fetchIngressStateFromServer() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, conn := range resp.Items {
|
for _, conn := range resp.Items {
|
||||||
if conn.Path == "live" && conn.State == "publish" {
|
if conn.Path == rtmpPath && conn.State == "publish" {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,10 @@ func TestMediaServerStartStop(t *testing.T) {
|
|||||||
"container not in RUNNING state",
|
"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")
|
launchFFMPEG(t, "rtmp://localhost:1935/live")
|
||||||
require.Eventually(
|
require.Eventually(
|
||||||
t,
|
t,
|
||||||
|
@ -48,7 +48,7 @@ func StartActor(ctx context.Context, params StartActorParams) (*Actor, error) {
|
|||||||
|
|
||||||
flex := tview.NewFlex().
|
flex := tview.NewFlex().
|
||||||
SetDirection(tview.FlexRow).
|
SetDirection(tview.FlexRow).
|
||||||
AddItem(serverBox, 7, 0, false).
|
AddItem(serverBox, 9, 0, false).
|
||||||
AddItem(destBox, 0, 1, false)
|
AddItem(destBox, 0, 1, false)
|
||||||
|
|
||||||
container := tview.NewFlex().
|
container := tview.NewFlex().
|
||||||
@ -127,20 +127,27 @@ func generateServerStatus(state domain.AppState) string {
|
|||||||
var s strings.Builder
|
var s strings.Builder
|
||||||
|
|
||||||
s.WriteString("\n")
|
s.WriteString("\n")
|
||||||
s.WriteString("Container status: ")
|
|
||||||
|
s.WriteString("[grey]Container status: ")
|
||||||
if state.ContainerRunning {
|
if state.ContainerRunning {
|
||||||
s.WriteString("[green]running[white]")
|
s.WriteString("[green]running")
|
||||||
} else {
|
} else {
|
||||||
s.WriteString("[red]stopped[white]")
|
s.WriteString("[red]stopped")
|
||||||
}
|
}
|
||||||
s.WriteString("\n\n")
|
s.WriteString("\n\n")
|
||||||
s.WriteString("Ingress stream: ")
|
|
||||||
if state.IngressLive {
|
s.WriteString("[grey]RTMP URL: ")
|
||||||
s.WriteString("[green]on-air[white]")
|
if state.IngressURL != "" {
|
||||||
} else {
|
s.WriteString("[white:grey]" + state.IngressURL)
|
||||||
s.WriteString("[yellow]off-air[white]")
|
}
|
||||||
|
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()
|
return s.String()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user