System designTroubleshooting

Two identical USB cameras: same name, open one by port

Two identical USB cameras share one name, so selecting by name or index always opens the first device. Open each camera by its USB port path instead.

LumaSpec Vision11 min read Share on LinkedIn

On this page 9 sections
  1. 01Why do two identical USB cameras always open as the same one?
  2. 02Which identifier actually tells the two cameras apart?
  3. 03How do I find each camera's port path on my machine?
  4. 04How do I open each camera by its path in code?
  5. 05Will both cameras stream at the same time once they open?
  6. 06Can I rely on the index or the serial number instead?
  7. 07When is a pair of GigE cameras the easier answer?
  8. 08What checks keep the mapping stable before the panel closes?
  9. 09Questions

You enumerate your capture devices and the list shows the same camera name twice. You select the second entry, and you still get the first camera's picture. That is not a wiring fault: two identical USB cameras report one identical friendly name, so every selection made by name or index resolves to the same first device. This page gives you the fix. You will find each camera's USB port path, open the cameras by path instead of by name, prove the mapping with a connector-swap test, and budget the pair's combined USB bandwidth before the panel closes. It is written for anyone wiring two matching board-level cameras or area scan cameras into one application: stereo rigs, over-view plus detail stations, front-and-back inspection.

Why do two identical USB cameras always open as the same one?

Because enumeration lists cameras by the friendly name string each one reports, and two identical units report one identical string, every selection made by name or by index resolves to the first device the operating system registered — asking for entry 1 hands back camera 0.

The friendly name is not an address. It is a descriptor string the camera firmware reports, so two cameras built from the same design carry the same string, byte for byte. The index is weaker still: it is an entry's position in the list your library assembled this session, which depends on when each device registered. Neither value points at one physical unit, so a name-based open hands you the same first camera every time, no matter which entry you pick.

The symptom test takes ten seconds: unplug one camera entirely and run the application again. If the "second" camera still opens and the picture does not change, you were never addressing two devices — you were opening the same one twice. UVC-class cameras often report a generic name in the first place, so a wrong or empty name can be its own fault; that case is fixed by reinstalling the device entry, as the generic UVC camera name and device-entry reinstall walkthrough describes.

Which identifier actually tells the two cameras apart?

The USB port path is the one identifier that differs out of the box: each physical connector sits at its own bus and hub port, so two identical cameras on two ports produce two distinct device paths, while their friendly names — and, on many modules, their serial numbers — match.

Identifier Where it comes from Unique for identical twins? Stable across a replug?
Friendly name Descriptor string the camera reports No — same design, same string Yes, but identical anyway
Index (0, 1, 2) Position in the library's session list No No — hot-plug and boot order change it
Serial number Descriptor string assigned per unit Only if each unit carries a distinct serial Yes — it travels with the camera
USB port path Where the camera is plugged: controller, hub, port Yes — one connector, one path With the port, not the camera
Numbered node (/dev/videoN) Kernel allocation order at probe time No No

Read the table as a decision, not as trivia. If both cameras report real, distinct serials, key your roles on the serial: it survives moving a camera to another connector. Check the serials first, because many USB camera modules ship with an empty or duplicated serial and leave nothing to key on. When serials fail — the common case with matching UVC modules — the port path is the only key that differs out of the box, and the price is discipline: the path belongs to the connector, so the cable going to a given port must stay there. For the enumeration side in more depth, the guide to USB port IDs that come out identical for every camera walks the same problem from the identification angle.

How do I find each camera's port path on my machine?

On Linux, list /dev/v4l/by-path/: one entry per camera, whose name encodes controller, bus, port chain and interface. On Windows, open Device Manager, the camera's Details tab, and read the device instance path, whose tail changes with the USB port.

A twin pair produces two entries that differ in the port field:

pci-0000:00:14.0-usb-0:2:1.0-video-index0
pci-0000:00:14.0-usb-0:3:1.0-video-index0

The leading block is the host controller's PCI address, so two entries sharing it sit on one controller and share its bandwidth budget — you will need that in a moment. The port field follows the physical connector: a camera behind a hub grows an extra dot in its port chain. The plain /dev/videoN numbers underneath can swap between boots, so treat the by-path name as the real name and the numbered node as disposable. When numbered nodes fight each other on a multi-camera Linux box, the device-path conflict fix for multiple USB cameras on Linux covers that failure directly.

