# Face-covering test notes — 5 September 2026

These are Baby Acrobatics' internal rendering and export checks on synthetic media. They are not an independent security audit or a face-recognition benchmark.

Article: https://www.babyacrobatics.com/kids-online-privacy/how-our-face-covering-works

## Historical experiment: before the changes

The original fixture was a 512 × 512 picture containing alternating 4-pixel light/dark squares. The circular cover had radius 160 pixels, strength 0.5 and default softness 0.45. We exported a JPEG, decoded it, and measured contrast in a narrow band at 94–98% of the cover radius.

The measure is a centred linear-regression slope of output brightness against the original pattern, expressed as a percentage. Unedited pixels measure about 100%; a constant fill measures about zero. Negative values can result from aliasing. This is surviving pattern contrast, not recoverable identity.

| Historical variant | JPEG outer-band contrast |
| --- | ---: |
| Earlier mosaic | 70.332% |
| Earlier mosaic with three extra offset passes | 69.943% |
| Earlier mosaic with an opaque coverage circle | 0.425% |
| Constant grey cover | 0.015% |

The current article rounds the first three values to one decimal place. The main problem was the old soft-edge mask blending original pixels back in after processing. Fine-pattern suppression does not show that coarser facial information has been removed.

The baseline also found fades exposing the source and uncovered intervals during tracking/end padding. That baseline is not the current implementation. In the baseline JSON, the variant named `current` means the renderer at the time of that earlier experiment.

Recorded baseline data: https://www.babyacrobatics.com/privacy/face-cover-baseline-2026-09-05.json

## Regression after the changes

The regression used Chrome 152.0.7977.77 with production rendering/export modules, synthetic pictures and a synthetic 30 fps video. No real children's pictures were used. It checked raster/JPEG outputs, Solid and eight Emoji options, custom Solid colours, outward softness, sizing, render-failure fallbacks, default Blur and zero fades, controlled tracking gaps and source-frame timing.

For the Solid/Emoji comparison, only pixels underneath the cover changed; the scene outside stayed constant. The raw protected output and decoded exported JPEG were unchanged in the tested cases. This establishes independence from those changed covered pixels in the fixture. It does not establish anonymity from the rest of an image.

| Video export | Decoded frames checked |
| --- | ---: |
| Fast, full clip | 60 |
| Fast, trimmed clip | 31 |
| Real-time, full clip | 60 |
| Real-time, trimmed clip | 31 |
| Total | 182 |

No frame failures were recorded. Binary markers in the source identify the actual saved frame, rather than relying only on output timestamps. Checks cover intended effect intervals, first/last frames, held gaps and end padding. The opaque-video checks allow six of 255 colour-channel levels for codec rounding and sample at least 12 pixels inside the cover. These tolerances are rendering checks, not privacy scores.

Recorded regression data: https://www.babyacrobatics.com/privacy/face-cover-regression-2026-09-05.json

These source-file SHA-256 hashes identify the files used by the recorded regression. Later changes require re-running the relevant tests:

- `mosaic.ts`: `5c6f3800ba68fde62ba0214ed9087b5af1c4fa07d943be3df4fa0b7784313784`
- `boxes.ts`: `0c486fcb312dc6ba0a157e98cb2884d1517138abccf46bb731c63b94eb9f189d`
- `exportMedia.ts`: `d0126227c03f632761702e6ff9752e181e034f3e0e0251b606bc4a9ef71381b1`
- `exportFast.ts`: `07dd935b53f4f9c323f1f35867bfb8a9b28fcdb8746bd01a86b1e5774049addb`

## Reproducing and interpreting the checks

In the application repository, the command is `npm run test:censor:exports` from `apps/frontend`. The runner is `scripts/censor-mosaic-privacy.mjs`. It uses installed Chrome, Puppeteer, esbuild, ffmpeg and ffprobe. It bundles the production modules and needs no development server; it blocks HTTP media requests and generates synthetic input. The current runner tests the improved renderer and does not recreate the old experimental variants. The historical results above are preserved as a separate baseline record.

This article reviewed the saved results and compared source hashes. It did not rerun the experiment or claim a new benchmark.

## Limits

- One recorded browser version, synthetic scenes and controlled movement. No general browser/device compatibility claim.
- No measurement of how often real faces are missed or how often real tracking loses a face.
- No recognition or reconstruction attack against our Blur or Mosaic. Both retain source-derived information.
- Holding a larger circle does not prove an unseen face stayed inside it. Review the gap.
- Solid and backed Emoji replace only the pixels they fully cover at full opacity. Deliberate fades, uncovered regions, audio, captions and other pictures still matter.
- No independent audit or security certification. An exported file has rendered pixels, but an original or another copy may remain elsewhere.

Research context: McPherson, Shokri and Shmatikov, *Defeating Image Obfuscation with Deep Learning* (2016): https://www.cs.cornell.edu/~shmat/shmat_imgobfuscation.pdf . It tested recognition from its own obfuscation/dataset combinations, not this application.
