Build1 distinct publisher3 min readUpdated
MediaPipe's GPU path built cleanly, ran in 5 ms, and produced empty masks on a Samsung A56. The CPU fallback only watched for exceptions, so it never fired.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A team building an offline virtual mirror for hair salons found that MediaPipe's ImageSegmenter with the GPU delegate was created without throwing, ran in 5 ms, and returned zero hair pixels on a Samsung A56 (Exynos 1580, Mali GPU) - both the confidence mask and the category mask came back empty, every time [7]. Their fallback to CPU triggered only on exceptions, there were no exceptions, and so the app simply looked slow instead of broken [8].
The constraints are worth stating because they are common. No frame leaves the device: model, fonts and runtime are all local, since a CDN request would break offline use and leak the salon's IP to a third party [2]. And salons do not buy flagship tablets, so the target is whatever mid-range Android is on the counter [3]. On a Pixel 8 Pro the same build ran at 9 fps, which the author calls poor but working; on the A56 there was no colour at all [5][6]. All figures come from diagnostics built into the engine and measured on real devices, according to the write-up [4].
The instructive part is the benchmark trap. The GPU path measured 96 times faster than CPU precisely because it was not doing any work, so timing alone would have selected the broken path [9]. Taken with the 5 ms GPU figure, that implies a working CPU pass on the order of 480 ms [27], consistent with the 437 ms of blocked main thread the team measured for the synchronous segmentForVideo call on Exynos [19]. The stated lesson is to check the output, not the exit code; the team now measures mask coverage and surfaces it in diagnostics [10].
The fallback rule is more careful than "retry on empty". After five consecutive empty masks, having never seen a good one in the whole session, the engine rebuilds on CPU [11]. The distinguishing condition is "never seen a mask", not "empty right now", because an empty mask is entirely normal when nobody is in front of the lens [12]. That is the difference between a broken delegate and an empty chair, and it has to be encoded explicitly. On the A56 the rebuild took the app from 2 fps to 14 fps with colour applied [13], a factor of seven [26].
Observability is not free either. An outputCategoryMask left enabled from an earlier experiment became a significant part of the frame budget [14].
Once the GPU path was honest, the profile of the Pixel 8 Pro's 9 fps was unflattering to the surrounding code rather than the model: 6 ms of inference against 126 ms of the team's own work [15], roughly 4.5 percent of the frame [25]. That work was 66 ms in a JavaScript loop recolouring pixels one at a time [16] and two GPU-to-CPU readbacks per frame, one of them costing 123 ms [17]. The author reports this is the shape of most "the ML model is too slow" complaints they have received [28]. The loop went into a fragment shader, free because the pixels were already on the GPU [18]; the readback went away by passing MediaPipe the same canvas and taking the mask with getAsWebGLTexture() [21]; and segmentation moved to one frame in every adaptive step, drawing the video on all of them [20].
Two constraints to watch if you copy this. MediaPipe recycles that texture underneath you, which produced colour flicker until the team copied it into their own texture with a shader [22]. And MediaPipe will not start inside a type: "module" worker, dying with ModuleFactory not set because its WASM loader registers the factory via importScripts() [24] - so the reflex of moving a blocking call off-thread is not available unless you use a classic worker. The team expected to need a worker and did not; decoupling cadence was enough [20].
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The team builds a virtual mirror for hair salons: a tablet camera feed where the customer's hair changes colour in real time while they move their head.
Privacy constraint: no frame ever leaves the device; the model, fonts and runtime all run locally with no CDN dependency, because a CDN request would break offline use and leak the salon's IP to a third party.
Hardware constraint: salons do not buy flagship tablets, so the app had to work on whatever mid-range Android is on the counter.
All numbers in the write-up were measured on real devices with diagnostics built into the engine, and none are estimates.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed first-party device measurements, unpublished harness
Claims are unusually specific for a practitioner post: named devices and silicon, per-stage millisecond costs, an explicit before/after frame budget, and a stated methodology that all numbers came from on-device diagnostics rather than estimates. The evidence is nonetheless self-reported and unverifiable from the supplied material: no code, raw diagnostics, MediaPipe version or model revision is published, and the device sample is two handsets. That caps the score well below the level a reproducible or independently confirmed benchmark would earn.
One team's shipping app; no external uptake
Adoption evidence exists but is confined to a single team: a shipping consumer APK for salon tablets and before/after benchmarks on two devices. There are no third-party deployments, no counts of salons or sessions, no downstream reuse of the described fallback pattern, and no vendor or community response in the supplied material. The score reflects a real but singular production instance rather than diffusion of the technique.
Claims sit at or slightly below the measurements
The write-up is calibrated rather than promotional: it names the trap in its own headline number (a 96x speedup produced by doing nothing), flags that its own diagnostic distorted the frame budget, and explicitly explains why 17 ms per frame yields 15 fps rather than 58 by attributing the remaining ceiling to WebView compositing inside Flutter that it has not investigated. The slightly negative value reflects that the most broadly useful finding — exception-based fallbacks cannot catch silent output failure — is stated as a personal lesson rather than pressed as the general engineering claim the measurements arguably support. The one place reach exceeds evidence is the generalization that the model is almost never the bottleneck, drawn from a single project.
Practitioner post with mild product visibility interest
The author writes about a commercial product they build — a salon virtual mirror — on a developer publishing platform, which carries reputational and product-visibility incentives and a natural bias toward framing their engineering decisions as sound. Offsetting factors are visible in the supplied material: the post makes no product pitch, discloses its own mistakes (a diagnostic left enabled, four of five wins being removal of self-inflicted work, an unresolved compositing ceiling), and has no evident vendor relationship with MediaPipe, which it criticizes. No sponsorship, funding or affiliate arrangement is disclosed or apparent.
Plausible and specific, but single-source and unreproduced
Internal coherence is high: the reported figures are mutually consistent (6 ms of a 132 ms frame at 9 fps; 5 ms x 96 implying a ~480 ms CPU pass; 2 to 14 fps on the A56), the mechanisms named are ones that plausibly behave as described, and the API-level details are the kind an implementer would only know from doing the work. Confidence is nevertheless limited by there being exactly one publisher, no published code or version pins, no vendor or independent confirmation of the silent Mali/Exynos delegate failure, and a two-device sample supporting conclusions aimed at mid-range Android broadly.
build
Grok 4.6 lands in Copilot two days after launch, and the model picker becomes a procurement problem1 distinct publisher
security
Google's reference agent approved a $10,000 refund on a $149 order, on purpose1 distinct publisher
product
Washington's secret AI test is coming for open weights, and release dates go with it2 distinct publishers
product
LineageOS 23 reaches the Galaxy S22 with about six months left on Samsung's clock1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 17, 2026