Why is my USB camera not detected, or dropping out mid-recording?

Three separate camera problems get reported with the same sentence. This page splits them apart, explains why two cameras that each work alone can be impossible together, and covers the indexing habit that quietly puts your wrist camera in the scene column.

Connection · Last updated 2026-08-09

Symptom

A camera that works on its own disappears as soon as a second one is plugged in, or it appears in the list and delivers black frames, or it was camera 1 yesterday and camera 0 today.

Short answer

With two or more USB cameras the usual cause is bandwidth rather than a broken camera: several cameras streaming uncompressed video on one USB controller ask for more than the controller can carry, and the one that loses the race never starts. Move a camera to a port on a different controller or onto a powered hub, and identify cameras by their label rather than their index, because index numbers change between reboots. A camera that is listed but black is almost always held open by another process.

Three failures, one complaint

What you seeCauseFirst move
Works alone, vanishes when a second camera is plugged inUSB bandwidth on one shared controllerMove one camera to a different controller or a powered hub
Listed, but every frame is blackAnother process holds the cameraClose whatever opened it, only one process gets a camera
Was camera 1 yesterday, camera 0 todayEnumeration order is not stableSelect by label, never by number
Works for a few minutes, then drops outPower on a passive hub, or a marginal cablePowered hub, shorter cable, direct port
Never appears on any machine or portThe camera or its cableTest it in any other application first
Appears, but only at a low resolutionThe controller granted what was leftFree up bandwidth, then reconnect
bash
ay-robots devices

# SERIAL PORTS
#   /dev/ttyACM0   SO-100  (6 servos responding)
# CAMERAS
#   0  USB 2.0 Camera        1920x1080
#   1  HD Webcam             1280x720
The number in front of a camera is an enumeration position, not an identity.

Bandwidth is the usual answer

A USB camera that streams uncompressed frames reserves bandwidth on its controller for as long as it is open, whether or not anything is looking at the frames. The reservation is made up front, and if the controller cannot satisfy it, the camera does not start. That is the mechanism behind the most common report on this page: two cameras that each work perfectly on their own and refuse to work together.

The trap is that USB sockets are not independent. Several physical ports on a machine usually hang off one controller and share its budget, and which ports share is not something you can tell by looking at the case. Two ports right next to each other may be one controller; a port on the opposite side of the laptop is often a different one. This is why "I moved it to another port and nothing changed" is such a common second sentence.

The levers, roughly in order of how well they work: put the second camera on a genuinely different controller, add a powered hub so the hub arbitrates and supplies its own power, lower the resolution of whichever camera matters least, and prefer a camera that can deliver a compressed stream, since compressed video needs a fraction of the budget that raw frames do. Two cameras at moderate resolution is an ordinary setup that works on ordinary hardware. The difficulty scales with pixels per second, not with the number of devices.

bash
# Linux: which controller does each port hang off
lsusb -t

# Linux: what the kernel calls each camera, and its capabilities
v4l2-ctl --list-devices

# The platform view of the same hardware
ay-robots devices
lsusb -t is the fastest way to find out whether two ports are really independent.

Camera indexes are not identities

The number in front of a camera is the order in which the operating system happened to enumerate it. Reboot the machine, plug the arm in before the camera instead of after, or wake from sleep with a hub attached, and the numbers can rearrange. Nothing warns you, because from the system’s point of view nothing went wrong.

The consequence for recording is expensive and delayed. If your wrist camera was 1 on Monday and 0 on Wednesday, and both sessions went into the same dataset by index, then half your episodes have the wrist view in the scene column and the other half do not. Nothing crashes. Training runs. The policy is asked to make sense of two contradictory views of the world and does poorly, and the cause is three weeks upstream by the time you look for it.

Label the cameras once and use the labels everywhere. The recording command takes camera names, and those names are what end up in the dataset column names, so a consistent label is what makes a dataset portable across sessions and machines.

bash
ay-robots record --task "pick up the red cube and place it in the bowl" \
  --dataset cube_pick \
  --episodes 10 \
  --cameras wrist,top
The labels wrist and top are what appear in the dataset, regardless of which index the system assigned today.
Name the cameras once, then stop thinking about numbers

Set the label when you first add a camera and keep it for the life of the project. Index numbers are fine for a quick look at what is plugged in and wrong for anything you intend to keep.

