Skip to content

Commit

Permalink
Merge branch 'bluenviron:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
p4xx07 authored Oct 2, 2023
2 parents 7885f28 + 9c6168e commit 0e6e90e
Show file tree
Hide file tree
Showing 17 changed files with 335 additions and 128 deletions.
16 changes: 16 additions & 0 deletions .github/DISCUSSION_TEMPLATE/questions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
body:

- type: textarea
attributes:
label: Question
validations:
required: true

- type: markdown
attributes:
value: |
Note: If you are asking for help because you're having trouble doing something, provide enough informations to replicate the problem. In particular, include in the question:
* the server version you are using
* precise instructions on how to replicate the problem
* server logs with setting `logLevel` set to `debug`
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ blank_issues_enabled: false

contact_links:
- name: Question
url: https://github.com/bluenviron/mediamtx/discussions/new
url: https://github.com/bluenviron/mediamtx/discussions/new?category=questions
about: Ask the community for help
51 changes: 47 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,34 @@ Currently the server supports recording tracks encoded with the following codecs
* Video: AV1, VP9, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG
* Audio: Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3
To upload recordings to a remote location, you can use _MediaMTX_ together with [rclone](https://github.com/rclone/rclone), a command line tool that provides file synchronization capabilities with a huge variety of services (including S3, FTP, SMB, Google Drive):
1. Download and install [rclone](https://github.com/rclone/rclone).
2. Configure _rclone_:
```
rclone config
```
3. Place `rclone` into the `runOnInit` and `runOnRecordSegmentComplete` hooks:
```yml
record: yes
paths:
mypath:
# this is needed to sync segments after a crash.
# replace myconfig with the name of the rclone config.
runOnInit: rclone sync -v ./recordings myconfig:/my-path/recordings
# this is called when a segment has been finalized.
# replace myconfig with the name of the rclone config.
runOnRecordSegmentComplete: rclone sync -v --min-age=1ms ./recordings myconfig:/my-path/recordings
```
If you want to delete local segments after they are uploaded, replace `rclone sync` with `rclone move`.
### Forward streams to another server
To forward incoming streams to another server, use _FFmpeg_ inside the `runOnReady` parameter:
Expand Down Expand Up @@ -1311,7 +1339,7 @@ paths:
# * RTSP_PORT: RTSP server port
# * G1, G2, ...: regular expression groups, if path name is
# a regular expression.
runOnReady: curl http://my-custom-server/webhook?source_type=$MTX_SOURCE_TYPE&source_id=$MTX_SOURCE_ID
runOnReady: curl http://my-custom-server/webhook?path=$MTX_PATH&source_type=$MTX_SOURCE_TYPE&source_id=$MTX_SOURCE_ID
# Restart the command if it exits.
runOnReadyRestart: no
```
Expand All @@ -1322,7 +1350,7 @@ paths:
paths:
mypath:
# Environment variables are the same of runOnReady.
runOnNotReady: curl http://my-custom-server/webhook?source_type=$MTX_SOURCE_TYPE&source_id=$MTX_SOURCE_ID
runOnNotReady: curl http://my-custom-server/webhook?path=$MTX_PATH&source_type=$MTX_SOURCE_TYPE&source_id=$MTX_SOURCE_ID
```
`runOnRead` allows to run a command when a client starts reading:
Expand All @@ -1338,7 +1366,7 @@ paths:
# * RTSP_PORT: RTSP server port
# * G1, G2, ...: regular expression groups, if path name is
# a regular expression.
runOnRead: curl http://my-custom-server/webhook?reader_type=$MTX_READER_TYPE&reader_id=$MTX_READER_ID
runOnRead: curl http://my-custom-server/webhook?path=$MTX_PATH&reader_type=$MTX_READER_TYPE&reader_id=$MTX_READER_ID
# Restart the command if it exits.
runOnReadRestart: no
```
Expand All @@ -1350,7 +1378,22 @@ paths:
mypath:
# Command to run when a client stops reading.
# Environment variables are the same of runOnRead.
runOnUnread: curl http://my-custom-server/webhook?reader_type=$MTX_READER_TYPE&reader_id=$MTX_READER_ID
runOnUnread: curl http://my-custom-server/webhook?path=$MTX_PATH&reader_type=$MTX_READER_TYPE&reader_id=$MTX_READER_ID
```
`runOnRecordSegmentComplete` allows to run a command when a record segment is complete:
```yml
paths:
mypath:
# Command to run when a record segment is complete.
# The following environment variables are available:
# * MTX_PATH: path name
# * RTSP_PORT: RTSP server port
# * G1, G2, ...: regular expression groups, if path name is
# a regular expression.
# * MTX_SEGMENT_PATH: segment file path
runOnRecordSegmentComplete: curl http://my-custom-server/webhook?path=$MTX_PATH&segment_path=$MTX_SEGMENT_PATH
```
### API
Expand Down
6 changes: 4 additions & 2 deletions apidocs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ components:
type: string
maxReaders:
type: integer
srtReadPassphrase:
type: string
record:
type: boolean

Expand Down Expand Up @@ -241,8 +243,6 @@ components:
type: string
srtPublishPassphrase:
type: string
srtReadPassphrase:
type: string

# RTSP
sourceProtocol:
Expand Down Expand Up @@ -349,6 +349,8 @@ components:
type: boolean
runOnUnread:
type: string
runOnRecordSegmentComplete:
type: string

Path:
type: object
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/notedit/rtmp v0.0.2
github.com/pion/ice/v2 v2.3.11
github.com/pion/interceptor v0.1.19
github.com/pion/interceptor v0.1.20
github.com/pion/rtcp v1.2.10
github.com/pion/rtp v1.8.2
github.com/pion/sdp/v3 v3.0.6
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ
github.com/pion/ice/v2 v2.3.11 h1:rZjVmUwyT55cmN8ySMpL7rsS8KYsJERsrxJLLxpKhdw=
github.com/pion/ice/v2 v2.3.11/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E=
github.com/pion/interceptor v0.1.18/go.mod h1:tpvvF4cPM6NGxFA1DUMbhabzQBxdWMATDGEUYOR9x6I=
github.com/pion/interceptor v0.1.19 h1:tq0TGBzuZQqipyBhaC1mVUCfCh8XjDKUuibq9rIl5t4=
github.com/pion/interceptor v0.1.19/go.mod h1:VANhFxdJezB8mwToMMmrmyHyP9gym6xLqIUch31xryg=
github.com/pion/interceptor v0.1.20 h1:gORAnvlXu1f4Bx+TcXe8UJ37Jqb/tkNQ6E83NNqYZh0=
github.com/pion/interceptor v0.1.20/go.mod h1:wkbPYAak5zKsfpVDYMtEfWEy8D4zL+rpxCxPImLOg3Y=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/mdns v0.0.8 h1:HhicWIg7OX5PVilyBO6plhMetInbzkVJAhbdJiAeVaI=
Expand Down
67 changes: 38 additions & 29 deletions internal/conf/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type PathConf struct {
SourceOnDemandStartTimeout StringDuration `json:"sourceOnDemandStartTimeout"`
SourceOnDemandCloseAfter StringDuration `json:"sourceOnDemandCloseAfter"`
MaxReaders int `json:"maxReaders"`
SRTReadPassphrase string `json:"srtReadPassphrase"`
Record bool `json:"record"`

// Authentication
Expand All @@ -74,7 +75,6 @@ type PathConf struct {
DisablePublisherOverride bool `json:"disablePublisherOverride"` // deprecated
Fallback string `json:"fallback"`
SRTPublishPassphrase string `json:"srtPublishPassphrase"`
SRTReadPassphrase string `json:"srtReadPassphrase"`

// RTSP
SourceProtocol SourceProtocol `json:"sourceProtocol"`
Expand Down Expand Up @@ -120,18 +120,19 @@ type PathConf struct {
RPICameraTextOverlay string `json:"rpiCameraTextOverlay"`

// Hooks
RunOnInit string `json:"runOnInit"`
RunOnInitRestart bool `json:"runOnInitRestart"`
RunOnDemand string `json:"runOnDemand"`
RunOnDemandRestart bool `json:"runOnDemandRestart"`
RunOnDemandStartTimeout StringDuration `json:"runOnDemandStartTimeout"`
RunOnDemandCloseAfter StringDuration `json:"runOnDemandCloseAfter"`
RunOnReady string `json:"runOnReady"`
RunOnReadyRestart bool `json:"runOnReadyRestart"`
RunOnNotReady string `json:"runOnNotReady"`
RunOnRead string `json:"runOnRead"`
RunOnReadRestart bool `json:"runOnReadRestart"`
RunOnUnread string `json:"runOnUnread"`
RunOnInit string `json:"runOnInit"`
RunOnInitRestart bool `json:"runOnInitRestart"`
RunOnDemand string `json:"runOnDemand"`
RunOnDemandRestart bool `json:"runOnDemandRestart"`
RunOnDemandStartTimeout StringDuration `json:"runOnDemandStartTimeout"`
RunOnDemandCloseAfter StringDuration `json:"runOnDemandCloseAfter"`
RunOnReady string `json:"runOnReady"`
RunOnReadyRestart bool `json:"runOnReadyRestart"`
RunOnNotReady string `json:"runOnNotReady"`
RunOnRead string `json:"runOnRead"`
RunOnReadRestart bool `json:"runOnReadRestart"`
RunOnUnread string `json:"runOnUnread"`
RunOnRecordSegmentComplete string `json:"runOnRecordSegmentComplete"`
}

func (pconf *PathConf) check(conf *Conf, name string) error {
Expand Down Expand Up @@ -319,13 +320,23 @@ func (pconf *PathConf) check(conf *Conf, name string) error {
return fmt.Errorf("'sourceOnDemand' is useless when source is 'publisher'")
}
}
if pconf.SRTReadPassphrase != "" {
err := srtCheckPassphrase(pconf.SRTReadPassphrase)
if err != nil {
return fmt.Errorf("invalid 'readRTPassphrase': %v", err)
}
}

// Publisher

if pconf.DisablePublisherOverride {
pconf.OverridePublisher = true
}
if pconf.Fallback != "" {
if pconf.Source != "publisher" {
return fmt.Errorf("'fallback' can only be used when source is 'publisher'")
}

if strings.HasPrefix(pconf.Fallback, "/") {
err := IsValidPathName(pconf.Fallback[1:])
if err != nil {
Expand All @@ -338,6 +349,16 @@ func (pconf *PathConf) check(conf *Conf, name string) error {
}
}
}
if pconf.SRTPublishPassphrase != "" {
if pconf.Source != "publisher" {
return fmt.Errorf("'srtPublishPassphase' can only be used when source is 'publisher'")
}

err := srtCheckPassphrase(pconf.SRTPublishPassphrase)
if err != nil {
return fmt.Errorf("invalid 'srtPublishPassphrase': %v", err)
}
}

// Authentication

Expand Down Expand Up @@ -374,25 +395,11 @@ func (pconf *PathConf) check(conf *Conf, name string) error {
}
}

// SRT

if pconf.SRTPublishPassphrase != "" {
err := srtCheckPassphrase(pconf.SRTPublishPassphrase)
if err != nil {
return fmt.Errorf("invalid 'srtPublishPassphrase': %v", err)
}
}
if pconf.SRTReadPassphrase != "" {
err := srtCheckPassphrase(pconf.SRTReadPassphrase)
if err != nil {
return fmt.Errorf("invalid 'readRTPassphrase': %v", err)
}
}

// Hooks

if pconf.RunOnInit != "" && pconf.Regexp != nil {
return fmt.Errorf("a path with a regular expression does not support option 'runOnInit'; use another path")
return fmt.Errorf("a path with a regular expression (or path 'all')" +
" does not support option 'runOnInit'; use another path")
}
if pconf.RunOnDemand != "" && pconf.Source != "publisher" {
return fmt.Errorf("'runOnDemand' can be used only when source is 'publisher'")
Expand All @@ -419,6 +426,8 @@ func (pconf PathConf) Clone() *PathConf {
panic(err)
}

dest.Regexp = pconf.Regexp

return &dest
}

Expand Down
8 changes: 5 additions & 3 deletions internal/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ func (p *Core) createResources(initial bool) error {
if initial {
p.Log(logger.Info, "MediaMTX %s", version)

if p.confPath == "" {
if p.confPath != "" {
a, _ := filepath.Abs(p.confPath)
p.Log(logger.Info, "configuration loaded from %s", a)
} else {
list := make([]string, len(defaultConfPaths))
for i, pa := range defaultConfPaths {
a, _ := filepath.Abs(pa)
Expand All @@ -224,8 +227,7 @@ func (p *Core) createResources(initial bool) error {
}

// on Linux, try to raise the number of file descriptors that can be opened
// to allow the maximum possible number of clients
// do not check for errors
// to allow the maximum possible number of clients.
rlimit.Raise() //nolint:errcheck

gin.SetMode(gin.ReleaseMode)
Expand Down
Loading

0 comments on commit 0e6e90e

Please sign in to comment.