Ingest, transform, and re-host video over RTSP with a simple Python API.
Project description
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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file easy_rtsp-0.1.4.tar.gz.
File metadata
- Download URL: easy_rtsp-0.1.4.tar.gz
- Upload date:
- Size: 195.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f860a87b0dee3bfbeef66d7f8535c99795fbd954fef15a86e9138b680fea006
|
|
| MD5 |
f320d51aa01f4ff6f595b8c7f0499fe0
|
|
| BLAKE2b-256 |
60cd9a6da2036c7acebd9dd520656712165c6cb54994bcdc18245acbc8a64d79
|
Provenance
The following attestation bundles were made for easy_rtsp-0.1.4.tar.gz:
Publisher:
release.yml on austinconnor/easy-rtsp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
easy_rtsp-0.1.4.tar.gz -
Subject digest:
7f860a87b0dee3bfbeef66d7f8535c99795fbd954fef15a86e9138b680fea006 - Sigstore transparency entry: 2169981935
- Sigstore integration time:
-
Permalink:
austinconnor/easy-rtsp@348131acbab0783e3722ded9ba4f49ece732d70f -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/austinconnor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@348131acbab0783e3722ded9ba4f49ece732d70f -
Trigger Event:
push
-
Statement type:
File details
Details for the file easy_rtsp-0.1.4-py3-none-any.whl.
File metadata
- Download URL: easy_rtsp-0.1.4-py3-none-any.whl
- Upload date:
- Size: 46.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37a961757a5f7a0ab5dd49dcb8aeb59d2a4e568a2e4886a8f495aa54443ba494
|
|
| MD5 |
ec4949b3733ea13fd852e7431a05a3c0
|
|
| BLAKE2b-256 |
ce512d53953efa65aee8885090156f4ebc6ca68d36e94dfb9c67a307aa837e25
|
Provenance
The following attestation bundles were made for easy_rtsp-0.1.4-py3-none-any.whl:
Publisher:
release.yml on austinconnor/easy-rtsp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
easy_rtsp-0.1.4-py3-none-any.whl -
Subject digest:
37a961757a5f7a0ab5dd49dcb8aeb59d2a4e568a2e4886a8f495aa54443ba494 - Sigstore transparency entry: 2169981951
- Sigstore integration time:
-
Permalink:
austinconnor/easy-rtsp@348131acbab0783e3722ded9ba4f49ece732d70f -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/austinconnor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@348131acbab0783e3722ded9ba4f49ece732d70f -
Trigger Event:
push
-
Statement type: