API Reference

libusb_uvc Package

Public interface for the libusb_uvc package.

The implementation lives in libusb_uvc.core. This module simply re-exports the public API defined in libusb_uvc.core.__all__ so that existing from libusb_uvc import ... statements keep working while the code base is refactored into smaller modules.

class libusb_uvc.AltSettingInfo(alternate_setting: int, endpoint_address: int | None, endpoint_attributes: int | None, max_packet_size: int)[source]

Bases: object

Information about an alternate streaming interface setting.

is_isochronous() bool[source]
alternate_setting: int
endpoint_address: int | None
endpoint_attributes: int | None
max_packet_size: int
class libusb_uvc.CapturedFrame(payload: bytes | bytearray, format: ~libusb_uvc.core.StreamFormat, frame: ~libusb_uvc.core.FrameInfo | ~libusb_uvc.core.StillFrameInfo, fid: int, pts: int | None, timestamp: float = <factory>, sequence: int = 0, decoded: object | None = None)[source]

Bases: object

Container returned by UVCCamera.read_frame() and asynchronous streams.

decoded: object | None = None
sequence: int = 0
to_bgr()[source]
to_bytes() bytes[source]
to_rgb()[source]
payload: bytes | bytearray
format: StreamFormat
frame: FrameInfo | StillFrameInfo
fid: int
pts: int | None
timestamp: float
class libusb_uvc.StreamStats(frames_completed: int = 0, frames_dropped: int = 0, bytes_delivered: int = 0, last_frame_duration_s: float | None = None, average_frame_duration_s: float | None = None, measured_frames: int = 0, last_drop_reason: str | None = None)[source]

Bases: object

Cumulative counters describing a stream’s behaviour.

average_frame_duration_s: float | None = None
bytes_delivered: int = 0
frames_completed: int = 0
frames_dropped: int = 0
last_drop_reason: str | None = None
last_frame_duration_s: float | None = None
measured_frames: int = 0
class libusb_uvc.FrameInfo(frame_index: int, width: int, height: int, default_interval: int, intervals_100ns: List[int], max_frame_size: int, bm_capabilities: int = 0)[source]

Bases: object

Frame descriptor summary collected from a VS frame descriptor.

bm_capabilities: int = 0
property intervals: List[float]

Backward compatibility alias returning frame intervals in Hz.

intervals_hz() List[float][source]
pick_interval(target_fps: float | None, *, strict: bool = False, tolerance_hz: float = 0.001) int[source]

Return the closest advertised frame interval to target_fps.

property supports_still: bool

Return True when the frame advertises still-image support.

frame_index: int
width: int
height: int
default_interval: int
intervals_100ns: List[int]
max_frame_size: int
class libusb_uvc.StreamFormat(description: str, format_index: int, subtype: int, guid: bytes, frames: ~typing.List[~libusb_uvc.core.FrameInfo] = <factory>, still_frames: ~typing.List[~libusb_uvc.core.StillFrameInfo] = <factory>)[source]

Bases: object

A Video Streaming format along with its advertised frames.

description: str
format_index: int
subtype: int
guid: bytes
frames: List[FrameInfo]
still_frames: List[StillFrameInfo]
class libusb_uvc.StreamingInterface(interface_number: int, formats: ~typing.List[~libusb_uvc.core.StreamFormat] = <factory>, alt_settings: ~typing.List[~libusb_uvc.core.AltSettingInfo] = <factory>)[source]

Bases: object

Grouping of the per-interface formats and alternate settings.

find_alt_by_endpoint(endpoint_address: int) AltSettingInfo | None[source]
find_frame(width: int, height: int, *, format_index: int | None = None, subtype: int | None = None) Tuple[StreamFormat, FrameInfo] | None[source]
find_still_frame(width: int, height: int, *, format_index: int | None = None, subtype: int | None = None) Tuple[StreamFormat, FrameInfo] | None[source]
get_alt(alternate_setting: int) AltSettingInfo | None[source]
iter_still_frames() Iterator[Tuple[StreamFormat, FrameInfo]][source]
select_alt_for_payload(required_payload: int) AltSettingInfo | None[source]
interface_number: int
formats: List[StreamFormat]
alt_settings: List[AltSettingInfo]
class libusb_uvc.ControlEntry(interface_number: int, unit_id: int, selector: int, name: str, type: str, info: int, minimum: int | None, maximum: int | None, step: int | None, default: int | None, length: int | None, raw_minimum: bytes | None = None, raw_maximum: bytes | None = None, raw_step: bytes | None = None, raw_default: bytes | None = None, metadata: ~typing.Dict[str, object] = <factory>)[source]

