Metadata-Version: 2.4
Name: rtsp
Version: 2.0.1
Summary: RTSP/RTMP client and server for Python.
Project-URL: Homepage, https://github.com/dactylroot/rtsp
Project-URL: Repository, https://github.com/dactylroot/rtsp
Project-URL: Changelog, https://github.com/dactylroot/rtsp/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/dactylroot/rtsp/issues
Author: Cory Root
License-Expression: MIT
License-File: LICENSE
Keywords: image,numpy,pillow,rtmp,rtsp,server,stream
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Multimedia :: Video :: Capture
Classifier: Topic :: Multimedia :: Video :: Display
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Networking
Requires-Python: >=3.10
Requires-Dist: av
Requires-Dist: numpy
Requires-Dist: pillow
Description-Content-Type: text/markdown

# RTSP

[![CI](https://github.com/dactylroot/rtsp/actions/workflows/test.yml/badge.svg)](https://github.com/dactylroot/rtsp/actions/workflows/test.yml)
[![codecov](https://codecov.io/gh/dactylroot/rtsp/graph/badge.svg?token=e4d9Fec6D5)](https://codecov.io/gh/dactylroot/rtsp)
[![PyPI version](https://badge.fury.io/py/rtsp.svg)](https://pypi.org/project/rtsp/)
[![PyPI pyversions](https://img.shields.io/pypi/pyversions/rtsp.svg)](https://pypi.org/project/rtsp/)
[![Downloads](https://static.pepy.tech/badge/rtsp)](https://pepy.tech/project/rtsp)
[![Downloads](https://static.pepy.tech/badge/rtsp/month)](https://pepy.tech/project/rtsp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

            /((((((\\\\
    =======((((((((((\\\\\
         ((           \\\\\\\
         ( (*    _/      \\\\\\\
           \    /  \      \\\\\\________________
            |  |   |      </    __             ((\\\\
            o_|   /        ____/ / _______       \ \\\\    \\\\\\\
                 |  ._    / __/ __(_-</ _ \       \ \\\\\\\\\\\\\\\\
                 | /     /_/  \__/___/ .__/       /    \\\\\\\     \\
         .______/\/     /           /_/           /         \\\
        / __.____/    _/         ________(       /\
       / / / ________/`---------'         \     /  \_
      / /  \ \                             \   \ \_  \
     ( <    \ \                             >  /    \ \
      \/      \\_                          / /       > )
               \_|                        / /       / /
                                        _//       _//
                                       /_|       /_|


A Pythonic RTSP client and microserver for video and computer vision work, from rapid prototyping to moderate-weight production. Pull frames from any RTSP stream or local capture device as Pillow images, preview streams in a window, or serve a frame buffer over RTSP with a single context manager. For multi-client distribution, pair it with a [MediaMTX](https://github.com/bluenviron/mediamtx) relay. For performance-intensive pipelines requiring high-throughput encoding or minimal latency, use OpenCV, GStreamer, or FFmpeg directly.

## Features

  * read most-recent RTSP frame as Pillow Image on demand
  * preview stream in a tkinter window. 'q' or ESC to quit.
  * URI shortcuts for rapid prototyping
    * integers (or numeric strings) open a local capture device, e.g. `rtsp.Client(0)`
    * bare host strings default to `rtsp://`, e.g. `rtsp.Client('192.168.1.1/stream')`
    * Raspberry Pi camera: enable the V4L2 driver (`dtoverlay=imx219` or similar in `/boot/config.txt`) and use `rtsp.Client(0)`
  * lightweight RTSP server
  * `rtmp://` and `rtmps://` URIs work with `Client` and `Source` using the same API as RTSP
  * enumerate local capture devices with `rtsp.list_devices()`
 
## Examples

### Client Use

Use RTSP access credentials in your connection string e.g.

    RTSP_URL = f"rtsp://{USERNAME}:{PASSWORD}@192.168.1.221:554/11"

One-off Retrieval

    import rtsp
    client = rtsp.Client(rtsp_server_uri = 'rtsp://...', verbose=True)
    client.read().show()
    client.close()

Stream Preview

    import rtsp
    with rtsp.Client(0) as client: # previews USB webcam 0
        client.preview()

Continuous Retrieval

    import rtsp

    with rtsp.Client(rtsp_server_uri = 'rtsp://...') as client:
        _image = client.read()

        while True:
            process_image(_image)
            _image = client.read(raw=True)

Resize Retrieval Image

    import rtsp

    RTSP_URL = "rtsp://..."
    client = rtsp.Client(rtsp_server_uri = RTSP_URL)

    width = 640
    height = 480

    client.read().resize([width, height]).show()
    client.close()

Rotate Retrieval Image

    import rtsp

    RTSP_URL = "rtsp://..."
    client = rtsp.Client(rtsp_server_uri = RTSP_URL)

    client.read().resize([client.read().size[0], client.read().size[0]]).rotate(90).resize([client.read().size[1], client.read().size[0]]).show()
    client.close()

Save Retrieval Image (With the TimeStamp Format and Set Number of Save Image)

    import rtsp
    import datetime

    RTSP_URL = "rtsp://..."
    IMAGE_COUNT = 10

    client = rtsp.Client(rtsp_server_uri = RTSP_URL)
    while client.isOpened() and IMAGE_COUNT > 0:
        client.read().save("./"+ str(datetime.datetime.now()) +".jpg")
        IMAGE_COUNT = IMAGE_COUNT - 1
    client.close()

### Source Use

Serve frames locally and preview them. `source.client_uri` gives the address
to connect to, and `verbose=True` logs the URI and fps on startup:

    import rtsp

    frames = ['frame1.jpg', 'frame2.jpg', 'frame3.jpg']

    with rtsp.Source('rtsp://0.0.0.0:8554/live', fps=1,
                     frame_buffer=frames, verbose=True) as source:
        with rtsp.Client(source.client_uri) as client:
            client.preview()   # blocks; press q or ESC to quit

Serve without a viewer. `serve_forever()` blocks and loops the buffer
indefinitely until Ctrl-C:

    import rtsp

    frames = ['frame1.jpg', 'frame2.jpg', 'frame3.jpg']

    with rtsp.Source('rtsp://0.0.0.0:8554/live', frame_buffer=frames) as source:
        source.serve_forever()   # blocks; Ctrl-C to stop

Multi-client stream via [MediaMTX](https://github.com/bluenviron/mediamtx) relay.
Also, frames can be added incrementally with `put()`:

    # Terminal: ./mediamtx          (listens on :8554 by default)

    import rtsp

    # serve=False pushes to the running MediaMTX relay.
    # Any number of Client() instances can then read from the same URI.
    with rtsp.Source('rtsp://localhost:8554/live', serve=False) as source:
        for frame in incoming_frames():
            source.put(frame)

    # Elsewhere, any number of concurrent readers:
    with rtsp.Client('rtsp://localhost:8554/live') as client:
        client.preview()

