ONVIF server with multi-lens camera support
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/0x524A/go-onvif/server"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create a custom multi-lens camera configuration
|
||||
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{
|
||||
// Profile 1: Main camera with 4K resolution
|
||||
{
|
||||
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,
|
||||
Bounds: server.Bounds{X: 0, Y: 0, Width: 3840, Height: 2160},
|
||||
},
|
||||
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}, // 10x optical zoom
|
||||
DefaultSpeed: server.PTZSpeed{Pan: 0.5, Tilt: 0.5, Zoom: 0.5},
|
||||
SupportsContinuous: true,
|
||||
SupportsAbsolute: true,
|
||||
SupportsRelative: true,
|
||||
Presets: []server.Preset{
|
||||
{Token: "preset_home", Name: "Home Position", Position: server.PTZPosition{Pan: 0, Tilt: 0, Zoom: 0}},
|
||||
{Token: "preset_entrance", Name: "Main Entrance", Position: server.PTZPosition{Pan: -45, Tilt: -20, Zoom: 3}},
|
||||
{Token: "preset_parking", Name: "Parking Lot", Position: server.PTZPosition{Pan: 90, Tilt: -30, Zoom: 5}},
|
||||
{Token: "preset_perimeter", Name: "Perimeter View", Position: server.PTZPosition{Pan: 180, Tilt: 0, Zoom: 2}},
|
||||
},
|
||||
},
|
||||
Snapshot: server.SnapshotConfig{
|
||||
Enabled: true,
|
||||
Resolution: server.Resolution{Width: 3840, Height: 2160},
|
||||
Quality: 95,
|
||||
},
|
||||
},
|
||||
// Profile 2: Wide-angle camera for overview
|
||||
{
|
||||
Token: "profile_wide",
|
||||
Name: "Wide Angle Overview",
|
||||
VideoSource: server.VideoSourceConfig{
|
||||
Token: "video_source_wide",
|
||||
Name: "Wide Angle Camera",
|
||||
Resolution: server.Resolution{Width: 2560, Height: 1440},
|
||||
Framerate: 30,
|
||||
Bounds: server.Bounds{X: 0, Y: 0, Width: 2560, Height: 1440},
|
||||
},
|
||||
VideoEncoder: server.VideoEncoderConfig{
|
||||
Encoding: "H264",
|
||||
Resolution: server.Resolution{Width: 2560, Height: 1440},
|
||||
Quality: 85,
|
||||
Framerate: 30,
|
||||
Bitrate: 8192, // 8 Mbps
|
||||
GovLength: 30,
|
||||
},
|
||||
Snapshot: server.SnapshotConfig{
|
||||
Enabled: true,
|
||||
Resolution: server.Resolution{Width: 2560, Height: 1440},
|
||||
Quality: 90,
|
||||
},
|
||||
},
|
||||
// Profile 3: Telephoto camera for distant subjects
|
||||
{
|
||||
Token: "profile_telephoto",
|
||||
Name: "Telephoto Camera",
|
||||
VideoSource: server.VideoSourceConfig{
|
||||
Token: "video_source_telephoto",
|
||||
Name: "Telephoto Camera",
|
||||
Resolution: server.Resolution{Width: 1920, Height: 1080},
|
||||
Framerate: 60, // High framerate for smooth tracking
|
||||
Bounds: server.Bounds{X: 0, Y: 0, Width: 1920, Height: 1080},
|
||||
},
|
||||
VideoEncoder: server.VideoEncoderConfig{
|
||||
Encoding: "H264",
|
||||
Resolution: server.Resolution{Width: 1920, Height: 1080},
|
||||
Quality: 88,
|
||||
Framerate: 60,
|
||||
Bitrate: 10240, // 10 Mbps
|
||||
GovLength: 60,
|
||||
},
|
||||
PTZ: &server.PTZConfig{
|
||||
NodeToken: "ptz_telephoto",
|
||||
PanRange: server.Range{Min: -180, Max: 180},
|
||||
TiltRange: server.Range{Min: -45, Max: 45},
|
||||
ZoomRange: server.Range{Min: 0, Max: 30}, // 30x optical zoom
|
||||
DefaultSpeed: server.PTZSpeed{Pan: 0.3, Tilt: 0.3, Zoom: 0.3},
|
||||
SupportsContinuous: true,
|
||||
SupportsAbsolute: true,
|
||||
SupportsRelative: true,
|
||||
Presets: []server.Preset{
|
||||
{Token: "preset_tel_home", Name: "Home", Position: server.PTZPosition{Pan: 0, Tilt: 0, Zoom: 0}},
|
||||
{Token: "preset_tel_far", Name: "Far View", Position: server.PTZPosition{Pan: 0, Tilt: 0, Zoom: 20}},
|
||||
{Token: "preset_tel_left", Name: "Left Side", Position: server.PTZPosition{Pan: -90, Tilt: 0, Zoom: 10}},
|
||||
{Token: "preset_tel_right", Name: "Right Side", Position: server.PTZPosition{Pan: 90, Tilt: 0, Zoom: 10}},
|
||||
},
|
||||
},
|
||||
Snapshot: server.SnapshotConfig{
|
||||
Enabled: true,
|
||||
Resolution: server.Resolution{Width: 1920, Height: 1080},
|
||||
Quality: 92,
|
||||
},
|
||||
},
|
||||
// Profile 4: Low-light camera for night vision
|
||||
{
|
||||
Token: "profile_lowlight",
|
||||
Name: "Low Light Night Camera",
|
||||
VideoSource: server.VideoSourceConfig{
|
||||
Token: "video_source_lowlight",
|
||||
Name: "Low Light Camera",
|
||||
Resolution: server.Resolution{Width: 1920, Height: 1080},
|
||||
Framerate: 30,
|
||||
Bounds: server.Bounds{X: 0, Y: 0, Width: 1920, Height: 1080},
|
||||
},
|
||||
VideoEncoder: server.VideoEncoderConfig{
|
||||
Encoding: "H264",
|
||||
Resolution: server.Resolution{Width: 1920, Height: 1080},
|
||||
Quality: 85,
|
||||
Framerate: 30,
|
||||
Bitrate: 6144, // 6 Mbps
|
||||
GovLength: 30,
|
||||
},
|
||||
Snapshot: server.SnapshotConfig{
|
||||
Enabled: true,
|
||||
Resolution: server.Resolution{Width: 1920, Height: 1080},
|
||||
Quality: 88,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Create and start server
|
||||
srv, err := server.New(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create server: %v", err)
|
||||
}
|
||||
|
||||
// Print configuration
|
||||
fmt.Println("╔════════════════════════════════════════════════════════════════╗")
|
||||
fmt.Println("║ ║")
|
||||
fmt.Println("║ 🎥 ONVIF Multi-Lens Camera Server Example 🎥 ║")
|
||||
fmt.Println("║ ║")
|
||||
fmt.Println("╚════════════════════════════════════════════════════════════════╝")
|
||||
fmt.Println()
|
||||
fmt.Println(srv.ServerInfo())
|
||||
fmt.Println()
|
||||
fmt.Println("📝 Configuration Details:")
|
||||
fmt.Println(" • 4 camera lenses with different capabilities")
|
||||
fmt.Println(" • Main camera: 4K resolution with 10x zoom PTZ")
|
||||
fmt.Println(" • Wide angle: 1440p for area overview")
|
||||
fmt.Println(" • Telephoto: 1080p@60fps with 30x zoom for distant subjects")
|
||||
fmt.Println(" • Low light: 1080p optimized for night vision")
|
||||
fmt.Println()
|
||||
fmt.Println("🔐 Credentials:")
|
||||
fmt.Println(" Username: admin")
|
||||
fmt.Println(" Password: SecurePass123")
|
||||
fmt.Println()
|
||||
fmt.Println("Press Ctrl+C to stop the server...")
|
||||
fmt.Println()
|
||||
|
||||
// Create context with cancellation
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// Setup signal handler
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
// Start server in goroutine
|
||||
go func() {
|
||||
if err := srv.Start(ctx); err != nil {
|
||||
log.Printf("Server error: %v", err)
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for interrupt signal
|
||||
<-sigChan
|
||||
fmt.Println("\n🛑 Shutting down server...")
|
||||
cancel()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
fmt.Println("✅ Server stopped successfully")
|
||||
}
|
||||
Reference in New Issue
Block a user