Compare commits
No commits in common. "60c7fb458ba6089869f62f392d8b58aca65eb81f" and "e49bbb6800658c7807fdf9ab4f2ad6b1b656d8d5" have entirely different histories.
60c7fb458b
...
e49bbb6800
@ -97,10 +97,11 @@ logfile:
|
|||||||
enabled: true # defaults to false
|
enabled: true # defaults to false
|
||||||
path: /path/to/logfile # defaults to $XDG_STATE_HOME/octoplex/octoplex.log
|
path: /path/to/logfile # defaults to $XDG_STATE_HOME/octoplex/octoplex.log
|
||||||
sources:
|
sources:
|
||||||
mediaServer:
|
rtmp:
|
||||||
|
enabled: true # must be true
|
||||||
streamKey: live # defaults to "live"
|
streamKey: live # defaults to "live"
|
||||||
host: rtmp.example.com # defaults to "localhost"
|
host: rtmp.example.com # defaults to "localhost"
|
||||||
rtmp: # must be present, use `rtmp: {}` for defaults
|
bindAddr: # optional
|
||||||
ip: 0.0.0.0 # defaults to 127.0.0.1
|
ip: 0.0.0.0 # defaults to 127.0.0.1
|
||||||
port: 1935 # defaults to 1935
|
port: 1935 # defaults to 1935
|
||||||
destinations:
|
destinations:
|
||||||
|
@ -39,8 +39,8 @@ func Run(ctx context.Context, params RunParams) error {
|
|||||||
applyConfig(cfg, state)
|
applyConfig(cfg, state)
|
||||||
|
|
||||||
// While RTMP is the only source, it doesn't make sense to disable it.
|
// While RTMP is the only source, it doesn't make sense to disable it.
|
||||||
if cfg.Sources.MediaServer.RTMP == nil {
|
if !cfg.Sources.RTMP.Enabled {
|
||||||
return errors.New("config: sources.mediaServer.rtmp is required")
|
return errors.New("config: sources.rtmp.enabled must be set to true")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger := params.Logger
|
logger := params.Logger
|
||||||
@ -89,9 +89,9 @@ func Run(ctx context.Context, params RunParams) error {
|
|||||||
updateUI()
|
updateUI()
|
||||||
|
|
||||||
srv, err := mediaserver.NewActor(ctx, mediaserver.NewActorParams{
|
srv, err := mediaserver.NewActor(ctx, mediaserver.NewActorParams{
|
||||||
RTMPAddr: domain.NetAddr(cfg.Sources.MediaServer.RTMP.NetAddr),
|
RTMPAddr: domain.NetAddr(cfg.Sources.RTMP.BindAddr),
|
||||||
Host: cfg.Sources.MediaServer.Host,
|
RTMPHost: cfg.Sources.RTMP.Host,
|
||||||
StreamKey: mediaserver.StreamKey(cfg.Sources.MediaServer.StreamKey),
|
StreamKey: mediaserver.StreamKey(cfg.Sources.RTMP.StreamKey),
|
||||||
ContainerClient: containerClient,
|
ContainerClient: containerClient,
|
||||||
Logger: logger.With("component", "mediaserver"),
|
Logger: logger.With("component", "mediaserver"),
|
||||||
})
|
})
|
||||||
|
@ -78,13 +78,12 @@ func testIntegration(t *testing.T, rtmpHost string, rtmpIP string, rtmpPort int,
|
|||||||
destURL2 := fmt.Sprintf("rtmp://%s:%d/%s/dest2", hostIP, destServerPort.Int(), wantStreamKey)
|
destURL2 := fmt.Sprintf("rtmp://%s:%d/%s/dest2", hostIP, destServerPort.Int(), wantStreamKey)
|
||||||
configService := setupConfigService(t, config.Config{
|
configService := setupConfigService(t, config.Config{
|
||||||
Sources: config.Sources{
|
Sources: config.Sources{
|
||||||
MediaServer: config.MediaServerSource{
|
RTMP: config.RTMPSource{
|
||||||
|
Enabled: true,
|
||||||
Host: rtmpHost,
|
Host: rtmpHost,
|
||||||
|
BindAddr: config.NetAddr{IP: rtmpIP, Port: rtmpPort},
|
||||||
StreamKey: streamKey,
|
StreamKey: streamKey,
|
||||||
RTMP: &config.RTMPSource{
|
|
||||||
NetAddr: config.NetAddr{IP: rtmpIP, Port: rtmpPort},
|
|
||||||
}},
|
}},
|
||||||
},
|
|
||||||
// Load one destination from config, add the other in-app.
|
// Load one destination from config, add the other in-app.
|
||||||
Destinations: []config.Destination{{Name: "Local server 1", URL: destURL1}},
|
Destinations: []config.Destination{{Name: "Local server 1", URL: destURL1}},
|
||||||
})
|
})
|
||||||
@ -276,9 +275,9 @@ func TestIntegrationCustomRTMPURL(t *testing.T) {
|
|||||||
|
|
||||||
configService := setupConfigService(t, config.Config{
|
configService := setupConfigService(t, config.Config{
|
||||||
Sources: config.Sources{
|
Sources: config.Sources{
|
||||||
MediaServer: config.MediaServerSource{
|
RTMP: config.RTMPSource{
|
||||||
|
Enabled: true,
|
||||||
Host: "rtmp.live.tv",
|
Host: "rtmp.live.tv",
|
||||||
RTMP: &config.RTMPSource{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -302,7 +301,7 @@ func TestIntegrationCustomRTMPURL(t *testing.T) {
|
|||||||
time.Second,
|
time.Second,
|
||||||
"expected to see custom host name",
|
"expected to see custom host name",
|
||||||
)
|
)
|
||||||
printScreen(t, getContents, "Ater opening the app with a custom host name")
|
printScreen(t, getContents, "Ater displaying the fatal error modal")
|
||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
@ -337,7 +336,7 @@ func TestIntegrationRestartDestination(t *testing.T) {
|
|||||||
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
||||||
|
|
||||||
configService := setupConfigService(t, config.Config{
|
configService := setupConfigService(t, config.Config{
|
||||||
Sources: config.Sources{MediaServer: config.MediaServerSource{RTMP: &config.RTMPSource{}}},
|
Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true}},
|
||||||
Destinations: []config.Destination{{
|
Destinations: []config.Destination{{
|
||||||
Name: "Local server 1",
|
Name: "Local server 1",
|
||||||
URL: fmt.Sprintf("rtmp://%s:%d/live", hostIP, destServerRTMPPort.Int()),
|
URL: fmt.Sprintf("rtmp://%s:%d/live", hostIP, destServerRTMPPort.Int()),
|
||||||
@ -483,7 +482,7 @@ func TestIntegrationStartDestinationFailed(t *testing.T) {
|
|||||||
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
||||||
|
|
||||||
configService := setupConfigService(t, config.Config{
|
configService := setupConfigService(t, config.Config{
|
||||||
Sources: config.Sources{MediaServer: config.MediaServerSource{RTMP: &config.RTMPSource{}}},
|
Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true}},
|
||||||
Destinations: []config.Destination{{Name: "Example server", URL: "rtmp://rtmp.example.com/live"}},
|
Destinations: []config.Destination{{Name: "Example server", URL: "rtmp://rtmp.example.com/live"}},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -559,7 +558,7 @@ func TestIntegrationDestinationValidations(t *testing.T) {
|
|||||||
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
||||||
|
|
||||||
configService := setupConfigService(t, config.Config{
|
configService := setupConfigService(t, config.Config{
|
||||||
Sources: config.Sources{MediaServer: config.MediaServerSource{StreamKey: "live", RTMP: &config.RTMPSource{}}},
|
Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true, StreamKey: "live"}},
|
||||||
})
|
})
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@ -702,7 +701,7 @@ func TestIntegrationStartupCheck(t *testing.T) {
|
|||||||
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation())
|
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
configService := setupConfigService(t, config.Config{Sources: config.Sources{MediaServer: config.MediaServerSource{RTMP: &config.RTMPSource{}}}})
|
configService := setupConfigService(t, config.Config{Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true}}})
|
||||||
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@ -771,7 +770,7 @@ func TestIntegrationMediaServerError(t *testing.T) {
|
|||||||
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation())
|
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
configService := setupConfigService(t, config.Config{Sources: config.Sources{MediaServer: config.MediaServerSource{RTMP: &config.RTMPSource{}}}})
|
configService := setupConfigService(t, config.Config{Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true}}})
|
||||||
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@ -810,7 +809,7 @@ func TestIntegrationDockerClientError(t *testing.T) {
|
|||||||
var dockerClient mocks.DockerClient
|
var dockerClient mocks.DockerClient
|
||||||
dockerClient.EXPECT().NetworkCreate(mock.Anything, mock.Anything, mock.Anything).Return(network.CreateResponse{}, errors.New("boom"))
|
dockerClient.EXPECT().NetworkCreate(mock.Anything, mock.Anything, mock.Anything).Return(network.CreateResponse{}, errors.New("boom"))
|
||||||
|
|
||||||
configService := setupConfigService(t, config.Config{Sources: config.Sources{MediaServer: config.MediaServerSource{RTMP: &config.RTMPSource{}}}})
|
configService := setupConfigService(t, config.Config{Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true}}})
|
||||||
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@ -851,7 +850,7 @@ func TestIntegrationDockerConnectionError(t *testing.T) {
|
|||||||
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.WithHost("http://docker.example.com"))
|
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.WithHost("http://docker.example.com"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
configService := setupConfigService(t, config.Config{Sources: config.Sources{MediaServer: config.MediaServerSource{RTMP: &config.RTMPSource{}}}})
|
configService := setupConfigService(t, config.Config{Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true}}})
|
||||||
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
@ -30,19 +30,15 @@ type NetAddr struct {
|
|||||||
|
|
||||||
// RTMPSource holds the configuration for the RTMP source.
|
// RTMPSource holds the configuration for the RTMP source.
|
||||||
type RTMPSource struct {
|
type RTMPSource struct {
|
||||||
NetAddr `yaml:",inline"`
|
Enabled bool `yaml:"enabled"`
|
||||||
}
|
|
||||||
|
|
||||||
// MediaServerSource holds the configuration for the media server source.
|
|
||||||
type MediaServerSource struct {
|
|
||||||
StreamKey string `yaml:"streamKey,omitempty"`
|
StreamKey string `yaml:"streamKey,omitempty"`
|
||||||
Host string `yaml:"host,omitempty"`
|
Host string `yaml:"host,omitempty"`
|
||||||
RTMP *RTMPSource `yaml:"rtmp,omitempty"`
|
BindAddr NetAddr `yaml:"bindAddr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sources holds the configuration for the sources.
|
// Sources holds the configuration for the sources.
|
||||||
type Sources struct {
|
type Sources struct {
|
||||||
MediaServer MediaServerSource `yaml:"mediaServer"`
|
RTMP RTMPSource `yaml:"rtmp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config holds the configuration for the application.
|
// Config holds the configuration for the application.
|
||||||
|
@ -182,8 +182,8 @@ func (s *Service) writeConfig(cfgBytes []byte) error {
|
|||||||
//
|
//
|
||||||
// This function may set exported fields to arbitrary values.
|
// This function may set exported fields to arbitrary values.
|
||||||
func (s *Service) populateConfigOnBuild(cfg *Config) {
|
func (s *Service) populateConfigOnBuild(cfg *Config) {
|
||||||
cfg.Sources.MediaServer.StreamKey = "live"
|
cfg.Sources.RTMP.Enabled = true
|
||||||
cfg.Sources.MediaServer.RTMP = &RTMPSource{NetAddr{"127.0.0.1", 1935}}
|
cfg.Sources.RTMP.StreamKey = "live"
|
||||||
|
|
||||||
s.populateConfigOnRead(cfg)
|
s.populateConfigOnRead(cfg)
|
||||||
}
|
}
|
||||||
|
@ -44,9 +44,7 @@ func TestConfigServiceCurrent(t *testing.T) {
|
|||||||
t.Cleanup(func() { require.NoError(t, os.RemoveAll(systemConfigDir)) })
|
t.Cleanup(func() { require.NoError(t, os.RemoveAll(systemConfigDir)) })
|
||||||
|
|
||||||
// Ensure defaults are set:
|
// Ensure defaults are set:
|
||||||
assert.NotNil(t, service.Current().Sources.MediaServer.RTMP)
|
assert.True(t, service.Current().Sources.RTMP.Enabled)
|
||||||
assert.Equal(t, "127.0.0.1", service.Current().Sources.MediaServer.RTMP.IP)
|
|
||||||
assert.Equal(t, 1935, service.Current().Sources.MediaServer.RTMP.Port)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigServiceCreateConfig(t *testing.T) {
|
func TestConfigServiceCreateConfig(t *testing.T) {
|
||||||
@ -69,9 +67,7 @@ func TestConfigServiceCreateConfig(t *testing.T) {
|
|||||||
|
|
||||||
var readCfg config.Config
|
var readCfg config.Config
|
||||||
require.NoError(t, yaml.Unmarshal(cfgBytes, &readCfg))
|
require.NoError(t, yaml.Unmarshal(cfgBytes, &readCfg))
|
||||||
assert.NotNil(t, readCfg.Sources.MediaServer.RTMP)
|
assert.True(t, readCfg.Sources.RTMP.Enabled, "default values not set")
|
||||||
assert.Equal(t, "127.0.0.1", readCfg.Sources.MediaServer.RTMP.IP)
|
|
||||||
assert.Equal(t, 1935, readCfg.Sources.MediaServer.RTMP.Port)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigServiceReadConfig(t *testing.T) {
|
func TestConfigServiceReadConfig(t *testing.T) {
|
||||||
@ -94,17 +90,16 @@ func TestConfigServiceReadConfig(t *testing.T) {
|
|||||||
Path: "test.log",
|
Path: "test.log",
|
||||||
},
|
},
|
||||||
Sources: config.Sources{
|
Sources: config.Sources{
|
||||||
MediaServer: config.MediaServerSource{
|
RTMP: config.RTMPSource{
|
||||||
|
Enabled: true,
|
||||||
StreamKey: "s3cr3t",
|
StreamKey: "s3cr3t",
|
||||||
Host: "rtmp.example.com",
|
Host: "rtmp.example.com",
|
||||||
RTMP: &config.RTMPSource{
|
BindAddr: config.NetAddr{
|
||||||
NetAddr: config.NetAddr{
|
|
||||||
IP: "0.0.0.0",
|
IP: "0.0.0.0",
|
||||||
Port: 19350,
|
Port: 19350,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
Destinations: []config.Destination{
|
Destinations: []config.Destination{
|
||||||
{
|
{
|
||||||
Name: "my stream",
|
Name: "my stream",
|
||||||
|
5
internal/config/testdata/complete.yml
vendored
5
internal/config/testdata/complete.yml
vendored
@ -3,10 +3,11 @@ logfile:
|
|||||||
enabled: true
|
enabled: true
|
||||||
path: test.log
|
path: test.log
|
||||||
sources:
|
sources:
|
||||||
mediaServer:
|
rtmp:
|
||||||
|
enabled: true
|
||||||
streamKey: s3cr3t
|
streamKey: s3cr3t
|
||||||
host: rtmp.example.com
|
host: rtmp.example.com
|
||||||
rtmp:
|
bindAddr:
|
||||||
ip: 0.0.0.0
|
ip: 0.0.0.0
|
||||||
port: 19350
|
port: 19350
|
||||||
destinations:
|
destinations:
|
||||||
|
@ -66,7 +66,7 @@ type Actor struct {
|
|||||||
type NewActorParams struct {
|
type NewActorParams struct {
|
||||||
APIPort int // defaults to 9997
|
APIPort int // defaults to 9997
|
||||||
RTMPAddr domain.NetAddr // defaults to 127.0.0.1:1935
|
RTMPAddr domain.NetAddr // defaults to 127.0.0.1:1935
|
||||||
Host string // defaults to "localhost"
|
RTMPHost string // defaults to "localhost"
|
||||||
StreamKey StreamKey // defaults to "live"
|
StreamKey StreamKey // defaults to "live"
|
||||||
ChanSize int // defaults to 64
|
ChanSize int // defaults to 64
|
||||||
UpdateStateInterval time.Duration // defaults to 5 seconds
|
UpdateStateInterval time.Duration // defaults to 5 seconds
|
||||||
@ -95,7 +95,7 @@ func NewActor(ctx context.Context, params NewActorParams) (_ *Actor, err error)
|
|||||||
return &Actor{
|
return &Actor{
|
||||||
apiPort: cmp.Or(params.APIPort, defaultAPIPort),
|
apiPort: cmp.Or(params.APIPort, defaultAPIPort),
|
||||||
rtmpAddr: rtmpAddr,
|
rtmpAddr: rtmpAddr,
|
||||||
rtmpHost: cmp.Or(params.Host, defaultRTMPHost),
|
rtmpHost: cmp.Or(params.RTMPHost, defaultRTMPHost),
|
||||||
streamKey: cmp.Or(params.StreamKey, defaultStreamKey),
|
streamKey: cmp.Or(params.StreamKey, defaultStreamKey),
|
||||||
updateStateInterval: cmp.Or(params.UpdateStateInterval, defaultUpdateStateInterval),
|
updateStateInterval: cmp.Or(params.UpdateStateInterval, defaultUpdateStateInterval),
|
||||||
tlsCert: tlsCert,
|
tlsCert: tlsCert,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user