A small, self-hosted SRT test source for macOS — built to exercise SRT ingest in mimoLive, but useful for testing any SRT receiver.
It streams a looping video file (or a synthetic test pattern) over SRT and fans the
same stream out to multiple simultaneous receivers — something a bare
ffmpeg/srt-live-transmit listener can't do (those are 1:1). It supports both SRT
Listener mode (receivers dial in) and Caller mode (the source dials out to a
receiver), and ships with a small web dashboard to watch connections and start/stop
caller pushes.
ffmpeg (file loop / pattern) ──SRT/MPEG-TS publish──▶ MediaMTX ──SRT listener──▶ N receivers (callers)
- macOS on Apple Silicon
- Homebrew
mediamtx, andffmpegbuilt with libsrt —setup.shinstalls/verifies bothpython3(Command Line Tools) for the dashboard
git clone https://github.com/boinx/srt-test-source.git
cd srt-test-source
./setup.sh # installs mediamtx + ffmpeg(libsrt), checks python3
./run.sh # starts the streamer + dashboardThat's it — a fresh clone streams the bundled sample video (media/test.mp4) on
teststream, plus the synthetic pattern stream. To stream your own clip instead,
point SRC_VIDEO at it in config.env and re-run.
In your receiver (e.g. mimoLive), add an SRT source in Caller mode:
srt://<this-mac-ip>:8890?streamid=read:teststream # the file / test card
srt://<this-mac-ip>:8890?streamid=read:pattern # synthetic moving pattern
run.sh prints the URL with this Mac's LAN IP filled in. Open the same URL from as
many receivers as you like. If your receiver only accepts the standard streamid syntax,
use streamid=#!::m=request,r=teststream.
| Variable | Default | Meaning |
|---|---|---|
SRC_VIDEO |
media/test.mp4 (bundled) |
Source clip for teststream. Missing → a test card is generated. |
SRT_PORT |
8890 |
SRT listener port (receivers connect here). |
API_PORT |
9997 |
MediaMTX control API (loopback only). |
DASH_PORT |
8080 |
Web dashboard (loopback only). |
PATTERN_BITRATE |
3M |
Bitrate of the synthetic pattern stream. |
Set your receiver to SRT Listener on a port, then push to it. Two ways:
One-shot:
./caller.sh <receiver-ip> 9000 # push teststream to that listener (Ctrl-C to stop)Managed (dashboard + CLI) — multiple endpoints, auto-reconnect:
./callers.sh add <receiver-ip> 9000 # push teststream
./callers.sh add <receiver-ip> 9000 pattern 200 # push pattern, latency 200ms
./callers.sh list
./callers.sh rm 1
./callers.sh clearEach push pulls a running stream from MediaMTX and forwards it (stream-copy) to the remote listener, and auto-reconnects if the receiver isn't up yet or restarts.
Open http://127.0.0.1:8080 (started by run.sh, or run ./dashboard.sh alone).
It polls every 2s and shows:
- Incoming SRT connections — every reader/publisher with remote IP, path, and bytes.
- Outgoing caller pushes — start one from the form, watch its state, stop it.
MediaMTX has no built-in dashboard; this is a tiny stdlib-Python server (control.py)
on top of its control API.
By default the dashboard runs only while its terminal is open. To start the streamer + dashboard at login and keep them alive:
./setup.sh --service # or: ./service.sh install
./service.sh uninstall # to remove- Multi-receiver fan-out needs a media server. MediaMTX is the SRT listener; the ffmpeg generators publish into it over SRT/MPEG-TS, and it duplicates the stream to every reader. A lone ffmpeg listener only accepts one caller.
- IPv4 binding. MediaMTX is pinned to
0.0.0.0on purpose: a bare:portbinds IPv6-only on macOS, and IPv4 receivers then can't reach it (the SRT handshake fails silently). If a connection fails with nothing in the log, checklsof -nP -iUDP:8890showsIPv4. - MP4 → MPEG-TS. The source is remuxed to a
.ts(in~/.cache/srt-test-source/) and stream-copied: an.mp4/.movpaces badly underffmpeg -re(drifts to ~0.66× real time), while a.tscopy holds 1.0× and preserves the original video and audio. - Firewall. If macOS's firewall is on, allow
mediamtx(andffmpegfor caller mode) to accept/make connections, or other machines can't reach the streams.
| File | Purpose |
|---|---|
setup.sh |
Install/verify dependencies (--service also installs the launchd service). |
run.sh |
Start streamer + dashboard together. |
start.sh |
Build the .ts, render the config, run MediaMTX (streamer only). |
dashboard.sh |
Run the control server + web dashboard. |
caller.sh |
One-shot caller-mode push. |
callers.sh |
CLI for managed caller pushes (add/list/rm/clear). |
control.py |
Dashboard + caller-push manager (stdlib Python). |
config.env |
User settings. |
mediamtx.yml.tmpl |
MediaMTX config template (rendered by start.sh). |
service.sh |
Install/remove the always-on launchd service. |
media/test.mp4 |
Bundled sample clip — the default teststream source. |
MIT — see LICENSE.