Camera access is requested only after pressing Start. The stream stays local in this browser.
Start asks the browser for camera permission. If permission is blocked, reset it from the browser site-permissions icon and start again. Camera access requires HTTPS or localhost.
Resolution uses ideal constraints, so the actual delivered resolution and frame rate (shown in the stats) may differ. Reported track FPS is what the camera negotiated; the live FPS is measured frame-by-frame via requestVideoFrameCallback on Chrome/Edge/Safari; Firefox falls back to requestAnimationFrame which measures display refresh, not real camera frames.
requestVideoFrameCallback
requestAnimationFrame
Snapshot downloads a PNG frame locally (applies mirror state). Record toggles a local WebM recording via MediaRecorder; click again to stop and download. Recording captures the raw stream, ignoring CSS filters.
MediaRecorder
Hardware controls auto-populates when the device exposes adjustable capabilities (zoom, focus distance, exposure compensation, color temperature, torch). Move the slider/click the toggle to apply via track.applyConstraints(). Empty list means the device does not expose runtime controls.
track.applyConstraints()
Keyboard shortcuts: F fullscreen · M mirror · G grid · C center · Space freeze · S snapshot · R record · H hide controls · ? help · Esc close dialog.
Reset returns mirror, overlays, filters, recording state, and selected resolution profile to defaults. Theme and selected camera persist.
Privacy: CSP connect-src 'none' blocks all network access. Stream is local. Settings live in localStorage under the camtest: prefix. Export creates a local JSON file with device labels redacted to [available].
connect-src 'none'
localStorage
camtest:
[available]