Skip to main content

DirectShow UVC Camera Control Library

Project description

duvc-ctl

duvc-ctl is a lightweight Python library for controlling USB Video Class (UVC) camera properties on Windows using the native DirectShow API.
It exposes camera and video properties (PTZ, focus, exposure, brightness, etc.), supports device monitoring with hotplug detection, and provides access to vendor-specific property sets — all without vendor SDKs, extra drivers, or dependencies.

Key Features

  • Simple Pythonic API: Property-based access (cam.brightness = 80) with automatic device management and beginner-friendly error handling
  • Advanced Result-Based API: Explicit error handling with Result types for detailed control in production code
  • Camera & Video Properties: Get/set PTZ controls, exposure, focus, white balance, gain, and other IAMCameraControl/IAMVideoProcAmp properties
  • Device Monitoring: List devices, check connectivity, and handle hotplug events
  • Vendor Extensions: Access custom property sets via GUID
  • Multiple Error Handling: Simple exceptions, Result types, or safe tuple returns
  • Thread-Safe: Safe for use in multi-threaded applications

Works on Windows 7+ with Python 3.8+. Suitable for computer vision, robotics, video streaming, and automation projects requiring precise USB camera control.

Installation

pip install duvc-ctl

Two APIs, One Library

duvc-ctl provides two complementary APIs for different use cases:

1. Pythonic API (Recommended for Most Users)

Use when: You want simple, readable code with automatic device selection and beginner-friendly errors.

Simple property-based control with context manager support:

import duvc_ctl as duvc

# Connect to first available camera
with duvc.CameraController() as cam:
    cam.brightness = 80        # Simple assignment
    cam.pan += 10              # Relative adjustment
    print(f"Zoom: {cam.zoom}")  # Simple property read
    
    # Reset to defaults
    cam.reset_to_defaults()

Or find a specific camera:

cam = duvc.find_camera("Logitech")
cam.brightness = 80
cam.close()

2. Result-Based API (Advanced)

Use when: You need explicit error handling, detailed diagnostics, or building production systems.

Result types provide detailed error information without exceptions:

import duvc_ctl as duvc

devices = duvc.list_devices()
if not devices:
    print("No cameras found")
else:
    device = devices[0]
    camera_result = duvc.open_camera(device)
    
    if camera_result.is_ok():
        camera = camera_result.value()
        
        # Set property with explicit error checking
        setting = duvc.PropSetting(100, duvc.CamMode.Manual)
        result = camera.set(duvc.CamProp.Pan, setting)
        
        if result.is_ok():
            print("Pan set successfully")
        else:
            error = result.error()
            print(f"Error: {error.description()}")
    else:
        print(f"Failed to open camera: {camera_result.error().description()}")

API Comparison

Feature Pythonic Result-Based
Device selection Automatic Manual
Error handling Exceptions Result types
Code verbosity Minimal Explicit
Learning curve Easy Moderate
Production ready Yes Yes
Diagnostics Basic Detailed

Quick Start — Pythonic API

import duvc_ctl as duvc

# List cameras
cameras = duvc.list_cameras()
print(f"Found {len(cameras)} camera(s): {cameras}")

# Connect and control
with duvc.CameraController() as cam:
    print(f"Connected to: {cam.device_name}")
    
    # Check supported properties
    supported = cam.get_supported_properties()
    print(f"Camera properties: {supported['camera']}")
    print(f"Video properties: {supported['video']}")
    
    # Video properties
    if 'brightness' in supported['video']:
        cam.brightness = 75
        cam.contrast = 60
        print(f"Brightness: {cam.brightness}")
    
    # PTZ properties
    if 'pan' in supported['camera']:
        cam.pan = 0      # Center
        cam.zoom = 100   # 1x zoom

Quick Start — Result-Based API

import duvc_ctl as duvc

devices = duvc.list_devices()
if devices:
    device = devices[0]
    
    # Open camera with explicit error handling
    result = duvc.open_camera(device)
    if result.is_ok():
        camera = result.value()
        
        # Get property with range
        range_result = camera.get_range(duvc.CamProp.Pan)
        if range_result.is_ok():
            pan_range = range_result.value()
            print(f"Pan range: {pan_range.min} to {pan_range.max}")
            
            # Set to center
            center = duvc.PropSetting(0, duvc.CamMode.Manual)
            result = camera.set(duvc.CamProp.Pan, center)

API Reference

Pythonic API — Classes

CameraController

High-level camera control with property-based access.

# Connect to first available camera
cam = duvc.CameraController()

# Connect to specific camera
cam = duvc.CameraController(device_index=1)
cam = duvc.CameraController(device_name="Logitech")

# Use as context manager (recommended)
with duvc.CameraController() as cam:
    cam.brightness = 80
    # Auto-closes camera

# Property access
cam.brightness = 75       # Set
value = cam.brightness    # Get
range_info = cam.get_property_range('brightness')

# Device info
print(cam.device_name)
print(cam.is_connected)

# Cleanup
cam.close()

Pythonic API — Device Discovery

