- Reformatted function signatures for better clarity in media.go and onvif-quick/main.go. - Replaced hardcoded values with constants in ascii.go and server/imaging.go for improved maintainability. - Enhanced error handling and logging consistency in onvif-diagnostics/main.go and server/server.go. - Updated comments to clarify functionality and ensure adherence to ONVIF specifications across various files.
ONVIF Server - Virtual IP Camera Simulator
A complete ONVIF-compliant server implementation that simulates multi-lens IP cameras with full support for Device, Media, PTZ, and Imaging services.
Features
🎥 Multi-Lens Camera Support
- Multiple Video Profiles: Support for up to 10 independent camera profiles
- Different Resolutions: From 640x480 to 4K (3840x2160)
- Configurable Framerates: 25, 30, 60 fps
- Multiple Encodings: H.264, H.265, MPEG4, JPEG
🎮 PTZ Control
- Continuous Movement: Smooth pan, tilt, and zoom control
- Absolute Positioning: Move to specific coordinates
- Relative Movement: Move relative to current position
- Preset Positions: Save and recall camera positions
- Status Monitoring: Real-time PTZ state information
📷 Imaging Control
- Brightness, Contrast, Saturation: Full color control
- Exposure Settings: Auto/Manual modes with gain control
- Focus Control: Auto-focus and manual focus positioning
- White Balance: Auto/Manual white balance adjustment
- Wide Dynamic Range (WDR): Enhanced contrast in challenging lighting
- IR Cut Filter: Day/Night mode control
🌐 ONVIF Services
- ✅ Device Service: Device information, capabilities, system time
- ✅ Media Service: Profiles, stream URIs (RTSP), snapshots
- ✅ PTZ Service: Full PTZ control and preset management
- ✅ Imaging Service: Complete imaging settings control
- ⏳ Events Service: (Planned)
🔐 Security
- WS-Security Authentication: UsernameToken with password digest
- Configurable Credentials: Custom username/password
- SOAP Message Security: Nonce and timestamp validation
Installation
# Clone the repository (if not already done)
git clone https://github.com/0x524a/onvif-go
cd onvif-go
# Build the server CLI
go build -o onvif-server ./cmd/onvif-server
# Or install globally
go install ./cmd/onvif-server
Quick Start
Basic Usage
Start the server with default settings (3 camera profiles):
./onvif-server
The server will start on http://0.0.0.0:8080 with:
- Username:
admin - Password:
admin - 3 camera profiles with different resolutions
- PTZ and Imaging services enabled
Custom Configuration
# Custom credentials and port
./onvif-server -username myuser -password mypass -port 9000
# More camera profiles
./onvif-server -profiles 5
# Disable PTZ
./onvif-server -ptz=false
# Custom device information
./onvif-server -manufacturer "Acme Corp" -model "SuperCam 5000"
Command-Line Options
-host string
Server host address (default "0.0.0.0")
-port int
Server port (default 8080)
-username string
Authentication username (default "admin")
-password string
Authentication password (default "admin")
-manufacturer string
Device manufacturer (default "onvif-go")
-model string
Device model (default "Virtual Multi-Lens Camera")
-firmware string
Firmware version (default "1.0.0")
-serial string
Serial number (default "SN-12345678")
-profiles int
Number of camera profiles (1-10) (default 3)
-ptz
Enable PTZ support (default true)
-imaging
Enable Imaging support (default true)
-events
Enable Events support (default false)
-info
Show server info and exit
-version
Show version and exit
Using the Server Library
Simple Example
package main
import (
"context"
"log"
"time"
"github.com/0x524a/onvif-go/server"
)
func main() {
// Use default configuration
config := server.DefaultConfig()
// Or customize
config.Port = 9000
config.Username = "myuser"
config.Password = "mypass"
// Create server
srv, err := server.New(config)
if err != nil {
log.Fatal(err)
}
// Start server
ctx := context.Background()
if err := srv.Start(ctx); err != nil {
log.Fatal(err)
}
}
Custom Multi-Lens Camera
package main
import (
"context"
"log"
"time"
"github.com/0x524a/onvif-go/server"
)
func main() {
config := &server.Config{
Host: "0.0.0.0",
Port: 8080,
BasePath: "/onvif",
Timeout: 30 * time.Second,
DeviceInfo: server.DeviceInfo{
Manufacturer: "MultiCam Systems",
Model: "MC-3000 Pro",
FirmwareVersion: "2.5.1",
SerialNumber: "MC3000-001234",
HardwareID: "HW-MC3000",
},
Username: "admin",
Password: "SecurePass123",
SupportPTZ: true,
SupportImaging: true,
SupportEvents: false,
Profiles: []server.ProfileConfig{
{
Token: "profile_main_4k",
Name: "Main Camera 4K",
VideoSource: server.VideoSourceConfig{
Token: "video_source_main",
Name: "Main Camera",
Resolution: server.Resolution{Width: 3840, Height: 2160},
Framerate: 30,
},
VideoEncoder: server.VideoEncoderConfig{
Encoding: "H264",
Resolution: server.Resolution{Width: 3840, Height: 2160},
Quality: 90,
Framerate: 30,
Bitrate: 20480, // 20 Mbps
GovLength: 30,
},
PTZ: &server.PTZConfig{
NodeToken: "ptz_main",
PanRange: server.Range{Min: -180, Max: 180},
TiltRange: server.Range{Min: -90, Max: 90},
ZoomRange: server.Range{Min: 0, Max: 10},
SupportsContinuous: true,
SupportsAbsolute: true,
SupportsRelative: true,
Presets: []server.Preset{
{Token: "preset_home", Name: "Home", Position: server.PTZPosition{Pan: 0, Tilt: 0, Zoom: 0}},
{Token: "preset_entrance", Name: "Entrance", Position: server.PTZPosition{Pan: -45, Tilt: -20, Zoom: 3}},
},
},
Snapshot: server.SnapshotConfig{
Enabled: true,
Resolution: server.Resolution{Width: 3840, Height: 2160},
Quality: 95,
},
},
// Add more profiles...
},
}
srv, err := server.New(config)
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
if err := srv.Start(ctx); err != nil {
log.Fatal(err)
}
}
Testing with ONVIF Client
You can test the server with the included ONVIF client library:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/0x524a/onvif-go"
)
func main() {
// Connect to the server
client, err := onvif.NewClient(
"http://localhost:8080/onvif/device_service",
onvif.WithCredentials("admin", "admin"),
onvif.WithTimeout(30*time.Second),
)
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Get device information
info, err := client.GetDeviceInformation(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Device: %s %s\n", info.Manufacturer, info.Model)
// Initialize to discover services
if err := client.Initialize(ctx); err != nil {
log.Fatal(err)
}
// Get media profiles
profiles, err := client.GetProfiles(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d profiles:\n", len(profiles))
for i, profile := range profiles {
fmt.Printf(" [%d] %s\n", i+1, profile.Name)
// Get stream URI
streamURI, err := client.GetStreamURI(ctx, profile.Token)
if err != nil {
log.Fatal(err)
}
fmt.Printf(" Stream: %s\n", streamURI.URI)
}
// PTZ control (if available)
if len(profiles) > 0 && profiles[0].PTZConfiguration != nil {
profileToken := profiles[0].Token
// Get PTZ status
status, err := client.GetStatus(ctx, profileToken)
if err != nil {
log.Fatal(err)
}
fmt.Printf("PTZ Position: Pan=%.2f, Tilt=%.2f, Zoom=%.2f\n",
status.Position.PanTilt.X,
status.Position.PanTilt.Y,
status.Position.Zoom.X)
// Move to home position
position := &onvif.PTZVector{
PanTilt: &onvif.Vector2D{X: 0.0, Y: 0.0},
Zoom: &onvif.Vector1D{X: 0.0},
}
if err := client.AbsoluteMove(ctx, profileToken, position, nil); err != nil {
log.Fatal(err)
}
fmt.Println("Moved to home position")
}
}
Examples
See the examples/onvif-server directory for a complete multi-lens camera configuration example.
# Run the example
cd examples/onvif-server
go run main.go
This example demonstrates:
- 4 different camera profiles (4K main, wide-angle, telephoto, low-light)
- PTZ control with multiple presets
- Different resolutions and framerates
- Custom device information
Use Cases
🧪 Testing & Development
- Test ONVIF client implementations
- Simulate multi-camera setups
- Develop video management systems
- Integration testing without physical cameras
📚 Learning & Education
- Understand ONVIF protocol
- Learn SOAP web services
- Study IP camera architectures
- Prototype camera systems
🎭 Demonstrations
- Demo video surveillance solutions
- Showcase camera management software
- Present multi-camera scenarios
- Trade show demonstrations
🔬 Research & Prototyping
- Computer vision research
- Video analytics development
- Stream processing pipelines
- AI/ML model training
Architecture
The server is built with a modular architecture:
server/
├── types.go # Core data types and configuration
├── server.go # Main server implementation
├── device.go # Device service handlers
├── media.go # Media service handlers
├── ptz.go # PTZ service handlers
├── imaging.go # Imaging service handlers
└── soap/
└── handler.go # SOAP message handling
Key Components
- Server Core: HTTP server, request routing, lifecycle management
- SOAP Handler: SOAP message parsing, authentication, response formatting
- Service Handlers: Device, Media, PTZ, Imaging service implementations
- State Management: PTZ positions, imaging settings, stream configurations
RTSP Streaming
The server provides RTSP URIs for each profile:
rtsp://localhost:8554/stream0 # Profile 0
rtsp://localhost:8554/stream1 # Profile 1
rtsp://localhost:8554/stream2 # Profile 2
...
Note: The current implementation returns RTSP URIs but does not include an actual RTSP server. To provide real video streams, integrate with:
- RTSPtoWeb
- MediaMTX
- FFmpeg RTSP server
- Custom RTSP implementation
Roadmap
- Events Service: Event subscription and notification
- Recording Service: Recording management
- Analytics Service: Video analytics support
- Actual RTSP Streaming: Integrated RTSP server with test patterns
- Web UI: Browser-based configuration and monitoring
- Docker Support: Containerized deployment
- Configuration Files: YAML/JSON configuration support
- WS-Discovery: Automatic device discovery on network
- TLS Support: HTTPS and secure RTSP
- Audio Support: Audio streaming and configuration
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Built on top of the onvif-go client library
- ONVIF specifications from ONVIF.org
- Inspired by the need for flexible camera simulation in development workflows
Note: This is a virtual camera server for testing and development. It simulates ONVIF protocol responses but does not capture or stream real video unless integrated with an RTSP server.