Bases: object

Rich metadata describing a validated UVC control.

is_readable() bool[source]
is_writable() bool[source]
raw_default: bytes | None = None
raw_maximum: bytes | None = None
raw_minimum: bytes | None = None
raw_step: bytes | None = None
interface_number: int
unit_id: int
selector: int
name: str
type: str
info: int
minimum: int | None
maximum: int | None
step: int | None
default: int | None
length: int | None
metadata: Dict[str, object]
class libusb_uvc.UVCControl(unit_id: int, selector: int, name: str, type: str)[source]

Bases: object

Represents a discovered UVC control.

unit_id: int
selector: int
name: str
type: str
class libusb_uvc.UVCUnit(unit_id: int, type: str, controls: List[UVCControl])[source]

Bases: object

Represents a Unit in the Video Control topology.

unit_id: int
type: str
controls: List[UVCControl]
class libusb_uvc.ExtensionUnit(unit_id: int, type: str, controls: List[UVCControl], guid: str)[source]

Bases: UVCUnit

Represents an Extension Unit with its specific GUID.

guid: str
class libusb_uvc.UVCCamera(device: Device, interface: StreamingInterface)[source]

Bases: object

Minimal helper to configure a streaming interface and fetch frames.

property active_alt_setting: int

Return the currently selected alternate setting (0 when idle).

capture_still_image(*, timeout_ms: int = 2000) CapturedFrame[source]

Trigger and fetch a single still image using the negotiated settings.

close() None[source]
configure_resolution(width: int, height: int, *, preferred_format_index: int | None = None, preferred_subtype: int | None = None, frame_rate: float | None = None, alt_setting: int | None = None) dict[source]

Convenience wrapper selecting a frame by its width/height.

configure_still_image(*, width: int | None = None, height: int | None = None, codec: CodecPreference = 'auto', format_index: int | None = None, frame_index: int | None = None, compression_index: int = 1) dict[source]

Probe and commit still-image parameters for a future capture.

configure_stream(stream_format: StreamFormat, frame: FrameInfo, frame_rate: float | None = None, alt_setting: int | None = None, *, strict_fps: bool = False) dict[source]

Probe and commit the requested format/frame, preparing for streaming.

property current_format: StreamFormat | None
property current_frame: FrameInfo | None
property current_resolution: Tuple[int, int] | None
property endpoint_address: int | None

USB endpoint address used for streaming (None if not configured).

enumerate_controls(*, refresh: bool = False) List[ControlEntry][source]
classmethod from_device(device: Device, interface_number: int) UVCCamera[source]
get_control(key: str | Tuple[int, int] | Tuple[int, int, int] | ControlEntry | UVCControl, *, raw: bool = False, interface_hint: int | None = None) int | bytes | None[source]
get_stream_stats() StreamStats[source]

Return a snapshot of synchronous capture statistics.

property max_payload_size: int | None

Maximum payload size requested when reading packets.

classmethod open(*, vid: int | None = None, pid: int | None = None, device_index: int = 0, interface: int = 1) UVCCamera[source]
poll_async_events(timeout: float = 0.1) None[source]
read_frame(timeout_ms: int = 1000, *, overall_timeout_ms: int | None = None) CapturedFrame[source]

Read a single video frame from the streaming endpoint.

read_vc_control(unit_id: int, selector: int, request: int, length: int, interface_number: int | None = None) bytes | None[source]

Read a Video Control value even while an async stream is active.

select_still_image(*, width: int | None = None, height: int | None = None, codec: CodecPreference = 'auto', format_index: int | None = None, frame_index: int | None = None) Tuple[StreamFormat, FrameInfo | StillFrameInfo][source]