# List camera names
cameras = duvc.list_cameras()

# Find camera by name pattern
cam = duvc.find_camera("Logitech")

# Get camera info
info = duvc.get_camera_info(0)

Result-Based API — Classes

Device

Represents a connected USB camera.

device.name   # Friendly name
device.path   # System path
device.is_valid()

Camera

Opened camera connection with explicit error handling.

result = duvc.open_camera(device)
if result.is_ok():
    camera = result.value()
    
    # All operations return Result types
    get_result = camera.get(duvc.CamProp.Pan)
    set_result = camera.set(duvc.CamProp.Pan, setting)
    range_result = camera.get_range(duvc.CamProp.Pan)

PropSetting

Property value and control mode.

setting = duvc.PropSetting(100, duvc.CamMode.Manual)
auto_setting = duvc.PropSetting(0, duvc.CamMode.Auto)
print(setting.value, setting.mode)

PropRange

Property constraints and defaults.

range_result = camera.get_range(duvc.CamProp.Pan)
if range_result.is_ok():
    prop_range = range_result.value()
    print(prop_range.min, prop_range.max, prop_range.step)

Result Types

# All Result types have the same pattern
result = camera.get(duvc.CamProp.Pan)

if result.is_ok():
    value = result.value()      # Get the value
else:
    error = result.error()      # Get the error
    print(error.description())

Property Enums

CamProp (Camera Properties)

Pan, Tilt, Roll, Zoom, Exposure, Iris, Focus, Privacy, 
ScanMode, Lamp, BacklightCompensation, DigitalZoom

VidProp (Video Properties)

Brightness, Contrast, Hue, Saturation, Sharpness, Gamma,
ColorEnable, WhiteBalance, BacklightCompensation, Gain,
DigitalMultiplier, DigitalMultiplierLimit, WhiteBalanceComponent, PowerLineFrequency

Control Modes

CamMode

  • Auto — Automatic adjustment
  • Manual — Manual control with specific values

Error Types

Pythonic API

Standard Python exceptions:

try:
    cam = duvc.CameraController()
except duvc.DeviceNotFoundError:
    print("No cameras found")
except duvc.PropertyNotSupportedError:
    print("Property not supported")

Result-Based API

Result type checking with no exceptions:

result = duvc.open_camera(device)
if result.is_ok():
    camera = result.value()
else:
    error = result.error()
    code = error.code()           # Get error code
    description = error.description()  # Get description

Exception Types (Both APIs)

  • DuvcError — Base exception for all errors
  • DeviceNotFoundError — Camera disconnected or not found
  • DeviceBusyError — Camera in use by another application
  • PropertyNotSupportedError — Property not supported by camera
  • InvalidValueError — Property value out of range
  • PermissionDeniedError — Insufficient permissions
  • SystemError — Windows/DirectShow system error

Examples

Property Enumeration

with duvc.CameraController() as cam:
    # Get supported properties
    props = cam.get_supported_properties()
    
    print("Camera properties:")
    for prop in props['camera']:
        print(f"  - {prop}")
    
    print("Video properties:")
    for prop in props['video']:
        print(f"  - {prop}")

PTZ Control

with duvc.CameraController() as cam:
    # Absolute positioning
    cam.pan = 0      # Center
    cam.tilt = 0
    
    # Relative movement
    cam.pan_relative(15)   # Move 15 degrees right
    cam.zoom_relative(2)   # Zoom in 2 steps
    
    # Get current values
    print(f"Pan: {cam.pan}°, Tilt: {cam.tilt}°, Zoom: {cam.zoom}")

Preset Configuration

with duvc.CameraController() as cam:
    # Apply built-in preset
    cam.apply_preset('daylight')
    
    # Create custom preset
    config = {
        'brightness': 75,
        'contrast': 60,
        'saturation': 80
    }
    cam.create_custom_preset('my_preset', config)
    
    # Apply custom preset
    cam.apply_preset('my_preset')

Batch Operations

with duvc.CameraController() as cam:
    # Set multiple properties at once
    settings = {
        'brightness': 80,
        'contrast': 65,
        'saturation': 75
    }
    results = cam.set_multiple(settings)
    
    # Get multiple properties at once
    values = cam.get_multiple(['brightness', 'contrast', 'saturation'])

Vendor Properties

import uuid
import duvc_ctl as duvc

device = duvc.list_devices()[0]

# Read vendor property
vendor_guid = uuid.UUID('12345678-1234-5678-9abc-123456789abc')
success, data = duvc.read_vendor_property(device, vendor_guid, 1)
if success:
    print(f"Property data: {data.hex()}")

# Write vendor property
success = duvc.write_vendor_property(device, vendor_guid, 1, b'\\x01\\x02\\x03')

Error Handling Patterns

# Pythonic API - with exceptions
try:
    with duvc.CameraController() as cam:
        cam.brightness = 999  # Out of range
except duvc.InvalidValueError as e:
    print(f"Invalid value: {e}")

