React Native View Recorder
Guides

How It Works

Platform-specific internals of view capture and video encoding

Recording loop

When you call recorder.record(), the library runs the following loop for each frame:

  1. Calls your onFrame callback with the current frame index
  2. Waits for the callback's returned promise (if any) to resolve
  3. Waits one requestAnimationFrame to ensure React has rendered
  4. Captures the native view to a pixel buffer
  5. Encodes the pixel buffer into the video stream
  6. Calls your onProgress callback

After all frames are captured, the encoder finalizes the MP4 container and returns the output path.

iOS

View capture

drawHierarchy(in:afterScreenUpdates:true) renders the view hierarchy into a CVPixelBuffer-backed bitmap context. The afterScreenUpdates: true parameter ensures all layer types are captured, including CAMetalLayer content (used by Skia). The pixel buffer is then appended to AVAssetWriter for encoding.

Video encoding

AVAssetWriter with AVAssetWriterInput configured for H.264 or HEVC. Pixel buffers are appended to the asset writer's input.

Supported codecs

  • H.264 (AVC)
  • HEVC (H.265)
  • HEVC with Alpha (for transparent video, iOS 13+)

Android

View capture

PixelCopy.request() captures from the window compositor. This works with any view type, including TextureView (used by Skia) and SurfaceView.

Video encoding

MediaCodec configured as a hardware encoder, with an EGL surface as input. Captured bitmaps are uploaded to the MediaCodec surface via OpenGL ES 2.0, then encoded in hardware.

Supported codecs

  • H.264 (AVC)
  • HEVC (H.265), if supported by device hardware (the library auto-detects this and falls back to H.264 when no hardware HEVC encoder is available)

MP4 container

The library writes a standard MP4 container. When optimizeForNetwork is enabled (the default), the moov atom is moved to the front of the file after encoding completes. This allows progressive playback without downloading the entire file.

optimizeForNetwork only takes effect on iOS (via AVAssetWriter.shouldOptimizeForNetworkUse). Android's MediaMuxer does not expose an equivalent API, so the option is silently ignored.

On this page