On Windows, the device instance path starts with USB, carries the vendor and product IDs, and ends with the parent hub and the port number. Move the camera to the neighbouring connector and the tail changes — that change is how you map roles to ports. Neither reading needs admin rights, and both belong in your commissioning record.

How do I open each camera by its path in code?

Pass the by-path string, not an index, to the capture call: OpenCV's cv2.VideoCapture accepts a device path with cv2.CAP_V4L2 on Linux, which pins each role in your program to a physical connector instead of to whatever order the library enumerated this session.

import glob, csv, cv2

paths: list[str] = sorted(glob.glob("/dev/v4l/by-path/*video-index0"))  # 2 entries for the pair
roles: dict[str, str] = {}
with open("camera_ports.csv", newline="") as f:      # recorded at commissioning
    for role, path in csv.reader(f):
        roles[role] = path                           # "front" -> pci-0000:00:14.0-usb-0:2:1.0-video-index0

assert len(paths) == 2, f"expected 2 cameras, enumerated {len(paths)}"

cap_front = cv2.VideoCapture(roles["front"], cv2.CAP_V4L2)
cap_back  = cv2.VideoCapture(roles["back"],  cv2.CAP_V4L2)

ok_front: bool = cap_front.isOpened()
ok_back:  bool = cap_back.isOpened()
assert ok_front and ok_back, "open failed - stop, do not fall back to the first device"

The test that proves the mapping takes two minutes. Hold a printed target in front of the front camera and read one frame from each handle: the frame from the front handle shows the target. Now swap the two connectors on the panel and rerun without changing anything: the front handle still shows the target, because the path belongs to the port and the cameras traded paths. Run the same swap against index-based code and the roles exchange silently — the exact failure this page removes.

On Windows, capture enumeration follows driver install order, so the rule applies one level up: open by the device instance path. Every serious capture stack can enumerate device paths and build a capture source from one; a library that only accepts zero-based indexes cannot address identical twins reliably, so move the open to one that accepts paths or unique IDs. If the cameras do not appear at all, settle which capture path the software should use for a UVC camera before debugging identity.

Will both cameras stream at the same time once they open?

Opening both is only half the fix: the pair's combined payload must fit the USB controller it shares. A 4000 × 3000 image at 30 fps moves 12 MB per frame at 8 bits per pixel, so two such streams need about 720 MB/s — beyond one USB 3.0 port.

The LS-CMR-0166 streams 4000 × 3000 at 30 fps, so it makes the worked case:

12 MB/frame = 4000 × 3000 px × 1 byte per pixel (8-bit mono) 360 MB/s = 12 MB/frame × 30 fps 720 MB/s = 2 × 360 MB/s, the pair together

One USB 3.0 port is a 5 Gbps link; after 8b/10b line coding that is 400 MB/s at the wire, and protocol overhead leaves roughly 380–430 MB/s of usable payload. Budget each controller at 350 MB/s and the decision writes itself: 720 MB/s cannot share one controller, so give each camera its own host controller, or cut the pair's combined rate below 350 MB/s by trimming frame rate or resolution. Entries sharing a controller address in the by-path name share one budget; two different addresses mean two budgets. For the fuller accounting, the bandwidth and power budget for multiple USB cameras on one host covers shared-host planning, and when a USB hub drops the frame rate covers the failure the budget prevents.

For a build like that, a 12 MP area scan model and a 120 fps board camera are USB3 picks that sit cleanly in a two-controller layout.

Area scan cameras12 MP USB3 area scan camera, IMX226, 1/1.7" rolling shutter, 30 fps, 4000 × 3000 resolution (LS-CMR-0166)LS-CMR-0166
Sensor format
1/1.7"
Interface
USB3
$560.00View part
Board-level cameras3.1 MP USB3 board-level camera, IMX252, 1/1.8" global shutter, 120 fps (LS-BCM-0003)LS-BCM-0003
Sensor format
1/1.8"
Lens mount
C-mount
$690.00View part

Both are USB3 models, so the open-by-path pattern applies to the pair unchanged.

Can I rely on the index or the serial number instead?

Only with proof from your own machine: the index is the position in that boot's enumeration list and can change after a replug or a reboot, and the serial number works only when each camera carries a distinct serial — many modules ship with empty or duplicated serials.

