Why your camera is not already a mirror
A webcam does not flip its own picture. Point one at yourself, raise your
right hand, and the hand that goes up on screen is on the
left — which is what the camera really sees, and
completely useless for checking a parting or a collar, because it is not
what a mirror does. A looking-glass reverses left and right; a lens does
not. This page puts that one flip back, and then gets out of the way.
One tab, one job
There is a picture, a short column of icons in its corner, and a
start/stop button under it. No device picker, no resolution or frame-rate
controls, no readouts, no code editor — the rest of the
camera toolkit has every one of
those, and this tab deliberately has none of them. The picture takes the
whole pane; press the corner icon, or double-click the picture, and it
takes the whole screen.
A magnifying mirror, too
The other thing people do with a mirror is get closer to it, and
a webcam in a laptop lid is always further away than a bathroom mirror is.
So the picture zooms, up to 16×:
pinch it on a trackpad or a phone screen, roll the
wheel over it, or press the + under the
full-screen toggle. Then drag the picture — with a finger
or the mouse — to put an eye, a tooth or a contact lens in the middle of
the frame. The zoom lands where you pointed rather than in the centre, so
pinching on your left eye makes your left eye bigger. The chip showing
2.4× is also the way back: press it, or press
0, and the whole picture returns.
Zooming costs nothing, for the same reason the flip below does: it is a
scale() and a translate() handed to the
compositor, not a redrawn frame, so a mirror at 16× runs at exactly
the resolution and frame rate your camera gave you.
The flip is free
Mirroring here is a single CSS scaleX(-1) on the video
element, so the compositor flips a frame the browser has already decoded.
No pixel passes through JavaScript, nothing is re-encoded, and the mirror
therefore runs at whatever resolution and frame rate your camera actually
gave you rather than at whatever a per-pixel loop could keep up with. The
Transform tab ships
the same flip as an editable flip-horizontal effect, one
pixel at a time, on purpose: there the arithmetic is the point, here the
picture is.
Nothing leaves this page
There is no server to send a picture to. OmniViewer is a static site: the
stream goes from your camera to your screen and nowhere else, nothing is
recorded, and the camera is released — hardware light off — the
moment you press stop or leave the tab. Nothing opens until you have
allowed it, either: arriving here from a link with no permission granted
gets you a button, not a live device. Once you have allowed it,
this tab opens into the picture on arrival — a mirror you have to
switch on every time is not much of a mirror — and pressing stop
still means stopped.
It’s one lens on OmniViewer’s
Webcam Test & Camera Capabilities:
drop a file and every tab is one click away. OmniViewer opens
every file format, entirely in your browser —
no upload, no server.
FAQ
Is my camera feed uploaded anywhere?
No. OmniViewer is a static page with no server-side processing and no analytics of the video: the stream goes from your camera to the page and nowhere else. There is no endpoint to upload to. Clips you record are held in your browser tab and disappear when you leave, unless you download them yourself.
Does the page open my camera without asking?
No. Nothing opens until you have granted this site camera access, and the grant is yours to make in the browser’s own prompt. What happens after that is different: once the permission exists, the Mirror and Transform tabs — the two that are nothing but a picture — open the camera on arrival rather than making you press start again every visit. The page checks whether the permission is already there without prompting for it, using the Permissions API where the browser supports the name and the presence of device labels everywhere else. Press stop and it stays stopped, and revoking the permission in your browser puts the button back.
What resolution does it open at?
The highest one your camera reports it can do. A camera’s real maximum is only readable from a track that is already open, so the first stream on a device is opened with no size constraint and then raised to the maximum getCapabilities() reports — one applyConstraints on the live track, no second permission prompt. The resolution picker on the Preview tab overrides it: pick a specific size, or “Camera’s choice” to send no width or height at all and see what the device volunteers on its own, which is usually a good deal less.
Why does the camera open at a lower resolution than I asked for?
Because a constraint is a request, not a command. An "ideal" constraint is a preference the browser may silently ignore, and a camera already opened by another application will hand you whatever mode it is already running in. The Capabilities tab is built to show exactly this: the resolution you asked for, the range the hardware reports it supports, and the one you actually got, with the disagreement flagged.
Why are my cameras listed without names?
Device labels are hidden until you grant camera access. Before the grant, a page can enumerate your devices and count them but cannot read their labels — that is a deliberate browser privacy mitigation. Press Start camera and allow access, and the names appear immediately. You can watch it happen on the Capabilities tab.
Does this work in every browser?
The preview and the asked/supported/got table work in any modern browser on a secure (https) page. How much the table has to show depends on the browser and the hardware: Chromium reports the widest set of camera controls, and most laptop webcams expose far fewer of them than a phone camera does. The effects need a Web Worker, and recording a clip of them needs both canvas captureStream and MediaRecorder.
What format does the clip recording use?
Whatever the browser supports, preferring MP4 — Safari and Chrome 130+ record MP4, which opens in OmniViewer’s /mp4 toolkit with its full atom tree. Browsers that only record WebM produce a valid file that opens in the universal raw, hex and strings views, since OmniViewer has no dedicated WebM route yet. Clips are capped at 30 seconds so the recording stays in memory safely.
Do the clips I record here contain EXIF or GPS data?
No, and that is half the point of recording them here. A browser capture has no camera make or model, no lens or firmware string, no serial number and no location — the capture path has no access to any of it. One line is added on the way out naming the website that made the file, and the toolkit that reads it will take even that out. Open a clip in /mp4 and compare it against a video from your camera roll to see the difference.
Does the page keep using my camera after I switch tabs?
No. Stopping the camera stops every track, which is what turns the hardware indicator light off; loading a file, pressing close, or leaving the route all do the same. Merely dropping the video element would leave the light on, so the toolkit stops the tracks explicitly.