Filters & Lenses
Swipe → · one shader for preview and photoOn launch
Colour picker
Tap the viewfinder to read a colour from the camera frame.
Custom lens
Camera Stream
a bigger stream costs delivered fpsGuides
composition only — captures are always the full frame
Camera controls
what WebKit actually exposesSmooth zoom is the stick under the viewfinder: push it right to zoom in, left to zoom out, and it springs back to the middle when the finger lifts. Full deflection is one zoom step a second, half a stick half that. The presets are an instant jump to an exact number.
Exposure & focus
viewing aids · never capturedSharpen
auto-levels Full + clarity High · after the shutterPhoto enhancement
review & importsSmooth grain while preserving strong edges, then sharpen fine edges. Keep detail blends original texture back in. Strong smoothing can flatten small textures. Presets leave auto-levels unchanged; Clarity and enhancement sharpening are alternatives.
Clarity
an edit · after the shutter, not liveAuto-levels
an edit · after the shutter · RGB onlyThe shutter keeps the frame it fired on, so the saved file can be looked at — and its clarity changed and the capture re-run — before it goes anywhere. Off, the shutter behaves exactly as it did: the photo lands on the Captures card and waits there for a Share tap. Holding the frame costs one extra full-size copy at the moment of capture, which is time the camera spends in its escalated mode.
Frame averaging
preview & video · steadies the hue lensesShoot when steady
auto shutter · one photo, then disarms🌙 Night — Test
Milestone 1 · stack only · nothing is savedNo runs logged yet — each Night attempt adds a line here.
Import
photo or video · same filters · saved as a new fileAn imported file has already been compressed once. Edge, Motion and Speed read what is in the pixels, so they will find that codec's blocking and ringing and draw it as confidently as they draw the room — artefacts arrive looking like structure. Footage straight off this camera has only been through one encoder; anything messaged, downloaded or re-shared has been through several.
Captures
Full measurements for every capture are under More.
Photo
The live stream stays responsive; the shutter briefly asks the SAME camera track for its maximum mode, waits for a real decoded frame at the new size, renders the ACTIVE filter once at that measured size, saves the JPEG, then restores the responsive stream. A short pause during capture is the trade. Saved dimensions are what the camera actually granted — never the request, never upscaled.
Maximum quality skips automatic compression selection and saves at JPEG 1.00. JPEG is still a lossy format. Smaller file checks nine distributed image regions at full resolution, including brightness and color, and never searches below quality 0.90. This is a sampled comparison, not a guarantee of lossless output. Dimensions stay unchanged.
Recording
RGB records the camera stream directly while the stream fits the encoder's frame limit; above it, and for every filter, the clip is the same GPU render the preview shows, at the RECORD IN size. The container is the browser's own choice, and every number below is measured from the finished file — never from what was asked.
RECORD IN follows the chosen tier exactly as a photo does, so MAX records at MAX. Untick it to hold recordings under the encoder's frame limit instead — a limit that is assumed at the H.264 Level 5.2 line until the probe below measures this device. That assumption would shrink a 12 MP frame to about three quarters of its area, and it would do the same on a camera many times larger, so it is not applied unless you ask for it. Nothing here is silent either way: every clip's dimensions are read back out of the finished file, so an encoder that cannot hold the frame reports did not decode rather than leaving you a broken clip that looks fine.
Encoder envelope probe. Records a synthetic moving-noise canvas through the same recorder at 4:3 sizes bracketing the H.264 Level 5.2 frame limit (36,864 macroblocks), then MAX at 30 / 15 / 10 / 5 fed fps — each file decoded. About 30 s; nothing is saved. Its verdict becomes this device's ENCODER capability.
Night / GPU precision
For each candidate accumulator format: allocate a texture, attach it to a framebuffer, check completeness, render known fractional values, read them back through an amplifying pass, and verify they survived. RGBA8 is probed as a CONTROL that is expected to FAIL — a test that passes everything proves nothing. The last row tries a full Night-sized ping-pong pair. It runs on its own throwaway context, so a loss cannot take the camera down; nothing is saved and Night is not changed.
Night sizes
Source truth
What this build is
V2 Milestones A–C: the camera shell, the frame-geometry authority, the GPU render contract and recording truth. The live stream is a performance decision; the photo is a quality decision (the camera's maximum, fetched only for the shot); a clip is measured from its own file and held under the encoder's measured frame limit. Preview, photo and filtered recording are ONE fragment shader at explicit sizes, and the truth table above is the authority's live output — every row a separate fact with its own policy.
Milestone D has begun: Motion is the first temporal tool, its frame history held at ANALYSIS resolution and saying so. The lens workbench (E) follows. The legacy app is unaffected and remains the default URL.