Pure Python Virtual IP Camera with ONVIF support
Project description
IPyCam - Pure Python Virtual IP Camera
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.
📺 Demo Video
https://github.com/user-attachments/assets/1d3afd23-1ab8-40f6-876c-3f3f9a0089fe
Features
- ONVIF Compliance: Full WS-Discovery support for automatic camera detection
- RTSP Streaming: High-performance video streaming via go2rtc (optional) or native Python fallback
- WebRTC Support: Direct browser streaming with native Python implementation
- PTZ Controls: Digital Pan-Tilt-Zoom with preset positions
- Hardware Acceleration: Automatic detection and use of NVENC, QSV, or CPU encoding (with go2rtc)
- Native Fallback: Pure Python streaming (WebRTC, MJPEG) when go2rtc is not available
- Web Interface: Built-in configuration and live preview
- Low Latency: Optimized async frame pipeline for real-time streaming
- Flexible Input: Accept frames from any source (webcam, video file, generated content)
Requirements
- Python 3.8+
- Optional: FFmpeg + go2rtc for hardware-accelerated encoding (recommended for high performance)
- Optional: aiortc (
pip install aiortc) for native WebRTC streaming fallback
Note: IPyCam can run without go2rtc using pure Python streaming. However, go2rtc + FFmpeg provides significantly better performance, especially for high-resolution streams.
Quick Start
Clone the repo:
git clone https://github.com/olkham/IPyCam.git
Setup Scripts (Windows and Linux)
If you prefer a guided setup, use the provided scripts. They install dependencies and prepare the environment for running the examples.
Windows (PowerShell or Command Prompt):
setup.bat
Linux/macOS (bash):
chmod +x setup.sh
./setup.sh
Tip: Run the script from the project root (the folder that contains
setup.batandsetup.sh).
Installation
Install directly from GitHub:
pip install git+https://github.com/olkham/IPyCam.git
Or install from source:
git clone https://github.com/olkham/IPyCam.git
cd ipycam
pip install -e .
Optional: Enhanced Streaming Performance (Recommended)
For hardware-accelerated encoding with go2rtc:
- Install go2rtc: Download from go2rtc releases
- Start go2rtc with IPyCam configuration:
go2rtc.exe --config ipycam\go2rtc.yaml
Keep this running in a separate terminal.
Without go2rtc, IPyCam will automatically fall back to native Python streaming.
Optional: 360° Camera Support
For the 360_ptz.py example with equirectangular projection:
pip install "ipycam[camera360]"
or install FrameSource separately:
pip install framesource
Basic Usage
import cv2
from ipycam import IPCamera, CameraConfig
# Create camera with custom config
config = CameraConfig(
name="My Virtual Camera",
main_width=1920,
main_height=1080,
main_fps=30,
)
camera = IPCamera(config)
camera.start()
# Stream from webcam
cap = cv2.VideoCapture(0)
try:
while camera.is_running:
ret, frame = cap.read()
if ret:
camera.stream(frame)
except KeyboardInterrupt:
pass
finally:
cap.release()
camera.stop()
Running as a Module
python -m ipycam
Then access:
- Web UI: http://localhost:8080/
- RTSP Main Stream: rtsp://localhost:8554/video_main
- RTSP Sub Stream: rtsp://localhost:8554/video_sub
- ONVIF Service: http://localhost:8080/onvif/device_service
Testing the Stream
Test the RTSP streams using ffplay:
# Test main stream
ffplay rtsp://localhost:8554/video_main
# Test sub stream
ffplay rtsp://localhost:8554/video_sub
Configuration
Configuration is stored in camera_config.json:
{
"name": "Virtual Camera",
"manufacturer": "PythonCam",
"model": "VirtualCam-1",
"main_width": 1920,
"main_height": 1080,
"main_fps": 30,
"main_bitrate": "4M",
"sub_width": 640,
"sub_height": 360,
"native_width": 640,
"native_height": 480,
"native_fps": 15,
"native_bitrate": "500K",
"hw_accel": "auto"
}
Hardware acceleration options (go2rtc only):
"auto"- Try NVENC → QSV → CPU (default)"nvenc"- NVIDIA GPU encoding"qsv"- Intel Quick Sync Video"cpu"- Software encoding (libx264)
Native fallback settings:
native_width/height/fps/bitrate- Used when go2rtc is not available- Lower resolution recommended for software encoding performance
PTZ Controls
The camera includes digital PTZ (Pan-Tilt-Zoom) support:
# Access PTZ through ONVIF or directly
camera.ptz.continuous_move(pan_speed=0.5, tilt_speed=0.0, zoom_speed=0.0)
camera.ptz.stop()
camera.ptz.goto_preset(preset_token="preset1")
PTZ presets are stored in ptz_presets.json.
Performance Tips
- Use hardware acceleration: Enable NVENC (NVIDIA) or QSV (Intel) for best performance
- Match resolutions: Set camera input to match streaming resolution to avoid resize overhead
- Adjust FPS: Most webcams are limited to 30fps
- Disable PTZ: Set camera to home position (0,0,0) to skip PTZ transforms
Architecture
ipycam/
├── __init__.py # Package exports
├── __main__.py # CLI entry point
├── camera.py # Main IPCamera class
├── config.py # CameraConfig dataclass
├── streamer.py # Video encoding and streaming pipeline
├── ptz.py # Digital PTZ implementation
├── onvif.py # ONVIF SOAP service
├── discovery.py # WS-Discovery server
├── http.py # HTTP request handler
└── static/ # Web UI and SOAP templates
Development
Running Tests
IPyCam includes a comprehensive test suite using pytest. To run the tests:
# Install dev dependencies
pip install -e ".[dev]"
# Run all tests
pytest
# Run with verbose output
pytest -v
# Run with coverage report
pytest --cov=ipycam --cov-report=term-missing
# Run specific test file
pytest tests/test_config.py
pytest tests/test_ptz.py
pytest tests/test_mjpeg.py
pytest tests/test_onvif.py
The test suite covers:
- CameraConfig: Configuration serialization, URL generation, hardware acceleration settings
- PTZController: Positioning, presets, hardware handler callbacks, frame transforms
- MJPEGStreamer: Client management, frame streaming, statistics
- ONVIFService: SOAP response generation, PTZ command parsing, device info
Troubleshooting
Camera freezes after a few frames
- With go2rtc: Check FFmpeg is installed and in PATH, verify go2rtc.exe is running
- Native mode: Install PyAV (
pip install av) for RTSP or aiortc for WebRTC - Check hardware encoder availability (go2rtc only)
Low FPS performance
- Recommended: Use go2rtc with hardware acceleration
- Native mode: Reduce
native_width,native_height, andnative_fpsin config - Check CPU/GPU usage
- Ensure webcam supports requested FPS
ONVIF discovery not working
- Check firewall allows UDP port 3702
- Verify local network allows multicast
- Use ONVIF Device Manager to test
License
MIT License - see LICENSE file for details
Credits
- Built with Python, NumPy, and OpenCV
- Uses go2rtc for RTSP streaming
- ONVIF protocol implementation based on WS-Discovery specs
Project details
Release history Release notifications | RSS feed
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 ipycam-1.2.0.tar.gz.
File metadata
- Download URL: ipycam-1.2.0.tar.gz
- Upload date:
- Size: 72.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89ea1ffc7dd0b6817e71b2eefb14859fcbe2eac1bab2be34fba5f5a139f8fe3a
|
|
| MD5 |
8a4955f47730e1177d6d59c98a4ec3c4
|
|
| BLAKE2b-256 |
37ebb706ab927fddbda022529645a6100fdb6da0e65bc70005c70d5a1f942a5c
|
Provenance
The following attestation bundles were made for ipycam-1.2.0.tar.gz:
Publisher:
publish.yaml on olkham/IPyCam
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipycam-1.2.0.tar.gz -
Subject digest:
89ea1ffc7dd0b6817e71b2eefb14859fcbe2eac1bab2be34fba5f5a139f8fe3a - Sigstore transparency entry: 2169120396
- Sigstore integration time:
-
Permalink:
olkham/IPyCam@a8ffec6d7b80930bc97d9e16de30bbbe940ec66f -
Branch / Tag:
refs/tags/v1.2.3 - Owner: https://github.com/olkham
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@a8ffec6d7b80930bc97d9e16de30bbbe940ec66f -
Trigger Event:
push
-
Statement type:
File details
Details for the file ipycam-1.2.0-py3-none-any.whl.
File metadata
- Download URL: ipycam-1.2.0-py3-none-any.whl
- Upload date:
- Size: 75.2 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 |
4e9b4e8a9cc4d1c5bd2519c28bb81478296a7f223e5869cba3bd02e0bcb8083d
|
|
| MD5 |
a041ce6db300408242e591be7d9c9737
|
|
| BLAKE2b-256 |
706bbb8f119cd5ce104eb4036942554fee2addb0560ae186596af000878fa7b2
|
Provenance
The following attestation bundles were made for ipycam-1.2.0-py3-none-any.whl:
Publisher:
publish.yaml on olkham/IPyCam
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipycam-1.2.0-py3-none-any.whl -
Subject digest:
4e9b4e8a9cc4d1c5bd2519c28bb81478296a7f223e5869cba3bd02e0bcb8083d - Sigstore transparency entry: 2169120539
- Sigstore integration time:
-
Permalink:
olkham/IPyCam@a8ffec6d7b80930bc97d9e16de30bbbe940ec66f -
Branch / Tag:
refs/tags/v1.2.3 - Owner: https://github.com/olkham
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@a8ffec6d7b80930bc97d9e16de30bbbe940ec66f -
Trigger Event:
push
-
Statement type: