diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 93c2d2ac62f..9c49fd22306 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -63,7 +63,7 @@ yes / no + ## Describe the feature Description diff --git a/.github/workflows/bump-hls-js.yml b/.github/workflows/bump_hls_js.yml similarity index 84% rename from .github/workflows/bump-hls-js.yml rename to .github/workflows/bump_hls_js.yml index 69c4443289a..cd78035b05a 100644 --- a/.github/workflows/bump-hls-js.yml +++ b/.github/workflows/bump_hls_js.yml @@ -1,4 +1,4 @@ -name: bump-hls-js +name: bump_hls_js on: schedule: @@ -6,7 +6,7 @@ on: workflow_dispatch: jobs: - bump-hls-js: + bump_hls_js: runs-on: ubuntu-20.04 steps: @@ -20,8 +20,8 @@ jobs: && ((git checkout deps/hlsjs && git rebase ${GITHUB_REF_NAME}) || git checkout -b deps/hlsjs) - run: > - curl -o internal/core/hls.min.js https://cdn.jsdelivr.net/npm/hls.js@latest/dist/hls.min.js - && echo VERSION=$(cat internal/core/hls.min.js | grep -o '"version",get:function(){return".*"}' | sed 's/"version",get:function(){return"\(.*\)"}/\1/') >> $GITHUB_ENV + curl -o internal/servers/hls/hls.min.js https://cdn.jsdelivr.net/npm/hls.js@latest/dist/hls.min.js + && echo VERSION=$(cat internal/servers/hls/hls.min.js | grep -o '"version",get:function(){return".*"}' | sed 's/"version",get:function(){return"\(.*\)"}/\1/') >> $GITHUB_ENV - id: check_repo run: > diff --git a/.github/workflows/lint.yml b/.github/workflows/code_lint.yml similarity index 83% rename from .github/workflows/lint.yml rename to .github/workflows/code_lint.yml index 5f7f364f6dd..e21c9a719b3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/code_lint.yml @@ -1,4 +1,4 @@ -name: lint +name: code_lint on: push: @@ -7,7 +7,7 @@ on: branches: [ main ] jobs: - code: + golangci_lint: runs-on: ubuntu-22.04 steps: @@ -19,9 +19,9 @@ jobs: - uses: golangci/golangci-lint-action@v3 with: - version: v1.53.3 + version: v1.55.0 - mod-tidy: + mod_tidy: runs-on: ubuntu-22.04 steps: @@ -29,13 +29,13 @@ jobs: - uses: actions/setup-go@v2 with: - go-version: "1.20" + go-version: "1.21" - run: | go mod tidy git diff --exit-code - apidocs: + api_docs: runs-on: ubuntu-22.04 steps: diff --git a/.github/workflows/test.yml b/.github/workflows/code_test.yml similarity index 89% rename from .github/workflows/test.yml rename to .github/workflows/code_test.yml index fd8dff8c4f1..de222864941 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/code_test.yml @@ -1,4 +1,4 @@ -name: test +name: code_test on: push: @@ -7,7 +7,7 @@ on: branches: [ main ] jobs: - test64: + test_64: runs-on: ubuntu-22.04 steps: @@ -19,7 +19,7 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} - test32: + test_32: runs-on: ubuntu-22.04 steps: @@ -35,6 +35,6 @@ jobs: - uses: actions/setup-go@v2 with: - go-version: "1.20" + go-version: "1.21" - run: make test-highlevel-nodocker diff --git a/.github/workflows/issue-lint.yml b/.github/workflows/issue_lint.yml similarity index 97% rename from .github/workflows/issue-lint.yml rename to .github/workflows/issue_lint.yml index b3dd6effb43..4a2185cc189 100644 --- a/.github/workflows/issue-lint.yml +++ b/.github/workflows/issue_lint.yml @@ -1,11 +1,11 @@ -name: issue-lint +name: issue_lint on: issues: types: [opened] jobs: - issue-lint: + issue_lint: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/issue-lock.yml b/.github/workflows/issue_lock.yml similarity index 97% rename from .github/workflows/issue-lock.yml rename to .github/workflows/issue_lock.yml index 6d370542cb9..a9e9f208c4e 100644 --- a/.github/workflows/issue-lock.yml +++ b/.github/workflows/issue_lock.yml @@ -1,4 +1,4 @@ -name: issue-lock +name: issue_lock on: schedule: @@ -6,7 +6,7 @@ on: workflow_dispatch: jobs: - issue-lock: + issue_lock: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/binaries.yml b/.github/workflows/nightly_binaries.yml similarity index 84% rename from .github/workflows/binaries.yml rename to .github/workflows/nightly_binaries.yml index 14fe6821a72..419a8dc071c 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/nightly_binaries.yml @@ -1,10 +1,10 @@ -name: binaries +name: nightly_binaries on: workflow_dispatch: jobs: - binaries: + nightly_binaries: runs-on: ubuntu-22.04 steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 32914f9e7a7..99639ceb757 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,13 +19,11 @@ jobs: name: binaries path: binaries - github: + github_release: needs: binaries runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 with: name: binaries @@ -58,6 +56,51 @@ jobs: }); } + github_notify_issues: + needs: github_release + runs-on: ubuntu-22.04 + + steps: + - uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { repo: { owner, repo } } = context; + + const tags = await github.rest.repos.listTags({ + owner, + repo, + }); + + const curTag = tags.data[0]; + const prevTag = tags.data[1]; + + const diff = await github.rest.repos.compareCommitsWithBasehead({ + owner, + repo, + basehead: `${prevTag.commit.sha}...${curTag.commit.sha}`, + }); + + const issues = {}; + + for (const commit of diff.data.commits) { + for (const match of commit.commit.message.matchAll(/(^| |\()#([0-9]+)( |\)|$)/g)) { + issues[match[2]] = 1; + } + } + + for (const issue in issues) { + try { + await github.rest.issues.createComment({ + owner, + repo, + issue_number: parseInt(issue), + body: `This issue is mentioned in release ${curTag.name} 🚀\n` + + `Check out the entire changelog by [clicking here](https://github.com/${owner}/${repo}/releases/tag/${curTag.name})`, + }); + } catch (exc) {} + } + dockerhub: needs: binaries runs-on: ubuntu-22.04 @@ -87,7 +130,7 @@ jobs: DOCKER_USER_LEGACY: ${{ secrets.DOCKER_USER_LEGACY }} DOCKER_PASSWORD_LEGACY: ${{ secrets.DOCKER_PASSWORD_LEGACY }} - apidocs: + api_docs: needs: binaries runs-on: ubuntu-22.04 diff --git a/.golangci.yml b/.golangci.yml index 593d6b20fe5..d2c93841a05 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,7 +1,10 @@ linters: enable: + - asciicheck + - bidichk - bodyclose - dupl + - errorlint - exportloopref - gochecknoinits - gocritic @@ -13,6 +16,7 @@ linters: - prealloc - revive - unconvert + - tparallel - wastedassign - whitespace diff --git a/Makefile b/Makefile index 1b3d08a8587..137eb9232c2 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -BASE_IMAGE = golang:1.20-alpine3.18 -LINT_IMAGE = golangci/golangci-lint:v1.53.3 +BASE_IMAGE = golang:1.21-alpine3.18 +LINT_IMAGE = golangci/golangci-lint:v1.55.2 NODE_IMAGE = node:16-alpine3.18 ALPINE_IMAGE = alpine:3.18 RPI32_IMAGE = balenalib/raspberry-pi:bullseye-run-20230712 diff --git a/README.md b/README.md index d4cf6bd1c13..a630cccb55a 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ Live streams can be published to the server with: |--------|--------|------------|------------| |[SRT clients](#srt-clients)||H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3| |[SRT cameras and servers](#srt-cameras-and-servers)||H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3| -|[WebRTC clients](#webrtc-clients)|Browser-based, WHIP|AV1, VP9, VP8, H264|Opus, G722, G711| -|[WebRTC servers](#webrtc-servers)|WHEP|AV1, VP9, VP8, H264|Opus, G722, G711| -|[RTSP clients](#rtsp-clients)|UDP, TCP, RTSPS|AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG and any RTP-compatible codec|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711, LPCM and any RTP-compatible codec| -|[RTSP cameras and servers](#rtsp-cameras-and-servers)|UDP, UDP-Multicast, TCP, RTSPS|AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG and any RTP-compatible codec|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711, LPCM and any RTP-compatible codec| -|[RTMP clients](#rtmp-clients)|RTMP, RTMPS, Enhanced RTMP|AV1, VP9, H265, H264|MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3)| +|[WebRTC clients](#webrtc-clients)|Browser-based, WHIP|AV1, VP9, VP8, H264|Opus, G722, G711 (PCMA, PCMU)| +|[WebRTC servers](#webrtc-servers)|WHEP|AV1, VP9, VP8, H264|Opus, G722, G711 (PCMA, PCMU)| +|[RTSP clients](#rtsp-clients)|UDP, TCP, RTSPS|AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG and any RTP-compatible codec|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM and any RTP-compatible codec| +|[RTSP cameras and servers](#rtsp-cameras-and-servers)|UDP, UDP-Multicast, TCP, RTSPS|AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG and any RTP-compatible codec|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM and any RTP-compatible codec| +|[RTMP clients](#rtmp-clients)|RTMP, RTMPS, Enhanced RTMP|AV1, VP9, H265, H264|MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), G711 (PCMA, PCMU), LPCM| |[RTMP cameras and servers](#rtmp-cameras-and-servers)|RTMP, RTMPS, Enhanced RTMP|H264|MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3)| |[HLS cameras and servers](#hls-cameras-and-servers)|Low-Latency HLS, MP4-based HLS, legacy HLS|AV1, VP9, H265, H264|Opus, MPEG-4 Audio (AAC)| |[UDP/MPEG-TS](#udpmpeg-ts)|Unicast, broadcast, multicast|H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3| @@ -37,11 +37,18 @@ And can be read from the server with: |protocol|variants|video codecs|audio codecs| |--------|--------|------------|------------| |[SRT](#srt)||H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3| -|[WebRTC](#webrtc)|Browser-based, WHEP|AV1, VP9, VP8, H264|Opus, G722, G711| -|[RTSP](#rtsp)|UDP, UDP-Multicast, TCP, RTSPS|AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG and any RTP-compatible codec|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711, LPCM and any RTP-compatible codec| +|[WebRTC](#webrtc)|Browser-based, WHEP|AV1, VP9, VP8, H264|Opus, G722, G711 (PCMA, PCMU)| +|[RTSP](#rtsp)|UDP, UDP-Multicast, TCP, RTSPS|AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG and any RTP-compatible codec|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM and any RTP-compatible codec| |[RTMP](#rtmp)|RTMP, RTMPS, Enhanced RTMP|H264|MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3)| |[HLS](#hls)|Low-Latency HLS, MP4-based HLS, legacy HLS|AV1, VP9, H265, H264|Opus, MPEG-4 Audio (AAC)| +And can be recorded with: + +|format|video codecs|audio codecs| +|------|------------|------------| +|[fMP4](#record-streams-to-disk)|AV1, VP9, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G711 (PCMA, PCMU), LPCM| +|[MPEG-TS](#record-streams-to-disk)|H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3| + **Features** * Publish live streams to the server @@ -49,6 +56,7 @@ And can be read from the server with: * Streams are automatically converted from a protocol to another * Serve multiple streams at once in separate paths * Record streams to disk +* Playback recordings * Authenticate users; use internal or external authentication * Redirect readers to other RTSP servers (load balancing) * Query and control the server through the API @@ -67,7 +75,7 @@ _rtsp-simple-server_ has been rebranded as _MediaMTX_. The reason is pretty obvi * [Standalone binary](#standalone-binary) * [Docker image](#docker-image) * [Arch Linux package](#arch-linux-package) - * [OpenWRT package](#openwrt-package) + * [OpenWrt binary](#openwrt-binary) * [Basic usage](#basic-usage) * [Publish to the server](#publish-to-the-server) * [By software](#by-software) @@ -108,32 +116,44 @@ _rtsp-simple-server_ has been rebranded as _MediaMTX_. The reason is pretty obvi * [Encrypt the configuration](#encrypt-the-configuration) * [Remuxing, re-encoding, compression](#remuxing-re-encoding-compression) * [Record streams to disk](#record-streams-to-disk) - * [Forward streams to another server](#forward-streams-to-another-server) + * [Playback recordings](#playback-recordings) + * [Forward streams to other servers](#forward-streams-to-other-servers) + * [Proxy requests to other servers](#proxy-requests-to-other-servers) * [On-demand publishing](#on-demand-publishing) * [Start on boot](#start-on-boot) + * [Linux](#linux) + * [OpenWrt](#openwrt) + * [Windows](#windows) * [Hooks](#hooks) * [API](#api) * [Metrics](#metrics) * [pprof](#pprof) + * [SRT-specific features](#srt-specific-features) + * [Standard stream ID syntax](#standard-stream-id-syntax) + * [WebRTC-specific features](#webrtc-specific-features) + * [Connectivity issues](#connectivity-issues) * [RTSP-specific features](#rtsp-specific-features) * [Transport protocols](#transport-protocols) * [Encryption](#encryption) * [Corrupted frames](#corrupted-frames) * [RTMP-specific features](#rtmp-specific-features) * [Encryption](#encryption-1) - * [WebRTC-specific features](#webrtc-specific-features) - * [Connectivity issues](#connectivity-issues) * [Compile from source](#compile-from-source) + * [Standard](#standard) + * [Raspberry Pi](#raspberry-pi) + * [OpenWrt](#openwrt-1) + * [Cross compile](#cross-compile) + * [Compile for all supported platforms](#compile-for-all-supported-platforms) * [Specifications](#specifications) * [Related projects](#related-projects) ## Installation -There are several installation methods available: standalone binary, Docker image, Arch Linux package and OpenWRT package. +There are several installation methods available: standalone binary, Docker image, Arch Linux package and OpenWrt binary. ### Standalone binary -1. Download and extract a standalone binary from the [release page](https://github.com/bluenviron/mediamtx/releases). +1. Download and extract a standalone binary from the [release page](https://github.com/bluenviron/mediamtx/releases) that corresponds to your operating system and architecture. 2. Start the server: @@ -163,14 +183,18 @@ The `--network=host` flag is mandatory since Docker can change the source port o ``` docker run --rm -it \ -e MTX_PROTOCOLS=tcp \ +-e MTX_WEBRTCADDITIONALHOSTS=192.168.x.x \ -p 8554:8554 \ -p 1935:1935 \ -p 8888:8888 \ -p 8889:8889 \ -p 8890:8890/udp \ +-p 8189:8189/udp \ bluenviron/mediamtx ``` +set `MTX_WEBRTCADDITIONALHOSTS` to your local IP address. + ### Arch Linux package If you are running the Arch Linux distribution, run: @@ -181,39 +205,11 @@ cd mediamtx makepkg -si ``` -### OpenWRT package +### OpenWrt binary -1. In a x86 Linux system, download the OpenWRT SDK corresponding to the wanted OpenWRT version and target from the [OpenWRT website](https://downloads.openwrt.org/releases/) and extract it. +If the architecture of the OpenWrt device is amd64, armv6, armv7 or arm64, use the [standalone binary method](#standalone-binary) and download a Linux binary that corresponds to your architecture. -2. Open a terminal in the SDK folder and setup the SDK: - - ```sh - ./scripts/feeds update -a - ./scripts/feeds install -a - make defconfig - ``` - -3. Download the server Makefile and set the server version inside the file: - - ```sh - mkdir package/mediamtx - wget -O package/mediamtx/Makefile https://raw.githubusercontent.com/bluenviron/mediamtx/main/openwrt.mk - sed -i "s/v0.0.0/$(git ls-remote --tags --sort=v:refname https://github.com/bluenviron/mediamtx | tail -n1 | sed 's/.*\///; s/\^{}//')/" package/mediamtx/Makefile - ``` - -4. Compile the server: - - ```sh - make package/mediamtx/compile -j$(nproc) - ``` - -5. Transfer the .ipk file from `bin/packages/*/base` to the OpenWRT system - -6. Install it with: - - ```sh - opkg install [ipk-file-name].ipk - ``` +Otherwise, [compile the server from source](#openwrt-1). ## Basic usage @@ -424,7 +420,7 @@ This web page can be embedded into another web page by using an iframe: ``` -For more advanced setups, you can create and serve a custom web page by starting from the [source code of the publish page](internal/core/webrtc_publish_index.html). +For more advanced setups, you can create and serve a custom web page by starting from the [source code of the publish page](internal/servers/webrtc/publish_index.html). ### By device @@ -495,6 +491,8 @@ docker run --rm -it \ bluenviron/mediamtx:latest-rpi ``` +Be aware that the Docker image is not compatible with cameras that requires a custom `libcamera` (like some ArduCam products), since it comes with a standard `libcamera` included. + Camera settings can be changed by using the `rpiCamera*` parameters: ```yml @@ -565,6 +563,8 @@ If credentials are enabled, append username and password to `streamid`; srt://localhost:8890?streamid=publish:mystream:user:pass&pkt_size=1316 ``` +If you need to use the standard stream ID syntax instead of the custom one in use by this server, see [Standard stream ID syntax](#standard-stream-id-syntax). + If you want to publish a stream by using a client in listening mode (i.e. with `mode=listener` appended to the URL), read the next section. Known clients that can publish with SRT are [FFmpeg](#ffmpeg), [GStreamer](#gstreamer), [OBS Studio](#obs-studio). @@ -636,7 +636,7 @@ paths: The resulting stream will be available in path `/proxied`. -The server supports any number of source streams (count is just limited by hardware capability) it's enough to add additional entries to the paths section: +The server supports any number of source streams (count is just limited by available hardware resources) it's enough to add additional entries to the paths section: ```yml paths: @@ -781,8 +781,6 @@ In order to use the UDP-multicast transport protocol, append `?vlcmulticast` to vlc --network-caching=50 rtsp://localhost:8554/mystream?vlcmulticast ``` -You can change the transport protocol by using the `--rtsp_` flag: - ##### Ubuntu bug The VLC shipped with Ubuntu 21.10 doesn't support playing RTSP due to a license issue (see [here](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=982299) and [here](https://stackoverflow.com/questions/69766748/cvlc-cannot-play-rtsp-omxplayer-instead-can)). To fix the issue, remove the default VLC instance and install the snap version: @@ -812,7 +810,7 @@ This web page can be embedded into another web page by using an iframe: ``` -For more advanced setups, you can create and serve a custom web page by starting from the [source code of the read page](internal/core/webrtc_read_index.html). +For more advanced setups, you can create and serve a custom web page by starting from the [source code of the read page](internal/servers/webrtc/read_index.html). Web browsers can also read a stream with the [HLS protocol](#hls). Latency is higher but there are less problems related to connectivity between server and clients, furthermore the server load can be balanced by using a common HTTP CDN (like CloudFront or Cloudflare), and this allows to handle readers in the order of millions. Visit the web page: @@ -841,9 +839,11 @@ Replace `mystream` with the path name. If credentials are enabled, append username and password to `streamid`; ``` -srt://localhost:8890?streamid=publish:mystream:user:pass +srt://localhost:8890?streamid=read:mystream:user:pass ``` +If you need to use the standard stream ID syntax instead of the custom one in use by this server, see [Standard stream ID syntax](#standard-stream-id-syntax). + Known clients that can read with SRT are [FFmpeg](#ffmpeg-1), [GStreamer](#gstreamer-1) and [VLC](#vlc). #### WebRTC @@ -876,7 +876,7 @@ Known clients that can read with RTSP are [FFmpeg](#ffmpeg-1), [GStreamer](#gstr ##### Latency -The RTSP protocol doesn't introduce any latency by itself. Latency is usually introduced by clients, that put frames in a buffer to compensate network fluctuations. In order to decrease latency, the best way consists in tuning the client. For instance, latency can be decreased with VLC by decreasing the Network caching parameter, that is available in the Open network stream dialog or alternatively ca be set with the command line: +The RTSP protocol doesn't introduce any latency by itself. Latency is usually introduced by clients, that put frames in a buffer to compensate network fluctuations. In order to decrease latency, the best way consists in tuning the client. For instance, in VLC, latency can be decreased by decreasing the Network caching parameter, that is available in the "Open network stream" dialog or alternatively can be set with the command line: ``` vlc --network-caching=50 rtsp://... @@ -884,7 +884,7 @@ vlc --network-caching=50 rtsp://... #### RTMP -RTMP is a protocol that allows to read and publish streams, but is less versatile and less efficient than RTSP and WebRTC ((doesn't support UDP, doesn't support most RTSP codecs, doesn't support feedback mechanism)). Streams can be read from the server by using the URL: +RTMP is a protocol that allows to read and publish streams, but is less versatile and less efficient than RTSP and WebRTC (doesn't support UDP, doesn't support most RTSP codecs, doesn't support feedback mechanism). Streams can be read from the server by using the URL: ``` rtmp://localhost/mystream @@ -1003,7 +1003,7 @@ There are 3 ways to change the configuration: MTX_RTSPADDRESS="127.0.0.1:8554" ./mediamtx ``` - Parameters that have array as value can be overriden by setting a comma-separated list. For example: + Parameters that have array as value can be overridden by setting a comma-separated list. For example: ``` MTX_PROTOCOLS="tcp,udp" @@ -1025,13 +1025,12 @@ There are 3 ways to change the configuration: ### Authentication -Edit `mediamtx.yml` and replace everything inside section `paths` with the following content: +Edit `mediamtx.yml` and set `publishUser` and `publishPass`: ```yml -paths: - all: - publishUser: myuser - publishPass: mypass +pathDefaults: + publishUser: myuser + publishPass: mypass ``` Only publishers that provide both username and password will be able to proceed: @@ -1043,28 +1042,39 @@ ffmpeg -re -stream_loop -1 -i file.ts -c copy -f rtsp rtsp://myuser:mypass@local It's possible to setup authentication for readers too: ```yml -paths: - all: - publishUser: myuser - publishPass: mypass +pathDefaults: + readUser: myuser + readPass: mypass +``` + +If storing plain credentials in the configuration file is a security problem, username and passwords can be stored as hashed strings. The Argon2 and SHA256 hashing algorithms are supported. + +To use Argon2, the string must be hashed using Argon2id (recommended) or Argon2i: - readUser: user - readPass: userpass +``` +echo -n "mypass" | argon2 saltItWithSalt -id -l 32 -e +``` + +Then stored with the `argon2:` prefix: + +```yml +pathDefaults: + readUser: argon2:$argon2id$v=19$m=4096,t=3,p=1$MTIzNDU2Nzg$OGGO0eCMN0ievb4YGSzvS/H+Vajx1pcbUmtLp2tRqRU + readPass: argon2:$argon2i$v=19$m=4096,t=3,p=1$MTIzNDU2Nzg$oct3kOiFywTdDdt19kT07hdvmsPTvt9zxAUho2DLqZw ``` -If storing plain credentials in the configuration file is a security problem, username and passwords can be stored as sha256-hashed strings; a string must be hashed with sha256 and encoded with base64: +To use SHA256, the string must be hashed with SHA256 and encoded with base64: ``` -echo -n "userpass" | openssl dgst -binary -sha256 | openssl base64 +echo -n "mypass" | openssl dgst -binary -sha256 | openssl base64 ``` Then stored with the `sha256:` prefix: ```yml -paths: - all: - readUser: sha256:j1tsRqDEw9xvq/D7/9tMx6Jh/jMhk3UfjwIB2f1zgMo= - readPass: sha256:BdSWkrdV+ZxFBLUQQY7+7uv9RmiSVA8nrPmjGjJtZQQ= +pathDefaults: + readUser: sha256:j1tsRqDEw9xvq/D7/9tMx6Jh/jMhk3UfjwIB2f1zgMo= + readPass: sha256:BdSWkrdV+ZxFBLUQQY7+7uv9RmiSVA8nrPmjGjJtZQQ= ``` **WARNING**: enable encryption or use a VPN to ensure that no one is intercepting the credentials in transit. @@ -1129,7 +1139,7 @@ To change the format, codec or compression of a stream, use _FFmpeg_ or _GStream ```yml paths: - all: + compressed: original: runOnReady: > ffmpeg -i rtsp://localhost:$RTSP_PORT/$MTX_PATH @@ -1143,20 +1153,18 @@ paths: To save available streams to disk, set the `record` and the `recordPath` parameter in the configuration file: ```yml -# Record streams to disk. -record: yes -# Path of recording segments. -# Extension is added automatically. -# Available variables are %path (path name), %Y %m %d %H %M %S %f (time in strftime format) -recordPath: ./recordings/%path/%Y-%m-%d_%H-%M-%S-%f +pathDefaults: + # Record streams to disk. + record: yes + # Path of recording segments. + # Extension is added automatically. + # Available variables are %path (path name), %Y %m %d %H %M %S %f %s (time in strftime format) + recordPath: ./recordings/%path/%Y-%m-%d_%H-%M-%S-%f ``` All available recording parameters are listed in the [sample configuration file](/mediamtx.yml). -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 +Be aware that not all codecs can be saved with all formats, as described in the compatibility matrix at the beginning of the README. 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): @@ -1171,35 +1179,84 @@ To upload recordings to a remote location, you can use _MediaMTX_ together with 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 + pathDefaults: + # 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 +### Playback recordings + +Recordings can be served to users through a dedicated HTTP server, that can be enabled inside the configuration: + +```yml +playback: yes +playbackAddress: :9996 +``` + +The server can be queried for recordings by using the URL: + +``` +http://localhost:9996/get?path=[mypath]&start=[start_date]&duration=[duration]&format=[format] +``` + +Where: + +* [mypath] is the path name +* [start_date] is the start date in RFC3339 format +* [duration] is the maximum duration of the recording in Golang format (example: 20s, 20h) +* [format] must be fmp4 + +All parameters must be [url-encoded](https://www.urlencoder.org/). + +For instance: + +``` +http://localhost:9996/get?path=stream2&start=2024-01-14T16%3A33%3A17%2B00%3A00&duration=200s&format=fmp4 +``` + +The resulting stream is natively compatible with any browser, therefore its URL can be directly inserted into a \