Resolve a still-image capable format/frame pairing.

select_stream(*, width: int | None = None, height: int | None = None, codec: CodecPreference = 'auto', format_index: int | None = None, frame_index: int | None = None) Tuple[StreamFormat, FrameInfo][source]

Resolve a streaming format/frame pairing using either dimensions or indexes.

set_control(key: str | Tuple[int, int] | Tuple[int, int, int] | ControlEntry | UVCControl, value: int | bytes | bytearray, *, raw: bool = False, interface_hint: int | None = None) None[source]
start_async_stream(packet_callback: Callable[[bytes], None], *, transfers: int = 8, packets_per_transfer: int = 32, timeout_ms: int = 1000) None[source]

Start ISO streaming with robust VC polling keep-alive.

stop_async_stream() None[source]
stop_streaming() None[source]

Return the interface to its idle state.

stream(*, width: int | None = None, height: int | None = None, codec: CodecPreference = 'auto', decoder: str | DecoderPreference | Iterable[str] | None = 'auto', format_index: int | None = None, frame_index: int | None = None, frame_rate: float | None = None, strict_fps: bool = False, queue_size: int = 4, skip_initial: int = 2, transfers: int = 16, packets_per_transfer: int = 64, timeout_ms: int = 2000, duration: float | None = None, record_to: str | Path | None = None) FrameStream[source]

Return a managed frame iterator for continuous streaming.

Parameters

decoder:

Optional decoder backend preference for frame-based codecs (for example H.264/H.265). Use DecoderPreference.NONE to keep raw payloads and defer decoding. MJPEG and uncompressed formats ignore this setting.

record_to:

Optional file path for writing the compressed payloads (requires a decoder backend that supports recording).

write_vc_control(unit_id: int, selector: int, payload: bytes, request: int = 1, interface_number: int | None = None) None[source]

Write a Video Control value even while an async stream is active.

class libusb_uvc.FrameStream(camera: UVCCamera, stream_format: StreamFormat, frame: FrameInfo, frame_rate: float | None, *, strict_fps: bool, queue_size: int, skip_initial: int, transfers: int, packets_per_transfer: int, timeout_ms: int, duration: float | None, decoder_preference: str | DecoderPreference | Iterable[str] | None = None, record_path: str | Path | None = None)[source]

Bases: object

Context manager and iterator yielding CapturedFrame objects.

close() None[source]
property stats: StreamStats

Return a snapshot of the accumulated stream statistics.

exception libusb_uvc.UVCError[source]

Bases: RuntimeError

Raised when the camera reports unexpected errors.

class libusb_uvc.CodecPreference[source]

Bases: str

Simple codec discriminator used when selecting a stream format.

AUTO = 'auto'
FRAME_BASED = 'frame-based'
H264 = 'h264'
H265 = 'h265'
MJPEG = 'mjpeg'
YUYV = 'yuyv'
class libusb_uvc.DecoderPreference[source]

Bases: str

Optional decoder selection for compressed payloads.

AUTO = 'auto'
GSTREAMER = 'gstreamer'
NONE = 'none'
PYAV = 'pyav'
libusb_uvc.describe_device(dev: Device) str[source]

Human readable summary of vendor/product/serial info.

libusb_uvc.find_uvc_devices(vid: int | None = None, pid: int | None = None) List[Device][source]

Return every USB device that looks like a UVC camera.

libusb_uvc.iter_video_streaming_interfaces(dev: Device) Iterator[Interface][source]

Yield every interface whose class/subclass matches UVC streaming.

libusb_uvc.list_streaming_interfaces(dev: Device) Dict[int, StreamingInterface][source]

Build StreamingInterface descriptions for dev.

libusb_uvc.list_control_units(dev: Device) Dict[int, List[UVCUnit]][source]

Build UVCUnit descriptions for all Video Control interfaces on dev.

We try to detach the VC interface from the kernel driver (uvcvideo) so that user-space control transfers work even when the module is loaded.

libusb_uvc.parse_vs_descriptors(extra: bytes) List[StreamFormat][source]

Parse the raw extra_descriptors blob for a VS interface.