# Result-Based API - explicit checking
result = duvc.open_camera(device)
if result.is_ok():
    camera = result.value()
    set_result = camera.set(duvc.CamProp.Pan, setting)
    if not set_result.is_ok():
        print(f"Failed: {set_result.error().description()}")

Requirements

  • Windows 10+ (x64)
  • Python 3.8+
  • No additional drivers or SDKs required

Performance

  • Native C++ backend with DirectShow for optimal performance
  • Thread-safe for concurrent access
  • Minimal overhead — thin Python wrapper over C++ core

Other Interfaces

  • C++ Library — Native API for C++ applications
  • CLI Toolduvc-cli.exe for scripting and automation

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

duvc_ctl-2.1.0.tar.gz (55.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

duvc_ctl-2.1.0-cp312-cp312-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.12Windows x86-64

duvc_ctl-2.1.0-cp311-cp311-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.11Windows x86-64

duvc_ctl-2.1.0-cp310-cp310-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.10Windows x86-64

duvc_ctl-2.1.0-cp39-cp39-win_amd64.whl (1.3 MB view details)

Uploaded CPython 3.9Windows x86-64

duvc_ctl-2.1.0-cp38-cp38-win_amd64.whl (1.3 MB view details)

Uploaded CPython 3.8Windows x86-64

File details

Details for the file duvc_ctl-2.1.0.tar.gz.

File metadata

  • Download URL: duvc_ctl-2.1.0.tar.gz
  • Upload date:
  • Size: 55.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for duvc_ctl-2.1.0.tar.gz
Algorithm Hash digest
SHA256 a29405dae537718a927953537ad89efb35addfb625695d80c8362dac46fc4891
MD5 17f3cd7835edb24003ec214485a5b1e3
BLAKE2b-256 d39a1ee83c72ba0954e329c4a93a79c2be8cd4fecf56102d12fa2c6daa848369

See more details on using hashes here.

Provenance

The following attestation bundles were made for duvc_ctl-2.1.0.tar.gz:

Publisher: build-and-publish.yml on allanhanan/duvc-ctl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duvc_ctl-2.1.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: duvc_ctl-2.1.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for duvc_ctl-2.1.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 e34a6f81f885f06106edea1886b1c7bc50ce4760df17073f534de53fe1011345
MD5 fd2b7269627c02c037ec168baa978a34
BLAKE2b-256 cf439ec11093c0cf2d9bb1e0643d34c4a56c69289cded916537bea4625a86f77

See more details on using hashes here.

Provenance

The following attestation bundles were made for duvc_ctl-2.1.0-cp312-cp312-win_amd64.whl:

Publisher: build-and-publish.yml on allanhanan/duvc-ctl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duvc_ctl-2.1.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: duvc_ctl-2.1.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for duvc_ctl-2.1.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 745b4bc7f3776081132d6dc402cdc0c3afa47fd150c58fcfedf4119a930e4f54
MD5 d823b984f82cc4a497225314033fff86
BLAKE2b-256 949c1d15402824d0b9ecbe18a32ea1053a08baab7058af22fd20b4ed0c3c3b43

See more details on using hashes here.

Provenance

The following attestation bundles were made for duvc_ctl-2.1.0-cp311-cp311-win_amd64.whl:

Publisher: build-and-publish.yml on allanhanan/duvc-ctl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duvc_ctl-2.1.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: duvc_ctl-2.1.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for duvc_ctl-2.1.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 233875132dce195f10e06a16361cb2599d6bd03734409a3662e46f29edb7a9d2
MD5 5a75a2917b3235279015fc1934769ff7
BLAKE2b-256 000e338a7bfc7fc9144a06b45e7033b7a3ebc8807cd58e1d54089eeaec471db1

See more details on using hashes here.

Provenance

The following attestation bundles were made for duvc_ctl-2.1.0-cp310-cp310-win_amd64.whl:

Publisher: build-and-publish.yml on allanhanan/duvc-ctl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duvc_ctl-2.1.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: duvc_ctl-2.1.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for duvc_ctl-2.1.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 9607ff9c86104ced4e79100f3cf3be93fb9662365bbc0297b92574b51d3184e8
MD5 9a447ae39624168a7be42ed91455d292
BLAKE2b-256 da1b9d4310ca788d30474a956c8dffef276c79ce2dca708459e302bd30ec871c

See more details on using hashes here.

Provenance

The following attestation bundles were made for duvc_ctl-2.1.0-cp39-cp39-win_amd64.whl:

Publisher: build-and-publish.yml on allanhanan/duvc-ctl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duvc_ctl-2.1.0-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: duvc_ctl-2.1.0-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for duvc_ctl-2.1.0-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 c1c24a71faff158a399b7a6f534865468ab8aec5fa3415a5d2686d88a9616142
MD5 bc35db29e2493938392aa0a63554c27e
BLAKE2b-256 74d0b203629dfa72b7535864879b150a3866149b608e302910c484cc9a350c02

See more details on using hashes here.

Provenance

The following attestation bundles were made for duvc_ctl-2.1.0-cp38-cp38-win_amd64.whl:

Publisher: build-and-publish.yml on allanhanan/duvc-ctl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page