ipycam 1.2.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.
- ipycam-1.2.0/LICENSE +21 -0
- ipycam-1.2.0/PKG-INFO +305 -0
- ipycam-1.2.0/README.md +275 -0
- ipycam-1.2.0/ipycam/__init__.py +68 -0
- ipycam-1.2.0/ipycam/__main__.py +327 -0
- ipycam-1.2.0/ipycam/__version__.py +1 -0
- ipycam-1.2.0/ipycam/camera.py +558 -0
- ipycam-1.2.0/ipycam/config.py +161 -0
- ipycam-1.2.0/ipycam/discovery.py +84 -0
- ipycam-1.2.0/ipycam/http.py +632 -0
- ipycam-1.2.0/ipycam/mjpeg.py +280 -0
- ipycam-1.2.0/ipycam/onvif.py +416 -0
- ipycam-1.2.0/ipycam/ptz.py +486 -0
- ipycam-1.2.0/ipycam/rtsp.py +973 -0
- ipycam-1.2.0/ipycam/static/css/style.css +572 -0
- ipycam-1.2.0/ipycam/static/index.html +196 -0
- ipycam-1.2.0/ipycam/static/js/app.js +808 -0
- ipycam-1.2.0/ipycam/static/soap/envelope.xml +9 -0
- ipycam-1.2.0/ipycam/static/soap/fault.xml +9 -0
- ipycam-1.2.0/ipycam/static/soap/get_audio_decoder_configurations.xml +2 -0
- ipycam-1.2.0/ipycam/static/soap/get_capabilities.xml +21 -0
- ipycam-1.2.0/ipycam/static/soap/get_device_information.xml +7 -0
- ipycam-1.2.0/ipycam/static/soap/get_profiles.xml +77 -0
- ipycam-1.2.0/ipycam/static/soap/get_scopes.xml +5 -0
- ipycam-1.2.0/ipycam/static/soap/get_services.xml +18 -0
- ipycam-1.2.0/ipycam/static/soap/get_snapshot_uri.xml +8 -0
- ipycam-1.2.0/ipycam/static/soap/get_stream_uri.xml +8 -0
- ipycam-1.2.0/ipycam/static/soap/get_system_date_time.xml +19 -0
- ipycam-1.2.0/ipycam/static/soap/get_users.xml +6 -0
- ipycam-1.2.0/ipycam/static/soap/get_video_encoder_configuration.xml +16 -0
- ipycam-1.2.0/ipycam/static/soap/get_video_source_configuration.xml +8 -0
- ipycam-1.2.0/ipycam/static/soap/probe_match.xml +22 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_absolute_move.xml +1 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_continuous_move.xml +1 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_get_configurations.xml +30 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_get_node.xml +37 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_get_nodes.xml +37 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_get_presets.xml +3 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_get_service_capabilities.xml +4 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_get_status.xml +13 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_goto_home.xml +1 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_goto_preset.xml +1 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_relative_move.xml +1 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_set_preset.xml +3 -0
- ipycam-1.2.0/ipycam/static/soap/ptz_stop.xml +1 -0
- ipycam-1.2.0/ipycam/streamer.py +565 -0
- ipycam-1.2.0/ipycam/webrtc.py +503 -0
- ipycam-1.2.0/ipycam.egg-info/PKG-INFO +305 -0
- ipycam-1.2.0/ipycam.egg-info/SOURCES.txt +57 -0
- ipycam-1.2.0/ipycam.egg-info/dependency_links.txt +1 -0
- ipycam-1.2.0/ipycam.egg-info/entry_points.txt +2 -0
- ipycam-1.2.0/ipycam.egg-info/requires.txt +12 -0
- ipycam-1.2.0/ipycam.egg-info/top_level.txt +1 -0
- ipycam-1.2.0/pyproject.toml +64 -0
- ipycam-1.2.0/setup.cfg +4 -0
- ipycam-1.2.0/tests/test_config.py +301 -0
- ipycam-1.2.0/tests/test_mjpeg.py +306 -0
- ipycam-1.2.0/tests/test_onvif.py +377 -0
- ipycam-1.2.0/tests/test_ptz.py +394 -0
ipycam-1.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Oliver Hamilton
|
|
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.
|
ipycam-1.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ipycam
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: Pure Python Virtual IP Camera with ONVIF support
|
|
5
|
+
Author-email: Oliver Hamilton <oliver9523@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: camera,onvif,rtsp,streaming,virtual-camera
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: numpy>=1.24.0
|
|
20
|
+
Requires-Dist: opencv-python>=4.8.0
|
|
21
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
22
|
+
Requires-Dist: aiortc>=1.14.0
|
|
23
|
+
Provides-Extra: camera360
|
|
24
|
+
Requires-Dist: framesource>=0.3.0; extra == "camera360"
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# IPyCam - Pure Python Virtual IP Camera
|
|
32
|
+
|
|
33
|
+
A lightweight, pure Python virtual IP camera that provides ONVIF discovery, RTSP streaming, and PTZ controls. Perfect for testing, development, or creating custom camera solutions.
|
|
34
|
+
|
|
35
|
+
## 📺 Demo Video
|
|
36
|
+
https://github.com/user-attachments/assets/1d3afd23-1ab8-40f6-876c-3f3f9a0089fe
|
|
37
|
+
|
|
38
|
+
[YouTube](https://www.youtube.com/watch?v=9AkqjnZRQTE)
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
- **ONVIF Compliance**: Full WS-Discovery support for automatic camera detection
|
|
43
|
+
- **RTSP Streaming**: High-performance video streaming via go2rtc (optional) or native Python fallback
|
|
44
|
+
- **WebRTC Support**: Direct browser streaming with native Python implementation
|
|
45
|
+
- **PTZ Controls**: Digital Pan-Tilt-Zoom with preset positions
|
|
46
|
+
- **Hardware Acceleration**: Automatic detection and use of NVENC, QSV, or CPU encoding (with go2rtc)
|
|
47
|
+
- **Native Fallback**: Pure Python streaming (WebRTC, MJPEG) when go2rtc is not available
|
|
48
|
+
- **Web Interface**: Built-in configuration and live preview
|
|
49
|
+
- **Low Latency**: Optimized async frame pipeline for real-time streaming
|
|
50
|
+
- **Flexible Input**: Accept frames from any source (webcam, video file, generated content)
|
|
51
|
+
|
|
52
|
+
## Requirements
|
|
53
|
+
|
|
54
|
+
- Python 3.8+
|
|
55
|
+
- **Optional**: FFmpeg + go2rtc for hardware-accelerated encoding (recommended for high performance)
|
|
56
|
+
- **Optional**: aiortc (`pip install aiortc`) for native WebRTC streaming fallback
|
|
57
|
+
|
|
58
|
+
> **Note**: IPyCam can run without go2rtc using pure Python streaming. However, go2rtc + FFmpeg provides significantly better performance, especially for high-resolution streams.
|
|
59
|
+
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
Clone the repo:
|
|
63
|
+
```bash
|
|
64
|
+
git clone https://github.com/olkham/IPyCam.git
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Setup Scripts (Windows and Linux)
|
|
68
|
+
|
|
69
|
+
If you prefer a guided setup, use the provided scripts. They install dependencies and prepare the environment for running the examples.
|
|
70
|
+
|
|
71
|
+
**Windows (PowerShell or Command Prompt):**
|
|
72
|
+
```bat
|
|
73
|
+
setup.bat
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Linux/macOS (bash):**
|
|
77
|
+
```bash
|
|
78
|
+
chmod +x setup.sh
|
|
79
|
+
./setup.sh
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> **Tip**: Run the script from the project root (the folder that contains `setup.bat` and `setup.sh`).
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
### Installation
|
|
86
|
+
|
|
87
|
+
Install directly from GitHub:
|
|
88
|
+
```bash
|
|
89
|
+
pip install git+https://github.com/olkham/IPyCam.git
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Or install from source:
|
|
93
|
+
```bash
|
|
94
|
+
git clone https://github.com/olkham/IPyCam.git
|
|
95
|
+
cd ipycam
|
|
96
|
+
pip install -e .
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Optional: Enhanced Streaming Performance (Recommended)**
|
|
100
|
+
|
|
101
|
+
For hardware-accelerated encoding with go2rtc:
|
|
102
|
+
|
|
103
|
+
1. **Install go2rtc**: Download from [go2rtc releases](https://github.com/AlexxIT/go2rtc/releases)
|
|
104
|
+
2. **Start go2rtc** with IPyCam configuration:
|
|
105
|
+
```bash
|
|
106
|
+
go2rtc.exe --config ipycam\go2rtc.yaml
|
|
107
|
+
```
|
|
108
|
+
Keep this running in a separate terminal.
|
|
109
|
+
|
|
110
|
+
Without go2rtc, IPyCam will automatically fall back to native Python streaming.
|
|
111
|
+
|
|
112
|
+
**Optional: 360° Camera Support**
|
|
113
|
+
|
|
114
|
+
For the `360_ptz.py` example with equirectangular projection:
|
|
115
|
+
```bash
|
|
116
|
+
pip install "ipycam[camera360]"
|
|
117
|
+
```
|
|
118
|
+
or install FrameSource separately:
|
|
119
|
+
```bash
|
|
120
|
+
pip install framesource
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Basic Usage
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
import cv2
|
|
127
|
+
from ipycam import IPCamera, CameraConfig
|
|
128
|
+
|
|
129
|
+
# Create camera with custom config
|
|
130
|
+
config = CameraConfig(
|
|
131
|
+
name="My Virtual Camera",
|
|
132
|
+
main_width=1920,
|
|
133
|
+
main_height=1080,
|
|
134
|
+
main_fps=30,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
camera = IPCamera(config)
|
|
138
|
+
camera.start()
|
|
139
|
+
|
|
140
|
+
# Stream from webcam
|
|
141
|
+
cap = cv2.VideoCapture(0)
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
while camera.is_running:
|
|
145
|
+
ret, frame = cap.read()
|
|
146
|
+
if ret:
|
|
147
|
+
camera.stream(frame)
|
|
148
|
+
except KeyboardInterrupt:
|
|
149
|
+
pass
|
|
150
|
+
finally:
|
|
151
|
+
cap.release()
|
|
152
|
+
camera.stop()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Running as a Module
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
python -m ipycam
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Then access:
|
|
162
|
+
- **Web UI**: http://localhost:8080/
|
|
163
|
+
- **RTSP Main Stream**: rtsp://localhost:8554/video_main
|
|
164
|
+
- **RTSP Sub Stream**: rtsp://localhost:8554/video_sub
|
|
165
|
+
- **ONVIF Service**: http://localhost:8080/onvif/device_service
|
|
166
|
+
|
|
167
|
+
### Testing the Stream
|
|
168
|
+
|
|
169
|
+
Test the RTSP streams using ffplay:
|
|
170
|
+
```bash
|
|
171
|
+
# Test main stream
|
|
172
|
+
ffplay rtsp://localhost:8554/video_main
|
|
173
|
+
|
|
174
|
+
# Test sub stream
|
|
175
|
+
ffplay rtsp://localhost:8554/video_sub
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Configuration
|
|
179
|
+
|
|
180
|
+
Configuration is stored in `camera_config.json`:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"name": "Virtual Camera",
|
|
185
|
+
"manufacturer": "PythonCam",
|
|
186
|
+
"model": "VirtualCam-1",
|
|
187
|
+
"main_width": 1920,
|
|
188
|
+
"main_height": 1080,
|
|
189
|
+
"main_fps": 30,
|
|
190
|
+
"main_bitrate": "4M",
|
|
191
|
+
"sub_width": 640,
|
|
192
|
+
"sub_height": 360,
|
|
193
|
+
"native_width": 640,
|
|
194
|
+
"native_height": 480,
|
|
195
|
+
"native_fps": 15,
|
|
196
|
+
"native_bitrate": "500K",
|
|
197
|
+
"hw_accel": "auto"
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Hardware acceleration options (go2rtc only):
|
|
202
|
+
- `"auto"` - Try NVENC → QSV → CPU (default)
|
|
203
|
+
- `"nvenc"` - NVIDIA GPU encoding
|
|
204
|
+
- `"qsv"` - Intel Quick Sync Video
|
|
205
|
+
- `"cpu"` - Software encoding (libx264)
|
|
206
|
+
|
|
207
|
+
Native fallback settings:
|
|
208
|
+
- `native_width/height/fps/bitrate` - Used when go2rtc is not available
|
|
209
|
+
- Lower resolution recommended for software encoding performance
|
|
210
|
+
|
|
211
|
+
## PTZ Controls
|
|
212
|
+
|
|
213
|
+
The camera includes digital PTZ (Pan-Tilt-Zoom) support:
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
# Access PTZ through ONVIF or directly
|
|
217
|
+
camera.ptz.continuous_move(pan_speed=0.5, tilt_speed=0.0, zoom_speed=0.0)
|
|
218
|
+
camera.ptz.stop()
|
|
219
|
+
camera.ptz.goto_preset(preset_token="preset1")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
PTZ presets are stored in `ptz_presets.json`.
|
|
223
|
+
|
|
224
|
+
## Performance Tips
|
|
225
|
+
|
|
226
|
+
1. **Use hardware acceleration**: Enable NVENC (NVIDIA) or QSV (Intel) for best performance
|
|
227
|
+
2. **Match resolutions**: Set camera input to match streaming resolution to avoid resize overhead
|
|
228
|
+
3. **Adjust FPS**: Most webcams are limited to 30fps
|
|
229
|
+
4. **Disable PTZ**: Set camera to home position (0,0,0) to skip PTZ transforms
|
|
230
|
+
|
|
231
|
+
## Architecture
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
ipycam/
|
|
235
|
+
├── __init__.py # Package exports
|
|
236
|
+
├── __main__.py # CLI entry point
|
|
237
|
+
├── camera.py # Main IPCamera class
|
|
238
|
+
├── config.py # CameraConfig dataclass
|
|
239
|
+
├── streamer.py # Video encoding and streaming pipeline
|
|
240
|
+
├── ptz.py # Digital PTZ implementation
|
|
241
|
+
├── onvif.py # ONVIF SOAP service
|
|
242
|
+
├── discovery.py # WS-Discovery server
|
|
243
|
+
├── http.py # HTTP request handler
|
|
244
|
+
└── static/ # Web UI and SOAP templates
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Development
|
|
248
|
+
|
|
249
|
+
### Running Tests
|
|
250
|
+
|
|
251
|
+
IPyCam includes a comprehensive test suite using pytest. To run the tests:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# Install dev dependencies
|
|
255
|
+
pip install -e ".[dev]"
|
|
256
|
+
|
|
257
|
+
# Run all tests
|
|
258
|
+
pytest
|
|
259
|
+
|
|
260
|
+
# Run with verbose output
|
|
261
|
+
pytest -v
|
|
262
|
+
|
|
263
|
+
# Run with coverage report
|
|
264
|
+
pytest --cov=ipycam --cov-report=term-missing
|
|
265
|
+
|
|
266
|
+
# Run specific test file
|
|
267
|
+
pytest tests/test_config.py
|
|
268
|
+
pytest tests/test_ptz.py
|
|
269
|
+
pytest tests/test_mjpeg.py
|
|
270
|
+
pytest tests/test_onvif.py
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
The test suite covers:
|
|
274
|
+
- **CameraConfig**: Configuration serialization, URL generation, hardware acceleration settings
|
|
275
|
+
- **PTZController**: Positioning, presets, hardware handler callbacks, frame transforms
|
|
276
|
+
- **MJPEGStreamer**: Client management, frame streaming, statistics
|
|
277
|
+
- **ONVIFService**: SOAP response generation, PTZ command parsing, device info
|
|
278
|
+
|
|
279
|
+
## Troubleshooting
|
|
280
|
+
|
|
281
|
+
### Camera freezes after a few frames
|
|
282
|
+
- **With go2rtc**: Check FFmpeg is installed and in PATH, verify go2rtc.exe is running
|
|
283
|
+
- **Native mode**: Install PyAV (`pip install av`) for RTSP or aiortc for WebRTC
|
|
284
|
+
- Check hardware encoder availability (go2rtc only)
|
|
285
|
+
|
|
286
|
+
### Low FPS performance
|
|
287
|
+
- **Recommended**: Use go2rtc with hardware acceleration
|
|
288
|
+
- **Native mode**: Reduce `native_width`, `native_height`, and `native_fps` in config
|
|
289
|
+
- Check CPU/GPU usage
|
|
290
|
+
- Ensure webcam supports requested FPS
|
|
291
|
+
|
|
292
|
+
### ONVIF discovery not working
|
|
293
|
+
- Check firewall allows UDP port 3702
|
|
294
|
+
- Verify local network allows multicast
|
|
295
|
+
- Use ONVIF Device Manager to test
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
MIT License - see LICENSE file for details
|
|
300
|
+
|
|
301
|
+
## Credits
|
|
302
|
+
|
|
303
|
+
- Built with Python, NumPy, and OpenCV
|
|
304
|
+
- Uses [go2rtc](https://github.com/AlexxIT/go2rtc) for RTSP streaming
|
|
305
|
+
- ONVIF protocol implementation based on WS-Discovery specs
|
ipycam-1.2.0/README.md
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# IPyCam - Pure Python Virtual IP Camera
|
|
2
|
+
|
|
3
|
+
A lightweight, pure Python virtual IP camera that provides ONVIF discovery, RTSP streaming, and PTZ controls. Perfect for testing, development, or creating custom camera solutions.
|
|
4
|
+
|
|
5
|
+
## 📺 Demo Video
|
|
6
|
+
https://github.com/user-attachments/assets/1d3afd23-1ab8-40f6-876c-3f3f9a0089fe
|
|
7
|
+
|
|
8
|
+
[YouTube](https://www.youtube.com/watch?v=9AkqjnZRQTE)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **ONVIF Compliance**: Full WS-Discovery support for automatic camera detection
|
|
13
|
+
- **RTSP Streaming**: High-performance video streaming via go2rtc (optional) or native Python fallback
|
|
14
|
+
- **WebRTC Support**: Direct browser streaming with native Python implementation
|
|
15
|
+
- **PTZ Controls**: Digital Pan-Tilt-Zoom with preset positions
|
|
16
|
+
- **Hardware Acceleration**: Automatic detection and use of NVENC, QSV, or CPU encoding (with go2rtc)
|
|
17
|
+
- **Native Fallback**: Pure Python streaming (WebRTC, MJPEG) when go2rtc is not available
|
|
18
|
+
- **Web Interface**: Built-in configuration and live preview
|
|
19
|
+
- **Low Latency**: Optimized async frame pipeline for real-time streaming
|
|
20
|
+
- **Flexible Input**: Accept frames from any source (webcam, video file, generated content)
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- Python 3.8+
|
|
25
|
+
- **Optional**: FFmpeg + go2rtc for hardware-accelerated encoding (recommended for high performance)
|
|
26
|
+
- **Optional**: aiortc (`pip install aiortc`) for native WebRTC streaming fallback
|
|
27
|
+
|
|
28
|
+
> **Note**: IPyCam can run without go2rtc using pure Python streaming. However, go2rtc + FFmpeg provides significantly better performance, especially for high-resolution streams.
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
Clone the repo:
|
|
33
|
+
```bash
|
|
34
|
+
git clone https://github.com/olkham/IPyCam.git
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Setup Scripts (Windows and Linux)
|
|
38
|
+
|
|
39
|
+
If you prefer a guided setup, use the provided scripts. They install dependencies and prepare the environment for running the examples.
|
|
40
|
+
|
|
41
|
+
**Windows (PowerShell or Command Prompt):**
|
|
42
|
+
```bat
|
|
43
|
+
setup.bat
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Linux/macOS (bash):**
|
|
47
|
+
```bash
|
|
48
|
+
chmod +x setup.sh
|
|
49
|
+
./setup.sh
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
> **Tip**: Run the script from the project root (the folder that contains `setup.bat` and `setup.sh`).
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
### Installation
|
|
56
|
+
|
|
57
|
+
Install directly from GitHub:
|
|
58
|
+
```bash
|
|
59
|
+
pip install git+https://github.com/olkham/IPyCam.git
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or install from source:
|
|
63
|
+
```bash
|
|
64
|
+
git clone https://github.com/olkham/IPyCam.git
|
|
65
|
+
cd ipycam
|
|
66
|
+
pip install -e .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Optional: Enhanced Streaming Performance (Recommended)**
|
|
70
|
+
|
|
71
|
+
For hardware-accelerated encoding with go2rtc:
|
|
72
|
+
|
|
73
|
+
1. **Install go2rtc**: Download from [go2rtc releases](https://github.com/AlexxIT/go2rtc/releases)
|
|
74
|
+
2. **Start go2rtc** with IPyCam configuration:
|
|
75
|
+
```bash
|
|
76
|
+
go2rtc.exe --config ipycam\go2rtc.yaml
|
|
77
|
+
```
|
|
78
|
+
Keep this running in a separate terminal.
|
|
79
|
+
|
|
80
|
+
Without go2rtc, IPyCam will automatically fall back to native Python streaming.
|
|
81
|
+
|
|
82
|
+
**Optional: 360° Camera Support**
|
|
83
|
+
|
|
84
|
+
For the `360_ptz.py` example with equirectangular projection:
|
|
85
|
+
```bash
|
|
86
|
+
pip install "ipycam[camera360]"
|
|
87
|
+
```
|
|
88
|
+
or install FrameSource separately:
|
|
89
|
+
```bash
|
|
90
|
+
pip install framesource
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Basic Usage
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import cv2
|
|
97
|
+
from ipycam import IPCamera, CameraConfig
|
|
98
|
+
|
|
99
|
+
# Create camera with custom config
|
|
100
|
+
config = CameraConfig(
|
|
101
|
+
name="My Virtual Camera",
|
|
102
|
+
main_width=1920,
|
|
103
|
+
main_height=1080,
|
|
104
|
+
main_fps=30,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
camera = IPCamera(config)
|
|
108
|
+
camera.start()
|
|
109
|
+
|
|
110
|
+
# Stream from webcam
|
|
111
|
+
cap = cv2.VideoCapture(0)
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
while camera.is_running:
|
|
115
|
+
ret, frame = cap.read()
|
|
116
|
+
if ret:
|
|
117
|
+
camera.stream(frame)
|
|
118
|
+
except KeyboardInterrupt:
|
|
119
|
+
pass
|
|
120
|
+
finally:
|
|
121
|
+
cap.release()
|
|
122
|
+
camera.stop()
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Running as a Module
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
python -m ipycam
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Then access:
|
|
132
|
+
- **Web UI**: http://localhost:8080/
|
|
133
|
+
- **RTSP Main Stream**: rtsp://localhost:8554/video_main
|
|
134
|
+
- **RTSP Sub Stream**: rtsp://localhost:8554/video_sub
|
|
135
|
+
- **ONVIF Service**: http://localhost:8080/onvif/device_service
|
|
136
|
+
|
|
137
|
+
### Testing the Stream
|
|
138
|
+
|
|
139
|
+
Test the RTSP streams using ffplay:
|
|
140
|
+
```bash
|
|
141
|
+
# Test main stream
|
|
142
|
+
ffplay rtsp://localhost:8554/video_main
|
|
143
|
+
|
|
144
|
+
# Test sub stream
|
|
145
|
+
ffplay rtsp://localhost:8554/video_sub
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Configuration
|
|
149
|
+
|
|
150
|
+
Configuration is stored in `camera_config.json`:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"name": "Virtual Camera",
|
|
155
|
+
"manufacturer": "PythonCam",
|
|
156
|
+
"model": "VirtualCam-1",
|
|
157
|
+
"main_width": 1920,
|
|
158
|
+
"main_height": 1080,
|
|
159
|
+
"main_fps": 30,
|
|
160
|
+
"main_bitrate": "4M",
|
|
161
|
+
"sub_width": 640,
|
|
162
|
+
"sub_height": 360,
|
|
163
|
+
"native_width": 640,
|
|
164
|
+
"native_height": 480,
|
|
165
|
+
"native_fps": 15,
|
|
166
|
+
"native_bitrate": "500K",
|
|
167
|
+
"hw_accel": "auto"
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Hardware acceleration options (go2rtc only):
|
|
172
|
+
- `"auto"` - Try NVENC → QSV → CPU (default)
|
|
173
|
+
- `"nvenc"` - NVIDIA GPU encoding
|
|
174
|
+
- `"qsv"` - Intel Quick Sync Video
|
|
175
|
+
- `"cpu"` - Software encoding (libx264)
|
|
176
|
+
|
|
177
|
+
Native fallback settings:
|
|
178
|
+
- `native_width/height/fps/bitrate` - Used when go2rtc is not available
|
|
179
|
+
- Lower resolution recommended for software encoding performance
|
|
180
|
+
|
|
181
|
+
## PTZ Controls
|
|
182
|
+
|
|
183
|
+
The camera includes digital PTZ (Pan-Tilt-Zoom) support:
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
# Access PTZ through ONVIF or directly
|
|
187
|
+
camera.ptz.continuous_move(pan_speed=0.5, tilt_speed=0.0, zoom_speed=0.0)
|
|
188
|
+
camera.ptz.stop()
|
|
189
|
+
camera.ptz.goto_preset(preset_token="preset1")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
PTZ presets are stored in `ptz_presets.json`.
|
|
193
|
+
|
|
194
|
+
## Performance Tips
|
|
195
|
+
|
|
196
|
+
1. **Use hardware acceleration**: Enable NVENC (NVIDIA) or QSV (Intel) for best performance
|
|
197
|
+
2. **Match resolutions**: Set camera input to match streaming resolution to avoid resize overhead
|
|
198
|
+
3. **Adjust FPS**: Most webcams are limited to 30fps
|
|
199
|
+
4. **Disable PTZ**: Set camera to home position (0,0,0) to skip PTZ transforms
|
|
200
|
+
|
|
201
|
+
## Architecture
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
ipycam/
|
|
205
|
+
├── __init__.py # Package exports
|
|
206
|
+
├── __main__.py # CLI entry point
|
|
207
|
+
├── camera.py # Main IPCamera class
|
|
208
|
+
├── config.py # CameraConfig dataclass
|
|
209
|
+
├── streamer.py # Video encoding and streaming pipeline
|
|
210
|
+
├── ptz.py # Digital PTZ implementation
|
|
211
|
+
├── onvif.py # ONVIF SOAP service
|
|
212
|
+
├── discovery.py # WS-Discovery server
|
|
213
|
+
├── http.py # HTTP request handler
|
|
214
|
+
└── static/ # Web UI and SOAP templates
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Development
|
|
218
|
+
|
|
219
|
+
### Running Tests
|
|
220
|
+
|
|
221
|
+
IPyCam includes a comprehensive test suite using pytest. To run the tests:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Install dev dependencies
|
|
225
|
+
pip install -e ".[dev]"
|
|
226
|
+
|
|
227
|
+
# Run all tests
|
|
228
|
+
pytest
|
|
229
|
+
|
|
230
|
+
# Run with verbose output
|
|
231
|
+
pytest -v
|
|
232
|
+
|
|
233
|
+
# Run with coverage report
|
|
234
|
+
pytest --cov=ipycam --cov-report=term-missing
|
|
235
|
+
|
|
236
|
+
# Run specific test file
|
|
237
|
+
pytest tests/test_config.py
|
|
238
|
+
pytest tests/test_ptz.py
|
|
239
|
+
pytest tests/test_mjpeg.py
|
|
240
|
+
pytest tests/test_onvif.py
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The test suite covers:
|
|
244
|
+
- **CameraConfig**: Configuration serialization, URL generation, hardware acceleration settings
|
|
245
|
+
- **PTZController**: Positioning, presets, hardware handler callbacks, frame transforms
|
|
246
|
+
- **MJPEGStreamer**: Client management, frame streaming, statistics
|
|
247
|
+
- **ONVIFService**: SOAP response generation, PTZ command parsing, device info
|
|
248
|
+
|
|
249
|
+
## Troubleshooting
|
|
250
|
+
|
|
251
|
+
### Camera freezes after a few frames
|
|
252
|
+
- **With go2rtc**: Check FFmpeg is installed and in PATH, verify go2rtc.exe is running
|
|
253
|
+
- **Native mode**: Install PyAV (`pip install av`) for RTSP or aiortc for WebRTC
|
|
254
|
+
- Check hardware encoder availability (go2rtc only)
|
|
255
|
+
|
|
256
|
+
### Low FPS performance
|
|
257
|
+
- **Recommended**: Use go2rtc with hardware acceleration
|
|
258
|
+
- **Native mode**: Reduce `native_width`, `native_height`, and `native_fps` in config
|
|
259
|
+
- Check CPU/GPU usage
|
|
260
|
+
- Ensure webcam supports requested FPS
|
|
261
|
+
|
|
262
|
+
### ONVIF discovery not working
|
|
263
|
+
- Check firewall allows UDP port 3702
|
|
264
|
+
- Verify local network allows multicast
|
|
265
|
+
- Use ONVIF Device Manager to test
|
|
266
|
+
|
|
267
|
+
## License
|
|
268
|
+
|
|
269
|
+
MIT License - see LICENSE file for details
|
|
270
|
+
|
|
271
|
+
## Credits
|
|
272
|
+
|
|
273
|
+
- Built with Python, NumPy, and OpenCV
|
|
274
|
+
- Uses [go2rtc](https://github.com/AlexxIT/go2rtc) for RTSP streaming
|
|
275
|
+
- ONVIF protocol implementation based on WS-Discovery specs
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
IPyCam - Pure Python Virtual IP Camera
|
|
3
|
+
|
|
4
|
+
A virtual IP camera that:
|
|
5
|
+
- Is discoverable via ONVIF (WS-Discovery)
|
|
6
|
+
- Provides RTSP streams via go2rtc
|
|
7
|
+
- Has a web interface for configuration and live preview
|
|
8
|
+
- Accepts frames from any source
|
|
9
|
+
- Supports digital PTZ (ePTZ) via ONVIF
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
from ipycam import IPCamera, CameraConfig
|
|
13
|
+
|
|
14
|
+
config = CameraConfig(name="My Camera")
|
|
15
|
+
camera = IPCamera(config)
|
|
16
|
+
camera.start()
|
|
17
|
+
|
|
18
|
+
while camera.is_running:
|
|
19
|
+
frame = get_frame() # Your frame source
|
|
20
|
+
camera.stream(frame)
|
|
21
|
+
|
|
22
|
+
camera.stop()
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from .__version__ import __version__
|
|
26
|
+
|
|
27
|
+
from .config import CameraConfig
|
|
28
|
+
from .camera import IPCamera
|
|
29
|
+
from .streamer import VideoStreamer, StreamConfig, StreamStats, HWAccel
|
|
30
|
+
from .ptz import PTZController, PTZState, PTZPreset, PTZHardwareHandler, PTZVelocity
|
|
31
|
+
from .onvif import ONVIFService
|
|
32
|
+
from .discovery import WSDiscoveryServer
|
|
33
|
+
from .http import IPCameraHTTPHandler
|
|
34
|
+
from .mjpeg import MJPEGStreamer, check_go2rtc_running, check_rtsp_port_available
|
|
35
|
+
from .webrtc import NativeWebRTCStreamer, WebRTCStats, is_webrtc_available
|
|
36
|
+
from .rtsp import NativeRTSPServer, is_native_rtsp_available
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
# Main classes
|
|
40
|
+
"IPCamera",
|
|
41
|
+
"CameraConfig",
|
|
42
|
+
# Streaming
|
|
43
|
+
"VideoStreamer",
|
|
44
|
+
"StreamConfig",
|
|
45
|
+
"StreamStats",
|
|
46
|
+
"HWAccel",
|
|
47
|
+
# MJPEG fallback
|
|
48
|
+
"MJPEGStreamer",
|
|
49
|
+
"check_go2rtc_running",
|
|
50
|
+
"check_rtsp_port_available",
|
|
51
|
+
# Native WebRTC fallback
|
|
52
|
+
"NativeWebRTCStreamer",
|
|
53
|
+
"WebRTCStats",
|
|
54
|
+
"is_webrtc_available",
|
|
55
|
+
# Native RTSP fallback
|
|
56
|
+
"NativeRTSPServer",
|
|
57
|
+
"is_native_rtsp_available",
|
|
58
|
+
# PTZ
|
|
59
|
+
"PTZController",
|
|
60
|
+
"PTZState",
|
|
61
|
+
"PTZPreset",
|
|
62
|
+
"PTZVelocity",
|
|
63
|
+
"PTZHardwareHandler",
|
|
64
|
+
# ONVIF
|
|
65
|
+
"ONVIFService",
|
|
66
|
+
"WSDiscoveryServer",
|
|
67
|
+
"IPCameraHTTPHandler",
|
|
68
|
+
]
|