webcam
Webcam Goes Black or Freezes Mid-Call? Here's What's Actually Happening
Your camera worked, then went black, froze, or turned choppy. How browsers signal device loss, why a black picture is often by design, and a fix order.
The camera worked when the call started. Twenty minutes in, your tile goes black, or freezes on an unflattering frame, or drops to a slideshow. The usual advice is “update your drivers,” which skips the useful part: a black picture, a frozen picture, and a choppy picture are three different failures, and the browser reports them in different ways, sometimes on purpose and sometimes not at all.
This post covers what goes wrong after the camera has started. If you never got a picture in the first place, the cause is almost always permissions or another app holding the device, and that’s covered in why browser camera and microphone access fails.
How the browser tells a page the camera is gone
A page’s camera feed is a MediaStreamTrack. Per the W3C Media Capture spec, a track has exactly two readyState values: live and ended. Once it’s ended it never comes back. The spec’s own example of what ends a track is “the user unplugs the USB web camera.” Revoking the page’s camera permission ends it too.
Separately, a live track can be muted, meaning its source is “temporarily unable to provide the track with data.” This is the interesting part. The spec leaves the reasons for muting up to each browser, and the examples it lists are things people blame on broken hardware: “the user closing a laptop lid with an embedded camera, the user toggling a control in the operating system, the user clicking a mute button in the User Agent chrome.” While a track is muted, the spec says a video element “is playing but rendering black video frames.”
So a black tile can be the browser working as designed.
| What you see | What the track says | Possible causes |
|---|---|---|
| Picture gone, app says camera disconnected | ended (event fires) | Cable pulled, device dropped off the USB bus, permission revoked |
| Black picture, no error | live but muted | Lid closed, OS toggle, another tab took the camera (Safari) |
| Black picture, no error, not muted | live, unmuted | Privacy shutter closed, kill switch sending black frames |
| Frozen frame | live, frames stopped | No standard signal; see the debugging order below |
Here’s what a page should listen for:
const [track] = stream.getVideoTracks()
track.addEventListener('ended', () => {
// Gone for good: unplugged, revoked, or ended by the browser.
showError('Camera disconnected. Reconnect it and start again.')
})
track.addEventListener('mute', () => showNotice('Camera paused by the system'))
track.addEventListener('unmute', () => hideNotice())
// Already dead between getUserMedia() and now? Check, don't just listen.
if (track.readyState === 'ended') showError('Camera disconnected.')
One detail trips up a lot of developers. ended does not fire when your own code calls track.stop(). MDN says calling stop() is “the only case where the track ends but the ended event is not fired.” That’s actually handy, because an ended listener only ever hears about real losses.
Browsers don’t all agree
“Implementation-defined” means you can’t count on every browser doing the same thing. Some real examples:
- Safari once didn’t fire
endedon unplug at all. WebKit bug 187896 (“‘ended’ Event doesn’t fire on MediaStreamTrack when a USB camera is unplugged”) was fixed in December 2018. It shows this path depends on each engine wiring it up. - In Safari, a second tab can take your camera. In WebKit bug 223198, a WebKit engineer explained that “only one page at a time can get camera and/or microphone.” The first page’s track gets muted and goes black. It doesn’t end. That’s by design.
- Firefox has a long-open bug about unplugging a USB camera mid-capture. In bug 1281155, the removed camera can still be picked afterward. Picking it “succeeds” but delivers no frames.
The hardware side: why a camera vanishes mid-stream
Loose cables and bumped connectors are boring but common. When the USB link drops, the OS sees the device as removed, and a well-behaved browser ends the track.
Bus-powered hubs. Under the USB 2.0 rules, a hub with no power supply of its own can only promise 100 mA per downstream port, against 500 mA from a powered port. If your camera lives on an unpowered hub or a monitor’s USB passthrough, plugging it straight into the computer is the cheapest experiment you can run.
USB bandwidth. A video camera reserves bus time up front, and Windows’ USB documentation says plainly that the system allocates bandwidth “on a first-come-first-serve basis”. It even uses a webcam as its example: the driver is supposed to try its highest-bandwidth setting and step down if that fails. Two cameras, or a camera plus a capture card, on one USB 2.0 controller can run out. A high-speed isochronous endpoint can move at most 3,072 bytes per 125 µs microframe, about 24.6 MB/s. Uncompressed YUY2 is 16 bits per pixel, so 1080p at 30 fps is 1920 × 1080 × 2 bytes × 30, roughly 124 MB/s. That’s five times what the endpoint can carry. Uncompressed HD over USB 2.0 can’t happen, so the camera either compresses (MJPEG, for example) or drops to a lower resolution or frame rate.
Privacy shutters and kill switches. Microsoft’s hardware guidance describes both behaviors you might hit:
- A closed shutter leaves the camera “operating normally.” Apps keep receiving frames, which are “black or very close to it.” Some makers swap in a static “camera blocked” image instead.
- Some kill switches “physically disconnect the camera device from the system.” Microsoft explicitly doesn’t recommend this, noting it “can cause certain applications to crash or misbehave if the camera is removed during use.” Its recommended design keeps the camera visible and has the image processor “synthesize black frames” instead.
So the same kind of camera switch might produce an ended track on one laptop and a perfectly healthy-looking black stream on another. Neither one is broken.
Selective suspend is probably not your culprit. USB selective suspend powers down idle devices, and Microsoft enables it by default and “strongly recommends not disabling” it. A camera that’s actively streaming isn’t idle, so turning selective suspend off is aimed at the wrong thing.
Choppy video: usually light, then bandwidth, then everything else
Low light lowers the frame rate, on purpose. Each frame has to be exposed before the next one starts. At 30 fps that leaves at most about 33 ms per frame. When the room is dark, auto-exposure wants longer than that, and many cameras are allowed to slow down to get it. Logitech’s RightLight 2 brief says its low-light boost “adjusts the frame rate, increasing the exposure time of the camera.” Linux exposes the same trade-off as a control called V4L2_CID_EXPOSURE_AUTO_PRIORITY, which “determines if the device may dynamically vary the frame rate.” If your video gets smoother when you turn on a lamp, that was the cause.
Negotiated mode. The resolution and frame rate you get come out of a negotiation between what the page asks for and what the camera offers. A page that asks for nothing gets defaults, which the spec notes “tend to” be 640 × 480 at 30 fps. A call app that asks for 1080p on a USB 2.0 port pushes the camera onto its compressed mode or a lower frame rate, per the bandwidth math above.
CPU and virtual cameras. Encoding video for a call costs CPU, and a laptop that’s thermal-throttling drops frames. A virtual camera (background-blur or streaming software pretending to be a webcam) adds another layer. Its output is only as smooth as that software keeps up.
A debugging order that converges
- Did the app say “disconnected”? That’s an
endedtrack: physical loss or revoked permission. Reseat the cable, plug the camera straight into the computer, and check for a camera key or switch that removes the device. - Black, but no error? Check the shutter first. Then look for another tab or app using the camera (in Safari, the other page wins), a closed lid, or an OS camera toggle.
- Frozen frame, no error? The track is still live but frames stopped arriving. Try a different port, ideally on a different controller. Unplug any second camera or capture card.
- Choppy? Compare measured frame rate to advertised (the tool below shows both). Add light facing you. If that doesn’t fix it, suspect the port, then the CPU, then any virtual camera.
- Fine in a test, bad in calls? The call app is probably asking for a higher mode than your setup can sustain. Lower the app’s video quality and see if the drops stop.
What our webcam test shows (and what it can’t)
The Webcam Test shows three numbers: the resolution the browser actually negotiated, a measured FPS counted from real decoded frames using requestVideoFrameCallback (supported in Chrome 83+, Safari 15.4+, and Firefox 132+), and the advertised frame rate, which is the rate the browser reports for the current mode. If advertised says 30 and measured says 14, check the lighting before you blame the hardware. The test doesn’t request a specific resolution, so you see the browser’s default mode, not your camera’s maximum.
As of today it also watches for device loss. If the track fires ended, the preview is replaced with “Camera disconnected — the device stopped sending video. Reconnect it and press Start.” and the stream is released instead of leaving a dead preview on screen. The Mic Test shares the same code and shows “Microphone disconnected” when a headset is pulled.
Here’s the honest limitation. We treat only ended as a disconnect, not mute. That’s deliberate, because muting is temporary and can undo itself. But it means some failures show up as a plain black preview with no message: Safari handing the camera to another tab, a closed lid, a shutter, or a kill switch that sends black frames. And as the bugs above show, not every engine fires ended on every unplug. If the picture goes black and the message doesn’t appear, run steps 2 and 3 above.
Test it yourself
- Webcam Test: live preview, negotiated resolution, measured vs. advertised FPS, device switching, and the new disconnect detection. Leave it running and wiggle the cable to find an intermittent connection.
- Mic Test: the same disconnect handling for microphones and headsets.
- Why browser camera and microphone access fails: every
getUserMediaerror name, for when the camera never starts at all.
Both tests run entirely in your browser. No video or audio is uploaded anywhere.