Rank the causes before touching code; in the order they turn out to be the whole story:

  1. Opened by name. The library matched the friendly string and always returned the first camera. Test: unplug one camera — if the "second" still opens, this is the cause. Fix: the path-based open above.
  2. Opened by index with the order assumed fixed. The index is that boot's list order. Test: replug both cameras and rerun; roles may swap. Fix: the same.
  3. Serial fallback unavailable. Both units report an empty or identical serial, so no unique-ID lookup can separate them. Test: read each camera's serial and compare. Fix: bind by port path.
  4. Both open but one stream stalls. The pair's payload exceeded one controller. Test: request full resolution and frame rate on both and watch the delivered frame counts. Fix: the controller split in the bandwidth section.

Each test takes under a minute, and working the list top down finds the cause in most two-camera rigs on the first pass.

When is a pair of GigE cameras the easier answer?

If identity problems keep coming back, GigE Vision cameras sidestep them: the standard gives every device a unique, persistent device ID, so your code selects cameras by ID instead of by connector, and what remains of multi-camera work is IP setup and link budgeting, not naming.

The trade is interface physics. One GigE link carries about 118 MB/s of usable payload against roughly 400 MB/s for USB 3.0, and 10GigE multiplies the GigE figure by ten; GigE runs reach 100 m on standard cabling, where USB stays short. So: two cameras with light streams on a short bench — USB with port paths stays the cheapest rig; two cameras whose combined payload busts one or even two USB controllers, or a rig that must survive connectors being moved — GigE or 10GigE with ID-based selection.

GigE brings its own twin-camera chores, covered where they live: the duplicate-name and IP fix for two identical GigE cameras on one PC, and the NIC port and bandwidth budget for two GigE cameras on one host. As a concrete pick, the MV-CU020-90GC is a 2.5 MP GigE camera with a global shutter.

Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
Up to 3 MP
$309.00View partBuild a system with it

What checks keep the mapping stable before the panel closes?

Run four tests before the machine ships: swap the connectors and confirm the roles follow the configuration, replug each camera and confirm the path comes back, cold-boot and confirm both open, then run both streams at full rate for thirty minutes with zero dropped frames.

Commissioning record

  • List both by-path entries and write role to path into camera_ports.csv before anything else.
  • Label each cable at both ends with its role and its port number.

Proof tests

  • Swap test: exchange the two connectors, rerun unchanged, and confirm the front role stays front.
  • Replug test: unplug and replug each camera in place; the same path must reappear.
  • Boot test: cold-reboot the machine and confirm both opens succeed.
  • Soak test: run both streams at target resolution and frame rate for 30 minutes with zero dropped frames.

Prevention

  • Never re-plumb a hub or move a connector after commissioning without recording the paths again.
  • Re-run the swap test after replacing any camera or cable.

That is the whole fix: two cameras that report one name are separated by the connector they sit on, opened by path, proved by a swap, and budgeted for bandwidth. If you are speccing a two-camera rig from scratch, shortlist in the camera finder or work through the camera configurator; for a check of the identity and bandwidth plan on your exact pair, contact the applications team.

Questions

Do I need admin rights or special drivers to open cameras by path?

No. Both identifiers come from the operating system's standard USB stack. On Linux, listing /dev/v4l/by-path/ needs no special privileges, and opening a node usually needs only membership of the video group. On Windows, the device instance path is visible in Device Manager without elevation. Your application then opens that path like any device path the capture library already supports, so no new driver enters the picture.

My two cameras report the same serial number — is the port path my only option?

For units with identical serials, yes: no camera-side unique ID exists to fall back on, so the connector is the only difference. If the cameras' own configuration software can write a distinct serial per unit, do that as the permanent fix, because a serial survives moving a camera between connectors. Until that is done, bind roles to ports and label both ends of each cable.

What happens to the paths if I move the cameras behind a USB hub?

Every hub level adds one segment to the port chain, so each path changes and the role map must be recorded again. The hub also shares its single upstream cable between everything behind it, so two cameras on one hub divide one cable's payload between them. Plan one camera per hub port at most, and re-run the commissioning record after any hub change.

How do I decide whether two cameras fit on one USB controller?

Add the payload of both streams and compare it with the controller's budget. One USB 3.0 port delivers roughly 400 MB/s of usable payload, so budget each controller at 350 MB/s. The 4000 × 3000 pair at 30 fps in the worked example sums to 720 MB/s and needs two controllers; two streams summing under 350 MB/s share one with margin.