easy-rtsp
Python library for ingesting video, transforming frames with NumPy/OpenCV, and republishing over RTSP, RTSPS, or SRT using FFmpeg, with optional MediaMTX for a proper RTSP server and WebRTC browser playback.
Documentation · PyPI · GitHub Wiki
Building an edge computer-vision pipeline? Start with the GStreamer, DeepStream, and Triton integration guide.
Status: early development. See ROADMAP.md for scope and roadmap.
Install
pip install easy-rtsp
For webcam capture, add the OpenCV extra:
pip install "easy-rtsp[webcam]"
Development from a clone:
uv sync --extra dev
Quick usage (Python API)
from easy_rtsp import Stream
# Ingest RTSP
for frame in Stream.open("rtsp://camera/live").frames():
...
# Ingest RTSP from connection parts
relay = Stream.open_rtsp(
"camera.local",
"cam/main",
username="user",
password="secret",
)
# Webcam -> transform -> publish
Stream.from_webcam(0).map(process_frame).serve("live")
# Make it reachable by other devices on the same network
stream = Stream.from_webcam(0, lan_access=True).serve("live")
print(stream.lan_viewer_urls)
# File with options
Stream.from_file("clip.mp4", file_loop=True).serve("live")
# RTSP relay with audio passthrough
relay.serve_rtsp("127.0.0.1", "live", audio_mode="passthrough")
# Wait for shutdown
stream = Stream.from_webcam(0).serve("live")
print(stream.viewer_url)
print(stream.status())
stream.wait()
CLI
Commands:
relay- ingest RTSP/RTSPS and republishwebcam- capture from webcam index (default0)file- publish from a file sourcedoctor- print FFmpeg, ffprobe, MediaMTX, and platform statusinstall-backends- show FFmpeg hints and optionally download MediaMTX--version- print the installed easy-rtsp version
Examples:
easy-rtsp relay rtsp://camera/live --serve live
easy-rtsp webcam 0 --serve live --webrtc
easy-rtsp webcam 0 --serve live --lan
easy-rtsp file input.mp4 --serve demo
easy-rtsp file clip.mp4 --serve live --fps 24 --no-loop
easy-rtsp relay rtsp://cam/live --serve live --record out.mp4 --hls-dir ./hls
easy-rtsp doctor
easy-rtsp --version
easy-rtsp install-backends
Shared --serve flags include endpoint, transport (relay), reconnect options, --server-host / --server-port, --lan, --low-latency-input, --record, --hls-dir, --hls-segment-time, --video-encoder, --audio-mode, --webrtc / --no-webrtc, --webrtc-port, and -v.
Logs go to stderr. Play: and WebRTC: URLs go to stdout. SIGINT is wired so Ctrl+C calls stop() reliably on Windows. CLI commands return a non-zero exit code and print FFmpeg's useful error tail when publishing fails.
Dependencies
| Component | Role |
|---|---|
| FFmpeg / ffprobe | Required on PATH for decode, encode, and publish. |
| MediaMTX | Optional. Without it, loopback publish uses MPEG-TS over TCP (tcp://127.0.0.1:PORT in VLC), not rtsp://. |
| OpenCV | Optional extra webcam: opencv-python-headless for Stream.from_webcam only. |
Download help:
easy-rtsp install-backends
Set EASY_RTSP_MEDIAMTX to the mediamtx executable or add it to PATH after install.
Features
Ingest sources
Stream.open(url)- RTSP or RTSPS URL with configurable reconnect retries.Stream.open_rtsp(host, path=..., username=..., password=...)- helper that builds a safe RTSP/RTSPS URL.Stream.from_webcam(index)- camera via OpenCV.Stream.from_file(path)- file decode; looping uses FFmpeg-stream_loop.Stream.from_frames(factory, fps, size)- synthetic or custom frame iterators (BGRuint8).
Frame processing
stream.map(fn)- per-frame transform; returnNoneto drop a frame. Chaining is supported.
Publishing (serve)
- Shorthand path -
"live"maps tortsp://127.0.0.1:8554/liveusingStreamConfig.server_host/server_port. - Full URLs -
rtsp://,rtsps://, andsrt://. - RTSP query strings and multi-segment paths are preserved; IPv6 literals are bracketed automatically by the URL builders.
audio_mode="passthrough"- relay source audio for RTSP ingest when usingStream.open(...)/Stream.open_rtsp(...)without frame transforms.- Local MediaMTX - easy-rtsp writes a minimal config and starts MediaMTX when possible.
- LAN access - set
lan_access=Trueor pass--lan; easy-rtsp binds MediaMTX to the network and reports ready-to-copy URLs inlan_viewer_urls/ CLI output. - No MediaMTX - FFmpeg listens for one MPEG-TS client over TCP.
- Existing server - FFmpeg pushes RTSP in client mode when something is already listening.
Side outputs
record_path- duplicate stream to MP4.hls_output_dir- HLS output withindex.m3u8and segments.hls_segment_time- optional HLS segment duration.
Encoder / quality
codec/video_encoder- choose H.264 encoder, including hardware encoders.preset-default,low_latency, orquality.bitrate- for example"4M".input_realtime_pace- FFmpeg-repacing for raw sources.
RTSP ingest (relay)
transport-tcporudp.reconnect,retry_interval_sec,max_reconnect_attempts- reconnect policy.on_reconnecting- optional callback(attempt_number).latency_ms- optional ingest hint.
LAN access
Local publishing is loopback-only by default. To watch from VLC or another RTSP client on a phone, TV, or computer connected to the same network:
easy-rtsp webcam 0 --serve live --lan
The CLI prints output such as LAN: rtsp://192.168.1.42:8554/live; open that exact URL on the other device. LAN RTSP requires MediaMTX, uses RTSP-over-TCP so only the selected RTSP TCP port is needed, and is unauthenticated—use it only on a trusted network. If the connection is blocked, allow inbound TCP port 8554 (or your --server-port) for MediaMTX in the host firewall. Client isolation on guest Wi-Fi can also prevent devices from reaching each other.
Add --webrtc for browser playback. The CLI will also print LAN WebRTC: URLs; WebRTC additionally needs TCP 8889 and UDP/TCP 8189 by default.
WebRTC (optional, local MediaMTX)
webrtc_enabled- off by default.webrtc_http_port- signaling port, default8889.- Pair with
lan_access=True/--lanfor automatically reported browser URLs on other devices.
File-specific
file_loop- loop file continuously, defaulttrue.fps- override publish FPS.
Control flow
serve()- starts publish in a background thread.serve_rtsp(host, path=..., username=..., password=...)- convenience wrapper for authenticated RTSP/RTSPS publish URLs.wait()/wait(timeout=...)- block until publish ends.stop()- stop encode/decode FFmpeg children and MediaMTX if started.wait_async()/stop_async()- async wrappers for service environments.latest_frame()- read the latest processed frame.save_snapshot(path)- write the latest processed frame to an image file.status()- get an immutable health snapshot with state, reconnect count, URLs, and error state.- Context manager -
with stream:callsstop()on exit. Stream.state,reconnect_count,viewer_url,webrtc_play_url,lan_viewer_urls,lan_webrtc_play_urls.
Releases
Releases use Git tags plus GitHub Actions:
- Run the Cut Release workflow with a version like
0.2.0, or push a tag manually withgit tag -a v0.2.0 -m "Release v0.2.0" && git push origin v0.2.0. - The Release workflow tests the repo, builds
sdistand wheel, and publishes to PyPI. - Publishing uses PyPI Trusted Publishing, so configure a trusted publisher for this repository, workflow, and environment in PyPI before the first release.
- If this repository does not have a historical release tag yet, create a baseline tag such as
v0.1.0before relying on tag-derived versions for future releases.
Third-party software
easy-rtsp only ships Python code under the license below. At runtime it invokes tools you install yourself; those are separate projects:
| Component | Where to get it | License (summary) |
|---|---|---|
| FFmpeg / ffprobe | ffmpeg.org, FFmpeg legal | Not MIT - typically LGPL 2.1+ or GPL depending on build and enabled codecs; see upstream and your binary's LICENSE / docs. |
| MediaMTX (optional) | bluenviron/mediamtx | MIT |
| OpenCV (Python bindings) | Optional easy-rtsp[webcam] -> opencv-python-headless; opencv.org |
Apache 2.0 |
easy-rtsp install-backends may download a MediaMTX release from GitHub; it does not bundle FFmpeg. Use official FFmpeg builds or your OS package manager and keep their license terms alongside any binaries you redistribute.
License
MIT
Metadata
Release files for easy-rtsp 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| easy_rtsp-0.1.5.tar.gz | 199.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| easy_rtsp-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 248.5 kB
Release files / easy_rtsp-0.1.5.tar.gz
| Download URL | easy_rtsp-0.1.5.tar.gz |
|---|---|
| Size | 199.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b98e4122fba9609ca7e84b0d0eeb0161c494651819bc1bcf15489d2a42445fad
|
|
BLAKE2b-256 checksum How to use checksums |
06adc1b60422229d673bdf1c9bcd2d73c48657d3621d0a86946b1a2a133482d7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / easy_rtsp-0.1.5-py3-none-any.whl
| Download URL | easy_rtsp-0.1.5-py3-none-any.whl |
|---|---|
| Size | 48.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2db4f3441a7b0f3f4bf0cc2411fc810ba94e9c35490fefbab80980c12cd603fb
|
|
BLAKE2b-256 checksum How to use checksums |
316e6b36defae85588c8cefe1e1364ea826e2deb40257052c86776247c2852ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log