MediaMTX

Ready-to-use media server and RTSP/WebRTC proxy

Video Surveillance ★ 20.2k stars Easy setup MIT

MediaMTX, formerly rtsp-simple-server, is a ready-to-use media server and proxy that lets you publish and read live video streams over RTSP, RTMP, HLS, and WebRTC. It is commonly used to relay IP camera feeds for surveillance setups.

Key features

  • RTSP, RTMP, HLS, WebRTC support
  • Stream proxying and relaying
  • On-demand publishing
  • Single binary deployment

Pros & cons

Strengths

  • Extremely lightweight
  • Wide protocol support

Trade-offs

  • No recording UI
  • Not a complete NVR

MediaMTX replaces

Last reviewed Aug 26, 2026 · 782 words

Most IP cameras fall over at 2 or 3 simultaneous RTSP clients, and that is the problem MediaMTX solves: it pulls the camera stream once and re-serves it to as many viewers as you like, over RTSP, RTMP, HLS, WebRTC and SRT, from one Go binary that fits comfortably in the 128 MB the catalogue lists. It is not an NVR. There is no motion detection, no timeline, no web UI for recordings, and the project (formerly rtsp-simple-server) is deliberate about that scope. Think of it as the plumbing under a surveillance or streaming setup, and it is the best plumbing available.

One YAML file, one entry per stream

Everything lives in mediamtx.yml. To proxy a camera:

paths:
  garage:
    source: rtsp://admin:[email protected]:554/stream1
    sourceOnDemand: yes

Start the binary or the bluenviron/mediamtx container and the same stream is available as rtsp://server:8554/garage, as HLS at http://server:8888/garage, and as a WebRTC page at http://server:8889/garage that plays in any browser with no plugin. sourceOnDemand means the camera is only contacted while someone is watching, which matters for battery cameras and for cameras that misbehave under a permanent connection. The default listeners are 8554 for RTSP, 1935 for RTMP, 8888 for HLS, 8889 for WebRTC, 8890 for SRT, 9997 for the HTTP API and 9998 for Prometheus metrics; expose only the ones you use.

WebRTC is the feature worth the trouble

HLS is easy and works everywhere but lags by several seconds. WebRTC gives sub-second latency in the browser, which is the difference between "is that the delivery driver" and watching him leave. The catch is NAT. WebRTC negotiates a UDP path, and if the viewer is not on the same network as the server you need UDP 8189 reachable and webrtcAdditionalHosts set to the address viewers will use, or a TURN server. The pragmatic shortcut for a home setup is a mesh VPN: over Tailscale every device is on the same virtual network and WebRTC works with no port forwarding at all.

It records, it just does not manage recordings

Add three lines to a path and MediaMTX writes segmented MP4 to disk:

    record: yes
    recordPath: /recordings/%path/%Y-%m-%d_%H-%M-%S-%f
    recordDeleteAfter: 168h

That gives you 7 days of continuous footage per camera with automatic pruning, and the API can list and serve segments. What you do not get is an interface, events, or object detection. That is the job of Frigate, which is the NVR I would put on top. Note that Frigate bundles go2rtc, a close cousin with heavy overlap; if you run Frigate you may not need MediaMTX at all, and if you need a standalone relay for OBS, a drone feed or a public stream, MediaMTX is the more general tool of the two.

Publishing into it from anything with ffmpeg

Streams do not have to come from cameras. Any encoder can push to a path:

ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://server:8554/live

OBS publishes to rtmp://server:1935/live as a custom server, and Raspberry Pi cameras are supported natively in the ARM builds. That makes it a self-hosted stand-in for a Wowza-style relay for a small event or a private livestream, at a cost of zero.

Add auth before you forward a single port

Out of the box every path is readable and publishable by anyone who can reach the ports, and the API on 9997 controls the server. Fix both before anything is exposed:

authInternalUsers:
  - user: admin
    pass: a-long-password
    permissions:
      - action: publish
      - action: read
      - action: api
  - user: viewer
    pass: another-password
    permissions:
      - action: read
        path: garage

Bind the API to localhost, put the HLS and WebRTC ports behind a reverse proxy with TLS, and treat camera passwords in the config file as the secrets they are. The wider video surveillance category is full of people who forwarded 8554 and found their garage on a search engine for open streams.

What I'd do

MediaMTX in a container on the same box as Frigate or Home Assistant, every camera proxied through it with sourceOnDemand, WebRTC over Tailscale for phone viewing, 7-day rolling recording on the paths that matter, and authInternalUsers set before the first docker compose up. If you only need what Frigate does, use Frigate's built-in go2rtc and skip this. If you need a general-purpose relay that speaks every protocol, this is the one, and at 128 MB there is no reason to run anything heavier.

Compare MediaMTX

2 head-to-head comparisons.

Similar video surveillance apps