darvision 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- darvision-1.0.0/.github/workflows/ci.yml +36 -0
- darvision-1.0.0/.vscode/settings.json +11 -0
- darvision-1.0.0/CONTRIBUTING.md +31 -0
- darvision-1.0.0/LICENSE +21 -0
- darvision-1.0.0/PKG-INFO +150 -0
- darvision-1.0.0/README.md +116 -0
- darvision-1.0.0/docs/architecture.md +62 -0
- darvision-1.0.0/docs/quickstart.md +70 -0
- darvision-1.0.0/examples/camera_stream_client.py +22 -0
- darvision-1.0.0/examples/camera_stream_host.py +23 -0
- darvision-1.0.0/examples/minimal_client.py +6 -0
- darvision-1.0.0/examples/minimal_host.py +6 -0
- darvision-1.0.0/pyproject.toml +55 -0
- darvision-1.0.0/src/darvision/__init__.py +10 -0
- darvision-1.0.0/src/darvision/camera/__init__.py +6 -0
- darvision-1.0.0/src/darvision/camera/base.py +59 -0
- darvision-1.0.0/src/darvision/camera/queue.py +55 -0
- darvision-1.0.0/src/darvision/camera/webcam.py +79 -0
- darvision-1.0.0/src/darvision/cli.py +161 -0
- darvision-1.0.0/src/darvision/client/__init__.py +4 -0
- darvision-1.0.0/src/darvision/client/client.py +100 -0
- darvision-1.0.0/src/darvision/config.py +89 -0
- darvision-1.0.0/src/darvision/exceptions.py +38 -0
- darvision-1.0.0/src/darvision/host/__init__.py +4 -0
- darvision-1.0.0/src/darvision/host/host.py +152 -0
- darvision-1.0.0/src/darvision/host/pipeline.py +160 -0
- darvision-1.0.0/src/darvision/plugins/__init__.py +5 -0
- darvision-1.0.0/src/darvision/plugins/base.py +69 -0
- darvision-1.0.0/src/darvision/plugins/manager.py +80 -0
- darvision-1.0.0/src/darvision/protocol/__init__.py +18 -0
- darvision-1.0.0/src/darvision/protocol/messages.py +131 -0
- darvision-1.0.0/src/darvision/rendering/__init__.py +5 -0
- darvision-1.0.0/src/darvision/rendering/base.py +38 -0
- darvision-1.0.0/src/darvision/rendering/opencv.py +99 -0
- darvision-1.0.0/src/darvision/serialization/__init__.py +5 -0
- darvision-1.0.0/src/darvision/serialization/decoder.py +37 -0
- darvision-1.0.0/src/darvision/serialization/encoder.py +45 -0
- darvision-1.0.0/src/darvision/transport/__init__.py +4 -0
- darvision-1.0.0/src/darvision/transport/base.py +53 -0
- darvision-1.0.0/src/darvision/transport/tunnel/__init__.py +4 -0
- darvision-1.0.0/src/darvision/transport/tunnel/base.py +35 -0
- darvision-1.0.0/src/darvision/transport/tunnel/ngrok.py +73 -0
- darvision-1.0.0/src/darvision/transport/websocket.py +153 -0
- darvision-1.0.0/tests/__init__.py +1 -0
- darvision-1.0.0/tests/test_encoder.py +54 -0
- darvision-1.0.0/tests/test_plugin_manager.py +88 -0
- darvision-1.0.0/tests/test_protocol.py +73 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e .[dev]
|
|
28
|
+
|
|
29
|
+
- name: Lint with ruff
|
|
30
|
+
run: ruff check src/
|
|
31
|
+
|
|
32
|
+
- name: Format check with black
|
|
33
|
+
run: black --check src/ tests/
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: pytest tests/ -v --tb=short
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"python.defaultInterpreterPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe",
|
|
3
|
+
"python.analysis.extraPaths": [
|
|
4
|
+
"${workspaceFolder}\\src",
|
|
5
|
+
"${workspaceFolder}\\.venv\\Lib\\site-packages"
|
|
6
|
+
],
|
|
7
|
+
"python.analysis.venvPath": "${workspaceFolder}",
|
|
8
|
+
"python.analysis.venv": ".venv",
|
|
9
|
+
"pyrefly.pythonInterpreter": "${workspaceFolder}\\.venv\\Scripts\\python.exe",
|
|
10
|
+
"pyrefly.projectRoots": ["${workspaceFolder}/src"]
|
|
11
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Contributing to DarVision
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing!
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Fork the repository and clone it.
|
|
8
|
+
2. Create a virtual environment:
|
|
9
|
+
```bash
|
|
10
|
+
python -m venv .venv
|
|
11
|
+
.\.venv\Scripts\pip install -e .[dev]
|
|
12
|
+
```
|
|
13
|
+
3. Run the test suite to make sure everything works:
|
|
14
|
+
```bash
|
|
15
|
+
.\.venv\Scripts\pytest tests/ -v
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Development Guidelines
|
|
19
|
+
|
|
20
|
+
- **No `print()` in library code.** Use Python's `logging` module.
|
|
21
|
+
- **No Base64 for frames.** Binary WebSocket messages only.
|
|
22
|
+
- **New camera sources** must inherit from `CameraSource`.
|
|
23
|
+
- **New AI plugins** must inherit from `DarVisionPlugin`.
|
|
24
|
+
- **New transport implementations** must inherit from `Transport`.
|
|
25
|
+
|
|
26
|
+
## Submitting a Pull Request
|
|
27
|
+
|
|
28
|
+
1. Create a branch: `git checkout -b feature/my-feature`
|
|
29
|
+
2. Make your changes with tests.
|
|
30
|
+
3. Run `ruff check src/` and `black --check src/`.
|
|
31
|
+
4. Open a pull request with a clear description.
|
darvision-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DarVision Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
darvision-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: darvision
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A Python framework that lets any computer stream its webcam to a remote viewer over WebSockets.
|
|
5
|
+
Author: Darshan Kerkar
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: computer-vision,opencv,remote,streaming,webcam,websocket
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Multimedia :: Video
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: click>=8.0.0
|
|
18
|
+
Requires-Dist: fastapi>=0.100.0
|
|
19
|
+
Requires-Dist: numpy>=1.24.0
|
|
20
|
+
Requires-Dist: opencv-python>=4.8.0
|
|
21
|
+
Requires-Dist: pillow>=10.0.0
|
|
22
|
+
Requires-Dist: pydantic>=2.0.0
|
|
23
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
24
|
+
Requires-Dist: uvicorn[standard]>=0.23.0
|
|
25
|
+
Requires-Dist: websockets>=11.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
31
|
+
Provides-Extra: ngrok
|
|
32
|
+
Requires-Dist: pyngrok>=7.0.0; extra == 'ngrok'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# DarVision
|
|
36
|
+
|
|
37
|
+
> **Stream any webcam to you — from anywhere in the world.**
|
|
38
|
+
>
|
|
39
|
+
> Created by [Darshan Kerkar](https://pypi.org/user/darshan-kerkar/)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## What is DarVision?
|
|
44
|
+
|
|
45
|
+
DarVision is a Python framework that turns any computer into a webcam streaming server.
|
|
46
|
+
|
|
47
|
+
The person on the **other side of the world** installs DarVision, runs one command, and their webcam is live. **You connect and watch.**
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Their Computer Your Computer (Darshan)
|
|
51
|
+
────────────── ───────────────────────
|
|
52
|
+
pip install darvision
|
|
53
|
+
darvision host --public ──► darvision connect wss://xxxx.ngrok-free.app
|
|
54
|
+
(their webcam streams) (you watch their stream)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install darvision
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
With ngrok (for public streaming over the Internet):
|
|
66
|
+
```bash
|
|
67
|
+
pip install darvision[ngrok]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
### They host — you watch
|
|
75
|
+
|
|
76
|
+
**Step 1 — Remote person (the host):**
|
|
77
|
+
```bash
|
|
78
|
+
pip install darvision[ngrok]
|
|
79
|
+
darvision host --public
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
They will see:
|
|
83
|
+
```
|
|
84
|
+
──────────────────────────────────────────────────
|
|
85
|
+
🎥 DarVision Host is running
|
|
86
|
+
──────────────────────────────────────────────────
|
|
87
|
+
Local : ws://192.168.x.x:8765
|
|
88
|
+
Public : wss://abcd1234.ngrok-free.app
|
|
89
|
+
──────────────────────────────────────────────────
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Step 2 — They send you the `wss://` URL.**
|
|
93
|
+
|
|
94
|
+
**Step 3 — You connect (Darshan):**
|
|
95
|
+
```bash
|
|
96
|
+
darvision connect wss://abcd1234.ngrok-free.app
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
A window opens showing their live webcam.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Local preview (host can see their own stream)
|
|
104
|
+
```bash
|
|
105
|
+
darvision host --preview
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### Health check
|
|
111
|
+
```bash
|
|
112
|
+
darvision doctor
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Python API
|
|
118
|
+
|
|
119
|
+
**Host (remote machine):**
|
|
120
|
+
```python
|
|
121
|
+
from darvision import Host
|
|
122
|
+
Host().start()
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Client (your machine):**
|
|
126
|
+
```python
|
|
127
|
+
from darvision import Client
|
|
128
|
+
Client().connect("wss://abcd1234.ngrok-free.app")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Roadmap
|
|
134
|
+
|
|
135
|
+
| Version | Feature |
|
|
136
|
+
|---------|---------|
|
|
137
|
+
| v1.0 | ✅ Webcam streaming over LAN / Internet |
|
|
138
|
+
| v1.1 | Camera source abstraction (video files, RTSP) |
|
|
139
|
+
| v1.2 | MediaPipe Pose plugin |
|
|
140
|
+
| v1.3 | Hand tracking plugin |
|
|
141
|
+
| v1.4 | YOLO object detection plugin |
|
|
142
|
+
| v1.5 | OCR plugin |
|
|
143
|
+
| v2.0 | Multi-client, browser viewer, recording |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Author
|
|
148
|
+
|
|
149
|
+
**Darshan Kerkar**
|
|
150
|
+
MIT License
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# DarVision
|
|
2
|
+
|
|
3
|
+
> **Stream any webcam to you — from anywhere in the world.**
|
|
4
|
+
>
|
|
5
|
+
> Created by [Darshan Kerkar](https://pypi.org/user/darshan-kerkar/)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What is DarVision?
|
|
10
|
+
|
|
11
|
+
DarVision is a Python framework that turns any computer into a webcam streaming server.
|
|
12
|
+
|
|
13
|
+
The person on the **other side of the world** installs DarVision, runs one command, and their webcam is live. **You connect and watch.**
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Their Computer Your Computer (Darshan)
|
|
17
|
+
────────────── ───────────────────────
|
|
18
|
+
pip install darvision
|
|
19
|
+
darvision host --public ──► darvision connect wss://xxxx.ngrok-free.app
|
|
20
|
+
(their webcam streams) (you watch their stream)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install darvision
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
With ngrok (for public streaming over the Internet):
|
|
32
|
+
```bash
|
|
33
|
+
pip install darvision[ngrok]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### They host — you watch
|
|
41
|
+
|
|
42
|
+
**Step 1 — Remote person (the host):**
|
|
43
|
+
```bash
|
|
44
|
+
pip install darvision[ngrok]
|
|
45
|
+
darvision host --public
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
They will see:
|
|
49
|
+
```
|
|
50
|
+
──────────────────────────────────────────────────
|
|
51
|
+
🎥 DarVision Host is running
|
|
52
|
+
──────────────────────────────────────────────────
|
|
53
|
+
Local : ws://192.168.x.x:8765
|
|
54
|
+
Public : wss://abcd1234.ngrok-free.app
|
|
55
|
+
──────────────────────────────────────────────────
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Step 2 — They send you the `wss://` URL.**
|
|
59
|
+
|
|
60
|
+
**Step 3 — You connect (Darshan):**
|
|
61
|
+
```bash
|
|
62
|
+
darvision connect wss://abcd1234.ngrok-free.app
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
A window opens showing their live webcam.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### Local preview (host can see their own stream)
|
|
70
|
+
```bash
|
|
71
|
+
darvision host --preview
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### Health check
|
|
77
|
+
```bash
|
|
78
|
+
darvision doctor
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Python API
|
|
84
|
+
|
|
85
|
+
**Host (remote machine):**
|
|
86
|
+
```python
|
|
87
|
+
from darvision import Host
|
|
88
|
+
Host().start()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Client (your machine):**
|
|
92
|
+
```python
|
|
93
|
+
from darvision import Client
|
|
94
|
+
Client().connect("wss://abcd1234.ngrok-free.app")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Roadmap
|
|
100
|
+
|
|
101
|
+
| Version | Feature |
|
|
102
|
+
|---------|---------|
|
|
103
|
+
| v1.0 | ✅ Webcam streaming over LAN / Internet |
|
|
104
|
+
| v1.1 | Camera source abstraction (video files, RTSP) |
|
|
105
|
+
| v1.2 | MediaPipe Pose plugin |
|
|
106
|
+
| v1.3 | Hand tracking plugin |
|
|
107
|
+
| v1.4 | YOLO object detection plugin |
|
|
108
|
+
| v1.5 | OCR plugin |
|
|
109
|
+
| v2.0 | Multi-client, browser viewer, recording |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Author
|
|
114
|
+
|
|
115
|
+
**Darshan Kerkar**
|
|
116
|
+
MIT License
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# DarVision Architecture
|
|
2
|
+
|
|
3
|
+
## Pipeline Overview
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
Camera Source (Thread 1)
|
|
7
|
+
│
|
|
8
|
+
FrameQueue (bounded, drop-oldest)
|
|
9
|
+
│
|
|
10
|
+
Plugin Manager (Thread 2)
|
|
11
|
+
│
|
|
12
|
+
FrameEncoder (JPEG → binary)
|
|
13
|
+
│
|
|
14
|
+
Transport.send_bytes() ─── asyncio event loop (Thread 3)
|
|
15
|
+
│
|
|
16
|
+
Internet / LAN
|
|
17
|
+
│
|
|
18
|
+
Transport.on_bytes() ─── asyncio event loop
|
|
19
|
+
│
|
|
20
|
+
FrameDecoder (binary → numpy)
|
|
21
|
+
│
|
|
22
|
+
Renderer (Thread 4)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Key Design Decisions
|
|
26
|
+
|
|
27
|
+
### Binary WebSocket (no Base64)
|
|
28
|
+
Frames are sent as raw JPEG bytes prefixed with a small JSON header.
|
|
29
|
+
This is ~33% smaller and faster than Base64-encoded JSON.
|
|
30
|
+
|
|
31
|
+
### Bounded FrameQueue
|
|
32
|
+
The camera never blocks on a slow network. When the queue is full,
|
|
33
|
+
the oldest frame is dropped. This keeps latency low under load.
|
|
34
|
+
|
|
35
|
+
### Abstract Interfaces
|
|
36
|
+
Every major component is behind an interface:
|
|
37
|
+
- `CameraSource` — swap webcam/video/RTSP
|
|
38
|
+
- `Transport` — swap WebSocket/WebRTC/Cloudflare
|
|
39
|
+
- `TunnelProvider` — swap ngrok/Cloudflare Tunnel
|
|
40
|
+
- `Renderer` — swap OpenCV/Qt/Browser
|
|
41
|
+
- `DarVisionPlugin` — add any AI model
|
|
42
|
+
|
|
43
|
+
### Thread Model
|
|
44
|
+
| Thread | Responsibility |
|
|
45
|
+
|--------|---------------|
|
|
46
|
+
| Camera | Read frames from hardware |
|
|
47
|
+
| Plugin | Process frames through AI plugins |
|
|
48
|
+
| Network | asyncio event loop (send/receive) |
|
|
49
|
+
| Renderer | Display frames in GUI window |
|
|
50
|
+
|
|
51
|
+
## Protocol Wire Format
|
|
52
|
+
|
|
53
|
+
Binary frame message:
|
|
54
|
+
```
|
|
55
|
+
[4 bytes: header length (big-endian uint32)]
|
|
56
|
+
[N bytes: JSON header]
|
|
57
|
+
[M bytes: raw JPEG]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
JSON header contains: `version`, `type`, `timestamp`, `width`, `height`, `size`.
|
|
61
|
+
|
|
62
|
+
Text messages (heartbeat, events): plain JSON.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# DarVision Quickstart
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install darvision
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
With ngrok tunnel support:
|
|
10
|
+
```bash
|
|
11
|
+
pip install darvision[ngrok]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Stream your webcam over LAN
|
|
15
|
+
|
|
16
|
+
**On the host machine:**
|
|
17
|
+
```bash
|
|
18
|
+
darvision host
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
You'll see:
|
|
22
|
+
```
|
|
23
|
+
──────────────────────────────────────────────────
|
|
24
|
+
🎥 DarVision Host is running
|
|
25
|
+
──────────────────────────────────────────────────
|
|
26
|
+
Local : ws://192.168.1.15:8765
|
|
27
|
+
Public : (use --public to enable ngrok tunnel)
|
|
28
|
+
──────────────────────────────────────────────────
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**On the client machine:**
|
|
32
|
+
```bash
|
|
33
|
+
darvision connect ws://192.168.1.15:8765
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A window will pop up showing the host's webcam feed in real time. Press `q` to quit.
|
|
37
|
+
|
|
38
|
+
## Stream over the Internet (ngrok)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
darvision host --public
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This starts an ngrok tunnel and prints a public URL:
|
|
45
|
+
```
|
|
46
|
+
Public : wss://abcd1234.ngrok-free.app
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The client can then connect from anywhere:
|
|
50
|
+
```bash
|
|
51
|
+
darvision connect wss://abcd1234.ngrok-free.app
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Python API
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from darvision import Host, Client
|
|
58
|
+
|
|
59
|
+
# Host
|
|
60
|
+
Host().start()
|
|
61
|
+
|
|
62
|
+
# Client
|
|
63
|
+
Client().connect("ws://192.168.1.15:8765")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Check your setup
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
darvision doctor
|
|
70
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
camera_stream_client.py — Connect to a DarVision host and display its webcam.
|
|
3
|
+
|
|
4
|
+
Run this after starting the host:
|
|
5
|
+
.\.venv\Scripts\python examples\camera_stream_client.py ws://localhost:8765
|
|
6
|
+
|
|
7
|
+
Or with a public ngrok URL:
|
|
8
|
+
.\.venv\Scripts\python examples\camera_stream_client.py wss://xxxx.ngrok-free.app
|
|
9
|
+
|
|
10
|
+
Press 'q' in the video window to exit.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
from darvision import Client
|
|
15
|
+
from darvision.config import setup_logging
|
|
16
|
+
|
|
17
|
+
setup_logging("INFO")
|
|
18
|
+
|
|
19
|
+
address = sys.argv[1] if len(sys.argv) > 1 else "ws://localhost:8765"
|
|
20
|
+
|
|
21
|
+
client = Client()
|
|
22
|
+
client.connect(address)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
camera_stream_host.py — Start the DarVision host (local LAN streaming).
|
|
3
|
+
|
|
4
|
+
Run this on the machine that has the webcam:
|
|
5
|
+
.\.venv\Scripts\python examples\camera_stream_host.py
|
|
6
|
+
|
|
7
|
+
Then on a second machine (or terminal), run:
|
|
8
|
+
.\.venv\Scripts\darvision connect ws://<your-ip>:8765
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from darvision import Host
|
|
12
|
+
from darvision.config import DarVisionConfig, setup_logging
|
|
13
|
+
|
|
14
|
+
setup_logging("INFO")
|
|
15
|
+
|
|
16
|
+
cfg = DarVisionConfig()
|
|
17
|
+
cfg.camera.width = 640
|
|
18
|
+
cfg.camera.height = 480
|
|
19
|
+
cfg.camera.fps = 30
|
|
20
|
+
cfg.network.port = 8765
|
|
21
|
+
|
|
22
|
+
host = Host(config=cfg)
|
|
23
|
+
host.start()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "darvision"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "A Python framework that lets any computer stream its webcam to a remote viewer over WebSockets."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Darshan Kerkar" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["computer-vision", "webcam", "streaming", "websocket", "opencv", "remote"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Topic :: Multimedia :: Video",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Image Processing",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
dependencies = [
|
|
27
|
+
"opencv-python>=4.8.0",
|
|
28
|
+
"numpy>=1.24.0",
|
|
29
|
+
"fastapi>=0.100.0",
|
|
30
|
+
"uvicorn[standard]>=0.23.0",
|
|
31
|
+
"websockets>=11.0",
|
|
32
|
+
"click>=8.0.0",
|
|
33
|
+
"pydantic>=2.0.0",
|
|
34
|
+
"Pillow>=10.0.0",
|
|
35
|
+
"PyYAML>=6.0.0",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.optional-dependencies]
|
|
39
|
+
ngrok = ["pyngrok>=7.0.0"]
|
|
40
|
+
dev = [
|
|
41
|
+
"pytest>=7.0.0",
|
|
42
|
+
"pytest-asyncio>=0.21.0",
|
|
43
|
+
"ruff>=0.1.0",
|
|
44
|
+
"black>=23.0.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.scripts]
|
|
48
|
+
darvision = "darvision.cli:cli"
|
|
49
|
+
|
|
50
|
+
[tool.hatch.build.targets.wheel]
|
|
51
|
+
packages = ["src/darvision"]
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
testpaths = ["tests"]
|
|
55
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DarVision — Real-time computer vision streaming framework.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from darvision.host.host import Host
|
|
6
|
+
from darvision.client.client import Client
|
|
7
|
+
from darvision.plugins.base import DarVisionPlugin
|
|
8
|
+
|
|
9
|
+
__version__ = "1.0.0"
|
|
10
|
+
__all__ = ["Host", "Client", "DarVisionPlugin", "__version__"]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Abstract camera source interface.
|
|
3
|
+
All camera implementations must inherit from CameraSource.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CameraSource(ABC):
|
|
13
|
+
"""
|
|
14
|
+
Abstract base class for all DarVision camera sources.
|
|
15
|
+
|
|
16
|
+
Supported sources (v1: WebcamSource only):
|
|
17
|
+
- WebcamSource — USB or built-in webcam via OpenCV
|
|
18
|
+
- VideoSource — video file (future v1.1)
|
|
19
|
+
- RTSPSource — IP/RTSP camera (future v1.1)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def open(self) -> None:
|
|
24
|
+
"""Open and initialize the camera source. Raises CameraError on failure."""
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def read(self) -> Optional[np.ndarray]:
|
|
29
|
+
"""
|
|
30
|
+
Read the next frame.
|
|
31
|
+
Returns a BGR numpy array, or None if no frame is available.
|
|
32
|
+
"""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def close(self) -> None:
|
|
37
|
+
"""Release the camera source and any associated resources."""
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def is_open(self) -> bool:
|
|
43
|
+
"""True if the source is currently open and ready to read."""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
@abstractmethod
|
|
48
|
+
def width(self) -> int:
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def height(self) -> int:
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def fps(self) -> float:
|
|
59
|
+
pass
|