Flutter Virtual Tryon – Pub Package

flutter_virtual_tryon — Flutter Package Portfolio

flutter_virtual_tryon

Cross-platform face tracking & overlay engine for Flutter

pub version MIT license platforms: Android, iOS, Web
Role
Sole Author & Maintainer
Platforms
Android, iOS, Web (macOS: manual mode only)
pub.dev Source License
MIT
Used in
Kalo Chasma — production Vision Mirror try-on

Project Overview

flutter_virtual_tryon is a general-purpose face-tracking and overlay engine for Flutter — not a “glasses package,” but a reusable computer-vision core that any overlay (glasses, sunglasses, contact lenses, or a fully custom Canvas drawing) sits on top of. It hides platform-specific computer vision behind one stable, frozen API: VisionBackend.auto() picks Google ML Kit on Android/iOS or MediaPipe Face Landmarker on web, and neither native dependency leaks into the platform that doesn’t need it.

It started as the hand-rolled camera/ML Kit/MediaPipe code inside Kalo Chasma, a production eyewear marketplace’s “Vision Mirror” try-on feature. Rather than let that logic stay app-locked, I extracted, generalized, tested, and published it as a standalone open-source package — then migrated Kalo Chasma itself onto it, so the package is validated by a real app in production, not just its own test suite.

Features Built

Live Camera Face Tracking
Photo / Still-Image Try-On
Glasses Overlay
Sunglasses Overlay
Contact Lens Overlay
Custom Canvas Overlays
Calibration Mode + Dart Export
Debug & FPS Visualization
Snapshot Capture
Mirrored-Selfie Correction
Mock Backend for Testing
ML Kit + MediaPipe, One API

My Responsibilities

  • API design & freeze: designed the entire public surface first — VirtualTryOn/VirtualTryOnImage widgets, VisionBackend, the overlay hierarchy, TrackingData — then froze it before implementation, so every later milestone was additive rather than breaking.
  • Platform-adaptive engine: conditional Dart exports (dart.library.io vs. dart.library.js_interop) keep Google ML Kit out of web builds and MediaPipe out of native builds entirely, with unsupported platforms (macOS) degrading honestly to manual-only mode instead of crashing.
  • Coordinate-space unification: normalized ML Kit’s raw-sensor coordinates and MediaPipe’s landmark space into one consistent, unmirrored TrackingData convention — including diagnosing and fixing a real iOS front-camera bug (landmarks rotated 90°, then rendering 180° upside-down) with a platform-specific relabeling fix, not a coordinate hack.
  • Renderer: a shared CustomPainter pipeline (OverlaysPainter) used identically by both the live-camera widget and the still-photo widget, with pixel-space eye-anchored placement, rotation, and scale — verified with genuine pixel-capture render tests rather than golden-image comparisons.
  • Still-image try-on (0.2.0): extended the engine to detect faces in a single supplied photo (detectStill) and exposed it as VirtualTryOnImage, reusing the same paint pipeline via an aspect-ratio-locked box instead of reimplementing letterbox math.
  • Calibration tooling: a plain ChangeNotifier-based CalibrationController plus an OverlayCalibrator widget that lets a developer drag/pinch/twist an overlay live against the camera and copy a ready-to-paste Dart snippet — no external design tool required.
  • Testing & release engineering: grew the suite from 0 to 145 unit/widget tests (83%+ line coverage, 100% on every file that doesn’t touch real camera/ML Kit hardware), then owned the full pub.dev release loop — versioning, CHANGELOG, dry-run validation, and five published releases (0.1.0 → 0.3.0).

Tech Stack

