WhoBuilt

Drawing onto the Camera

Sep 25, 2024· 23 min· 1.3K views·Watch on YouTube

Speaker

Marc Rousavy, open-source developer and founder of Margelo, explains how VisionCamera and React Native Skia can draw real-time effects into a camera stream at React Universe Conf 2024, hosted by Callstack.

Why draw on camera frames

Rousavy describes real-time overlays, color effects, face blurring, and foreground segmentation as camera drawing use cases. A Margelo client project dims the background and adds an animated sticker around a person's hand, while the captured video keeps only the foreground. Building such features natively requires separate iOS and Android implementations.

How VisionCamera processes frames

VisionCamera provides camera features such as photo and video capture, QR scanning, and controls for buffer compression and pixel format. Its frame processors run on a separate camera thread for each frame. Frames stay as native C++ objects exposed to JavaScript through JSI, avoiding the cost of copying or serializing large image buffers.

Keep processing native and app logic in JavaScript

Rousavy describes a hybrid approach: JavaScript handles camera setup, plugin configuration, and decisions about results, while native plugins perform high-performance processing. Plugins can wrap libraries such as ML Kit, Apple Vision, or TensorFlow Lite. This lets apps use native processing while sharing their JavaScript logic across iOS and Android.

Draw effects into the camera stream with Skia

Updating UI state or using Reanimated shared values to draw over the preview can lag because the camera and UI run on separate threads, and those overlays do not become part of the video stream. VisionCamera's Skia frame processor lets developers draw back onto the frame. In Rousavy's face-blurring example, a native detector finds faces and Skia applies a blur inside each face region.

Performance and ways to try it

Rousavy says the face-blur app takes about 40 lines of code and runs in 10 milliseconds on the demonstrated iPhone 11, including detection, JSI, and drawing. He says it also runs on Android without writing Java or Kotlin. He points listeners to VisionCamera, Reanimated, a face-blur demo, and his Shadow Lens app.

Takeaways

  • Keep large camera frames in native memory and expose references to avoid copying image data through JavaScript.
  • Use native plugins for time-sensitive image processing and JavaScript for app logic and configuration.
  • To make an effect part of recorded video, draw into the camera frame rather than placing a view over the preview.
  • Account for the camera and UI running at different frame rates when designing real-time effects.
  • Benchmark the full processing path on target devices; the face-blur example took about 10 milliseconds on one iPhone 11.

Mentioned in this talk

Search inside this talk

What was claimed 8

Related talks