libusb_uvc.perform_probe_commit(dev: Device, interface_number: int, stream_format: StreamFormat, frame: FrameInfo, frame_rate: float | None, do_commit: bool, bm_hint: int = 1, *, strict_interval: bool = False, payload_hint: int = 0) dict[source]

Try multiple control lengths when running VS_PROBE/VS_COMMIT.

libusb_uvc.perform_still_probe_commit(dev: Device, interface_number: int, stream_format: StreamFormat, frame: FrameInfo, compression_index: int = 1, do_commit: bool = True) dict[source]
libusb_uvc.probe_streaming_interface(dev: Device, interface_number: int, stream_format: StreamFormat, frame: FrameInfo, frame_rate: float | None, do_commit: bool, alt_setting: int | None, keep_alt: bool = False, *, strict_interval: bool = False, payload_hint: int = 0) dict[source]

Claim interface_number and run VS_PROBE/VS_COMMIT.

When alt_setting is provided and do_commit is true, the function selects that alternate setting after the commit. If keep_alt is false (default) the interface is switched back to alternate 0 before returning so that enumeration scripts leave the camera untouched. Streaming code can set keep_alt to True and manage the lifecycle manually.

libusb_uvc.select_format_and_frame(formats: List[StreamFormat], format_index: int | None, frame_index: int | None) Tuple[StreamFormat, FrameInfo][source]

Resolve CLI overrides to a concrete (format, frame) tuple.

libusb_uvc.resolve_stream_preference(interface: StreamingInterface, width: int, height: int, codec: str = 'auto') Tuple[StreamFormat, FrameInfo][source]

Select a (format, frame) tuple based on resolution and codec preference.

codec may be one of auto (YUYV → MJPEG → frame-based), yuyv, mjpeg, frame-based, h264 or h265. The frame-based variants filter UVC VS_FORMAT_FRAME_BASED descriptors, matching on the reported description when a specific codec is requested. Raises UVCError if the requested combination does not exist.

libusb_uvc.resolve_still_preference(interface: StreamingInterface, width: int, height: int, codec: str = 'auto') Tuple[StreamFormat, FrameInfo | StillFrameInfo][source]
libusb_uvc.yuy2_to_rgb(payload: bytes, width: int, height: int)[source]

Convert a single YUY2 frame into an RGB numpy.ndarray.

The function imports numpy lazily so that users who only need the descriptor utilities do not have to install it.

libusb_uvc.decode_to_rgb(payload: bytes, stream_format: StreamFormat, frame: FrameInfo)[source]

Convert a raw payload into an RGB image (numpy array).

Supports YUY2/YUYV and MJPEG. Raises RuntimeError if decoding is not possible due to missing dependencies (e.g. OpenCV for MJPEG).

libusb_uvc.find_vc_interface_number(dev: Device) int[source]

Return the interface number of the first VC interface (class 0x0e, subclass 0x01).

libusb_uvc.claim_vc_interface(dev: Device, vc_if: int, *, auto_reattach: bool = True, auto_detach: bool | None = None)[source]

Detach only the VC interface from the kernel, claim it, then release and reattach.

libusb_uvc.vc_ctrl_get(dev: Device, vc_if: int, unit_id: int, selector: int, request: int, length: int)[source]

Low level VC GET_* (GET_CUR/MIN/MAX/RES/DEF/INFO/LEN).

libusb_uvc.vc_ctrl_set(dev: Device, vc_if: int, unit_id: int, selector: int, payload: bytes)[source]

Low level VC SET_CUR.

libusb_uvc.read_vc_control_value(dev: Device, vc_if: int, unit_id: int, selector: int, request: int, *, length_hint: int = 64)[source]

Read a VC control using GET_LEN if available, else length_hint.

libusb_uvc.write_vc_control_value(dev: Device, vc_if: int, unit_id: int, selector: int, payload: bytes)[source]
class libusb_uvc.UVCControlsManager(device: Device, units: List[UVCUnit], interface_number: int | None = None)[source]

Bases: object

Validate UVC controls and enrich them with quirks metadata.

get_controls() List[ControlEntry][source]
libusb_uvc.load_quirks() Dict[str, dict][source]

Load per-GUID control definitions from the packaged quirks directory.

