An almost-pure-Go library for accessing UVC devices. The library currently depends on libusb via cgo but not libuvc. One day this may change but libusb is much more complex.
The non-Go equivalent of this library is libuvc.
- UVC 1.5 support
- Input terminals (recording from cameras)
- Output terminals (displaying images on a device)
- Isochronous and bulk transfer support
- Android support
- Video decoding API
- Camera controls
- UAC Audio support
- UAC1 support
- Basic audio controls
- UAC2/3 support
go-uvc includes a debugging tool (the screenshot above) to connect to and debug cameras. To use it,
go run github.com/kevmo314/go-uvc/cmd/inspect -path /dev/bus/usb/001/002This project includes Docker support with USB device passthrough capabilities for accessing UVC devices from within containers.
docker build -t go-uvc .To run the container with USB device access, you need to use privileged mode and mount the USB bus:
# Run with full USB bus access (recommended for development)
docker run -it --rm \
--privileged \
--device=/dev/bus/usb:/dev/bus/usb \
-v /dev/bus/usb:/dev/bus/usb \
go-uvc \
/app/inspect -path /dev/bus/usb/001/002
# Run with specific USB device access
docker run -it --rm \
--device=/dev/bus/usb/001/002 \
go-uvc \
/app/inspect -path /dev/bus/usb/001/002To find your USB camera device path:
# List all USB devices
lsusb
# Find the bus and device number (e.g., Bus 001 Device 002)
# The path will be /dev/bus/usb/{bus}/{device}This project includes a DevContainer configuration for VS Code with USB passthrough support.
- Docker Desktop or Docker Engine
- VS Code with the Remote-Containers extension
- Open the project in VS Code
- When prompted, click "Reopen in Container" or use the command palette (F1) and select "Remote-Containers: Reopen in Container"
- The container will build with all necessary dependencies and USB access configured
- USB devices will be automatically available at
/dev/bus/usb/
# Build the development container
docker build -f .devcontainer/Dockerfile -t go-uvc-dev .
# Run the development container with USB access
docker run -it --rm \
--privileged \
--device=/dev/bus/usb:/dev/bus/usb \
-v /dev/bus/usb:/dev/bus/usb \
-v $(pwd):/workspace \
-w /workspace \
go-uvc-dev- Permission Denied: Make sure to run the container with
--privilegedflag - Device Not Found: Verify the device path with
lsusbon the host - Device Busy: Ensure no other application is using the USB device
- SELinux/AppArmor: On systems with SELinux or AppArmor, you may need additional configuration
A minimal example of how you might use go-uvc.
package main
import (
"image/jpeg"
"fmt"
"log"
"syscall"
"github.com/kevmo314/go-uvc"
"github.com/kevmo314/go-uvc/pkg/descriptors"
)
func main() {
fd, err := syscall.Open("/dev/bus/usb/001/002", syscall.O_RDWR, 0)
if err != nil {
panic(err)
}
ctx, err := uvc.NewUVCDevice(uintptr(fd))
if err != nil {
panic(err)
}
info, err := ctx.DeviceInfo()
if err != nil {
panic(err)
}
for _, iface := range info.StreamingInterfaces {
for i, desc := range iface.Descriptors {
fd, ok := desc.(*descriptors.MJPEGFormatDescriptor)
if !ok {
continue
}
frd := iface.Descriptors[i+1].(*descriptors.MJPEGFrameDescriptor)
resp, err := iface.ClaimFrameReader(fd.Index(), frd.Index())
if err != nil {
panic(err)
}
for i := 0; ; i++ {
fr, err := resp.ReadFrame()
if err != nil {
panic(err)
}
img, err := jpeg.Decode(fr)
if err != nil {
continue
}
// do something with img
}
}
}
}