CategoryTools / Libraries
LanguageDart, Flutter (widgets, CustomPainter, Canvas)
Computer VisionGoogle ML Kit Face Detection (Android/iOS), MediaPipe Face Landmarker (web, JS interop)
Cameracamera plugin — live image-stream processing, throttled per-frame detection
RenderingCustomPainter, RepaintBoundary pixel capture, ChangeNotifier-driven calibration
Testingflutter_test, tester.runAsync for real async decode/detect, MockVisionBackend
Distributionpub.dev, Semantic Versioning, Keep a Changelog, MIT license
CIGitHub Actions — analyze, test, and a Chrome-target compile check for the web JS interop

Architecture Highlights

  • One frozen public API, three backends: VisionBackend.auto() resolves to whichever real engine the current platform supports; app code never branches on platform itself.
  • Honest degradation, not a fake success: platforms without a detection backend (macOS) report backendUnavailable through the normal error channel instead of silently doing nothing.
  • Shared paint pipeline: the live-camera widget and the still-photo widget both render through the same OverlaysPainter, so a fix or a new overlay type only has to be written once.
  • Relabel, don’t reflow: the mirrored-source fixes (both the live iOS front camera and 0.3.0’s still-photo mirroredSource) correct orientation by relabeling which landmark is “left” vs. “right,” never by mutating coordinates — so a fix for rotation can never accidentally shift an overlay off the face.
  • Test philosophy: unit tests never depend on a real camera or ML model; hand-built fixtures and MockVisionBackend keep the suite fast and deterministic, while real-device verification is tracked explicitly as a separate, documented step.

Release History

VersionShipped
0.1.0First public release — full live-tracking API, ML Kit + MediaPipe backends, all built-in overlays, calibration mode, debug tools, 132 tests.
0.1.1–0.1.3Dependency currency, then a real-device iOS front-camera bug found, diagnosed, and fixed (rotation + mirrored-landmark correction), confirmed on hardware before release.
0.2.0Still-image try-on — VirtualTryOnImage for gallery/captured photos, sharing the live widget’s render pipeline. Additive, zero breaking changes.
0.3.0Mirrored-selfie correction — TrackingData.swapLeftRight() and VirtualTryOnImage(mirroredSource:), closing the gap the still-image feature had for front-camera selfies.

Outcome / Highlights

  • Production-validated, not just tested: powers Kalo Chasma’s live Vision Mirror feature today — real users, real devices, not a demo-only package.
  • Three platforms, one API: Android and iOS get live ML Kit tracking, web gets MediaPipe, behind a single VisionBackend.auto() call app code never has to branch on.
  • Privacy by construction: all detection runs on-device or in-browser; the package never uploads a frame anywhere.
  • 145 tests, analyzer-clean: shipped with a real regression suite, including pixel-level render assertions and platform-specific coordinate-math fixtures.
  • Real bugs, real fixes, documented: two on-device iOS bugs (rotation, then mirrored orientation) were found, root-caused, and fixed with regression tests and a public CHANGELOG entry explaining exactly what was wrong and why the fix works.

Skills Demonstrated

Flutter Package Development On-Device ML / Computer Vision Cross-Platform Engineering Public API Design CustomPainter / Canvas Rendering Coordinate-Space Geometry Test-Driven Development Open Source Publishing Technical Documentation Real-Device Debugging
  • Extracting and generalizing app-specific code into a clean, reusable, published package without breaking the app it came from
  • Designing a public API that stays stable across five releases by freezing it before implementation
  • Unifying three different computer-vision coordinate spaces (ML Kit Android, ML Kit iOS, MediaPipe web) into one consistent convention
  • Diagnosing and fixing real on-device orientation bugs with root-cause understanding, not trial-and-error patches
  • Running a disciplined release loop: versioning, changelog, dry-run validation, and pub.dev publishing

Work With Me

I build and publish production-grade Flutter packages, cross-platform on-device ML features, and polished Material 3 UX.

View on pub.dev View on GitHub
Let’s build your next Flutter package

Description

flutter_virtual_tryon — a cross-platform Flutter package for face-tracking virtual try-on. ML Kit + MediaPipe behind one API. Live camera & photo modes. MIT licensed.