class libusb_uvc.StereoCameraConfig(vid: int, pid: int, device_index: int | None = None, device_sn: str | None = None, device_path: Tuple[int, Tuple[int, ...]] | None = None, interface: int = 1, width: int = 640, height: int = 480, codec: CodecPreference = 'auto', decoder: DecoderPreference = 'auto', frame_rate: float | None = None, strict_fps: bool = False, skip_initial: int = 0, queue_size: int = 6, timeout_ms: int = 3000)[source]

Bases: object

Description of a single camera used in a stereo pair.

codec: CodecPreference = 'auto'
decoder: DecoderPreference = 'auto'
device_index: int | None = None
device_path: Tuple[int, Tuple[int, ...]] | None = None
device_sn: str | None = None
frame_rate: float | None = None
height: int = 480
interface: int = 1
queue_size: int = 6
skip_initial: int = 0
strict_fps: bool = False
timeout_ms: int = 3000
width: int = 640
vid: int
pid: int
class libusb_uvc.StereoCapture(left: StereoCameraConfig, right: StereoCameraConfig, *, sync_window_ms: float = 2.0, drop_window_ms: float = 10.0, prefer_hardware_pts: bool = False, calibration_pairs: int = 30)[source]

Bases: object

Synchronise two UVCCamera streams and yield paired frames.

close() None[source]
property stats: StereoStats
class libusb_uvc.StereoFrame(left: CapturedFrame, right: CapturedFrame, delta_ms: float, timestamp_left: float, timestamp_right: float, hardware_offset_ms: float | None = None)[source]

Bases: object

Pair of frames captured within the synchronisation window.

hardware_offset_ms: float | None = None
left: CapturedFrame
right: CapturedFrame
delta_ms: float
timestamp_left: float
timestamp_right: float
class libusb_uvc.StereoStats(paired: int = 0, left_dropped: int = 0, right_dropped: int = 0, max_delta_ms: float = 0.0, avg_delta_ms: float | None = None, last_delta_ms: float | None = None)[source]

Bases: object

Aggregated statistics for a stereo capture session.

avg_delta_ms: float | None = None
last_delta_ms: float | None = None
left_dropped: int = 0
max_delta_ms: float = 0.0
paired: int = 0
right_dropped: int = 0

Asynchronous Backend

Asynchronous UVC packet reader built on top of libusb1.

The default PyUSB API only exposes synchronous read calls which block per packet. For high-bandwidth YUYV streams the camera quickly overflows unless we keep several URBs in flight. libusb1 exposes the necessary primitives to submit multiple transfers and to inspect each ISO packet individually. This module provides a tiny wrapper around that API so the rest of the project can consume decoded packets without worrying about the USB plumbing.

class libusb_uvc.uvc_async.IsoConfig(endpoint: 'int', packet_size: 'int', transfers: 'int' = 8, packets_per_transfer: 'int' = 32, timeout_ms: 'int' = 1000)[source]

Bases: object

endpoint: int
packet_size: int
transfers: int = 8
packets_per_transfer: int = 32
timeout_ms: int = 1000
class libusb_uvc.uvc_async.InterruptConfig(endpoint: 'int', packet_size: 'int', timeout_ms: 'int' = 1000)[source]

Bases: object

endpoint: int
packet_size: int
timeout_ms: int = 1000
class libusb_uvc.uvc_async.InterruptListener(context: USBContext, handle: USBDeviceHandle, config: InterruptConfig, callback: Callable[[bytes], None] | None = None)[source]

Bases: object

Simple interrupt-IN listener for VC notifications.

start() None[source]
stop() None[source]
class libusb_uvc.uvc_async.UVCPacketStream(context: USBContext, handle: USBDeviceHandle, config: IsoConfig, callback: Callable[[bytes], None])[source]

Bases: object

Manage an asynchronous ISO stream, invoking a callback per packet.

The callback receives the raw bytes of each isochronous packet (including UVC headers). The consumer is responsible for parsing the UVC headers and reassembling complete frames.

start() None[source]
stop() None[source]
handle_events_and_resubmit(timeout_us: int) None[source]
is_active() bool[source]