Only one process gets the camera

In practice a camera is exclusive: the first process to open it holds it, and everything after that is refused or handed nothing. The refusal is rarely reported as clearly as it should be, so the second consumer typically shows the camera in its list and then produces black frames, which reads as a broken camera.

The usual holders are a video call application minimized in the background, a browser tab that was granted camera permission and never released it, a preview window you opened yourself and forgot, and an earlier instance of the client that did not exit cleanly. Two backends running at once do it to each other as well, so it is worth confirming there is only one.

bash
# Is a backend already running on this machine
ay-robots status

# After closing the other consumers, rescan
ay-robots devices

Work through it in this order

  1. 1
    Scan and note what is actually listed

    A camera that is missing from the list and a camera that is listed but black are different problems. Do not skip this distinction, it halves the search.

    bash
    ay-robots devices
  2. 2
    Unplug every camera but the failing one

    If it works alone, the camera is fine and you have a bandwidth or contention problem. If it fails alone on a known-good port, the camera or its cable is the suspect.

  3. 3
    Close everything else that could hold a camera

    Video calls, browser tabs with camera permission, any preview window, any second copy of the client. Then rescan before changing anything physical.

  4. 4
    Move the camera to a port on the other side of the machine

    You are trying to land on a different controller. On Linux, lsusb -t tells you whether you succeeded instead of leaving you to guess.

  5. 5
    Put it on a powered hub

    A powered hub supplies its own current and often resolves both the bandwidth contention and the slow dropouts that come from a laptop port supplying two cameras and an arm adapter.

  6. 6
    Shorten the cable, remove extensions

    Long unpowered extensions are a leading cause of "worked for five minutes then stopped". Test with the shortest cable you own before concluding anything about the camera.

  7. 7
    Reduce the pixel rate

    Lower the resolution of the camera that contributes least, or use one that delivers a compressed stream. This is the lever that makes an over-subscribed controller viable without buying anything.

  8. 8
    Fix the labels, then record one throwaway episode

    Confirm that the labels you expect appear in the recording before you commit a session to it. One test episode is cheap; discovering a swapped camera after fifty is not.

    bash
    ay-robots record --task "camera check" --episodes 1 --cameras wrist,top
A hub power supply is not a servo power supply

Adding a powered hub puts another brick on your desk, and desks with several bricks are where the expensive mistake happens. Feetech STS3215 servos run at 7.4 V and 12 V destroys them in seconds. Label the hub supply and the arm supply so that a tired hand at the back of the desk cannot confuse them.

What a dropout does to an episode

The client timestamps each stream and keeps them aligned, so a camera that stops delivering does not silently smear frames across the gap. What you get instead is an episode with missing coverage during the interesting part, which is worth exactly nothing as training data even though it costs the same disk space. Review episodes before you keep them, and throw away anything recorded during a session where a camera was dropping. The reasoning behind the review habit is on /learn/record-your-first-dataset, and the composition of a usable dataset is on /so-100/data-collection.

Frequently asked questions

How many cameras can I use at once?

Two is the common setup and it works on ordinary hardware. Beyond two you are managing bandwidth on purpose: separate controllers, compressed streams, and resolutions chosen deliberately rather than left at whatever the camera offers.

The camera works in a video call but not here. Why?

Two reasons, and both can apply. Call applications typically request a lower resolution or a compressed format, which fits where a raw stream does not. And if the call application is still running, it is holding the camera, so nothing else can open it.

Does the camera index end up in my dataset?

No, the label does. That is exactly why the label is worth setting once and keeping: it is stable across reboots and across machines, while the index is neither.

Can I move a camera to a better position halfway through a dataset?

Not without splitting the dataset. A policy learns the mapping from pixels to actions, so moving the camera invalidates everything recorded before the move in the same way that nudging a tripod does.

Do I need a wrist camera at all?

You can record with one scene camera and get a working pipeline. A wrist view earns its place at the moment of the grasp, when the gripper occludes the object from any camera that is not on the wrist.

My camera is fine but the arm disappeared when I added the second camera.

Then the serial adapter and the cameras are sharing a controller and the cameras took the budget. Move the arm adapter to a port on a different controller, or move the cameras onto a powered hub and leave the adapter directly on the machine.