Mask is a native macOS menu bar app that applies real-time skin correction and background replacement to your video feed system-wide. It works in Zoom, Google Meet, FaceTime, and any other app that reads a camera. All processing runs on-device using Apple's Neural Engine.
Most virtual camera tools skew toward AR lenses and heavy stylization, and in-app filters like Zoom's don't cross platform boundaries. The gap I wanted to fill was something subtle and low-friction: a correction layer for professionals on calls for hours who want to look polished without the setup.
Mask lives in the menu bar and stays out of the way until you need it. The panel is 320px wide, matching Apple's HIG width for menu bar accessory windows, and is compact by design with no scroll view and no nested settings. Every control is visible at once.
The three filters in the app target specific needs: skin smoothing for texture and tone, redness correction for screen flush and warm lighting, and background replacement for privacy or room distractions. Each filter was tuned to a default that works without adjustments.
I built a geometry-based face mask from Vision landmarks, then applied an edge-preserving filter that smooths skin while stopping at structural edges like the hairline and eyelid crease. A high-frequency residual layer preserves texture, so the result reads as healthy skin.
Whether you blur the background or swap in an image, Mask separates you from the room in real time, so it stays locked to you as you move. I ran the whole pipeline on the GPU to keep it light enough for hours of calls.
I designed redness correction to target screen flush and warm lighting without overcorrecting into an unnatural skin tone. In testing, it conflicted with the skin-smoothing pipeline downstream, and the tradeoffs weren't worth it as it kept interfering with the other filter outputs no matter what fixes were made. So, it was removed in the final version, for now.
Learning the tool while trying to ship something real meant early code had structural issues that only surfaced during live testing. Tracing bugs back consistently pointed to something deeper than the surface symptom, and the fix almost always required a broader architectural change rather than a patch.
The parallel to design work was hard to miss. Pausing to restructure rather than patch is an instinct I already had as a designer. Building solo made me apply it to code for the first time.