Metadata-Version: 2.4
Name: rtsp-stream
Version: 0.1.0
Summary: Lightweight, thread-based RTSP video stream reader with automatic reconnection.
Author: Nikhil Budaniya
License-Expression: MIT
Project-URL: Homepage, https://github.com/nikhil/rtsp-stream
Project-URL: Repository, https://github.com/nikhil/rtsp-stream
Project-URL: Issues, https://github.com/nikhil/rtsp-stream/issues
Keywords: rtsp,video,stream,opencv,camera,reconnect
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: opencv-python>=4.5
Requires-Dist: numpy>=1.21
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-mock>=3; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"

# rtsp-stream

Lightweight, thread-based RTSP video stream reader with **automatic reconnection** — drop the `VideoCapture` boilerplate and let the library handle feed drops for you.

## Install

```bash
pip install rtsp-stream
```

> **Note:** `opencv-python` is listed as a dependency. If your project already uses `opencv-contrib-python` or a headless variant, install with `--no-deps` and manage OpenCV separately.

## Quick start

```python
from rtsp_stream import VideoStream

stream = VideoStream("rtsp://camera-ip/stream")
stream.start()

while True:
    frame = stream.read()   # returns None until first frame arrives
    if frame is not None:
        # do something with the numpy array
        pass

stream.stop()
```

### Context manager

```python
with VideoStream("rtsp://camera-ip/stream").start() as stream:
    frame = stream.read()
```

---

## Configuration

| Parameter | Type | Default | Description |
|---|---|---|---|
| `rtsp_url` | `str` | — | Any URL accepted by `cv2.VideoCapture` |
| `reconnect_delay` | `float` | `1.0` | Seconds between reconnection attempts |
| `max_reconnect_attempts` | `int \| None` | `None` | Max consecutive attempts before giving up (`None` = forever) |
| `reconnect_backoff` | `float` | `1.0` | Multiply delay by this after each failure (e.g. `2.0` = exponential back-off) |
| `max_reconnect_delay` | `float` | `30.0` | Upper bound on back-off delay |
| `on_connect` | `Callable` | `None` | Called every time a connection succeeds |
| `on_disconnect` | `Callable` | `None` | Called every time the feed drops |
| `on_reconnect_failure` | `Callable` | `None` | Called when `max_reconnect_attempts` is exhausted |
| `cap_backend` | `int` | `cv2.CAP_ANY` | OpenCV backend flag |
| `cap_buffer_size` | `int \| None` | `None` | Sets `CAP_PROP_BUFFERSIZE` right after opening (reduces RTSP latency) |

### Exponential back-off example

```python
stream = VideoStream(
    "rtsp://camera-ip/stream",
    reconnect_delay=1.0,
    reconnect_backoff=2.0,       # 1s → 2s → 4s → 8s …
    max_reconnect_delay=30.0,    # capped at 30s
    max_reconnect_attempts=10,
)
stream.start()
```

### Callbacks

```python
def on_connect():
    print("Camera back online")

def on_disconnect():
    print("Feed dropped — waiting to reconnect")

def on_failure():
    print("Gave up reconnecting")
    # trigger an alert, restart a service, etc.

stream = VideoStream(
    "rtsp://camera-ip/stream",
    on_connect=on_connect,
    on_disconnect=on_disconnect,
    on_reconnect_failure=on_failure,
)
stream.start()
```

---

## Properties

```python
stream.fps            # float
stream.frame_width    # int
stream.frame_height   # int
stream.is_connected   # bool
stream.reconnect_count  # int — total reconnect attempts so far
```

---

## Logging

The library uses Python's standard `logging` module under the `rtsp_stream` logger. To see reconnect events:

```python
import logging
logging.basicConfig(level=logging.INFO)
```

---

## Running tests

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest -q
```

## License

MIT
