Device Features· 7 min read

Camera, Media Upload and Video in React Native

Camera and video in React Native in 2026: expo-camera vs VisionCamera, image picking, scanning codes, uploading large media reliably and playing video.

By

Full-Stack, Mobile & AI Engineer

Camera and video features look like a single component in a design file: a capture button, a preview, an upload progress bar. In production they're several systems: camera permissions, capture quality, compression, uploads that survive bad networks, server-side transcoding, and playback that adapts to the viewer's connection.

This guide covers React Native camera and media work in 2026: choosing between expo-camera and VisionCamera, picking photos and videos, scanning codes, uploading large files reliably, and playing video smoothly. It's informed by building Spoxio, a sports social app built around athletes' highlight videos, with upload and transcoding.

Key takeaways

  • expo-camera covers most needs: photos, video and barcode scanning with a simple API.
  • VisionCamera is for advanced capture: frame processors, precise format control, high frame rates.
  • Use the system picker (expo-image-picker) for choosing existing photos and videos, which also avoids broad media permissions.
  • Upload large media directly to storage with pre-signed URLs, and process it on the server, rather than streaming through your API.
  • Transcode videos server-side into streaming formats and sizes, then play them with a player that supports adaptive streaming.

Choosing a camera library

Needexpo-cameraVisionCamera
Take photos and record videoYesYes
Scan QR codes and barcodesYesYes (code scanner)
Real-time frame processing (ML, filters)LimitedFrame processors
Fine control of formats, frame rates, HDRBasicDetailed
SimplicityVery simpleMore setup

Start with expo-camera unless you need real-time processing or precise capture control. (The old react-native-camera package is no longer maintained; its users moved to VisionCamera.)

What is VisionCamera?

VisionCamera, from Margelo, is the high-performance camera library for React Native: detailed control of formats and frame rates, plus frame processors that run code such as machine learning on each frame. Version 5, current in 2026, reworked the API around outputs; the basic view is short:

const { hasPermission, requestPermission } = useCameraPermission();

<Camera style={{ flex: 1 }} isActive={true} device="back" />

It works in Expo through app config (camera and microphone permissions) and a development build, not in Expo Go. When it shows a black screen on Android, check the permission state, that isActive is true, and that you're testing on a device with a camera rather than an emulator without one.

For "take a photo or pick one" flows, you often don't need a camera screen at all. expo-image-picker opens the system camera or the photo library and returns the result:

import * as ImagePicker from "expo-image-picker";

export async function takePhoto() {
  const { granted } = await ImagePicker.requestCameraPermissionsAsync();
  if (!granted) return null;
  const result = await ImagePicker.launchCameraAsync({ mediaTypes: ["images"], quality: 0.8 });
  return result.canceled ? null : result.assets[0];
}

Offer both options from one button with an action sheet ("Take photo" or "Choose from library"); it's the pattern users already know from other apps.

Permissions done right

  • Write purpose strings that explain the feature ("Record highlights to share with scouts"), not just "Camera access needed".
  • Ask for camera and microphone access when the user starts recording, not at launch.
  • Prefer the system photo picker for choosing existing media: it doesn't require broad photo library permission, and Google Play restricts broad photo and video access to apps that truly need it.

Picking existing photos and videos

import * as ImagePicker from "expo-image-picker";

export async function pickVideo() {
  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ["videos"],
    allowsEditing: true,
    quality: 1,
  });
  if (result.canceled) return null;
  return result.assets[0]; // uri, duration, width, height, fileSize
}

Check duration and file size before uploading, and tell users early if a video is too long rather than after a slow upload fails.

Camera to text, base64 and other common requests

  • Reading text from the camera (OCR): use on-device text recognition, such as Google's ML Kit through a community library or a VisionCamera frame processor, or send the photo to a cloud OCR service when accuracy matters more than privacy.
  • Base64 images: pickers can return base64, but it inflates data by about a third and holds the whole file in memory. Upload the file itself whenever your API allows it.
  • Square or cropped photos: allowsEditing with an aspect in expo-image-picker gives users the system crop screen.

Uploading large media reliably

Video files are big, and mobile networks are unreliable. The pattern that holds up:

  1. Ask your server for a pre-signed upload URL (for example to S3 or similar object storage) for this specific file.
  2. Upload directly from the device to storage, not through your API server.
  3. Show real progress and allow retries; for very large files, use multipart uploads that can resume.
  4. Notify your server when the upload completes, which then starts processing.
  5. Mark the post as "processing" in the app until the server finishes.

Compress or downscale on the device first when full quality isn't needed; a 4K original is rarely necessary for a social highlight.

Capture quality and file size

Default capture settings are rarely right for an app that uploads media. A minute of 4K video can be hundreds of megabytes, which is slow to upload and expensive to store. Decide what the product actually needs: a social highlight might be 1080p at a moderate bitrate, a document scan a sharp still at a fixed size. Note that iPhones record HEVC by default, which is efficient but not universally playable, so transcode on the server rather than assuming one format. If uploads are slow for your users, compress on the device before uploading, and test the result on the smallest screens and slowest phones you support.

Testing media features

Media bugs hide in the conditions you don't test: a 10-minute video on a slow connection, an upload interrupted by a phone call, a recording started with low storage, a user who denied microphone access but allowed the camera. Build a short test script covering those cases and run it on real devices before every release that touches capture or upload.

Server-side processing

Raw uploads aren't ready for playback. A processing step typically:

  • Transcodes to widely supported codecs and to adaptive streaming formats (HLS), in several resolutions.
  • Generates thumbnails and a poster frame for feeds.
  • Checks content where moderation matters, before the video becomes public.
  • Stores outputs behind a CDN for fast playback worldwide.

Managed services (cloud media services or video platforms) handle this well; building your own transcoding pipeline only makes sense at scale.

From the field: For Spoxio, a social network and scouting platform for sport, I built the athlete-and-scout app with highlight video upload and transcoding, profile discovery, feeds and follows, direct messaging, live streaming and multi-voice chat rooms, plus a verification pipeline and moderation flows that protect athletes. Video features are where upload reliability and server-side processing decide the user experience.

Playing video

  • Use expo-video (the modern Expo video player) or another maintained player that supports HLS for adaptive streaming.
  • Autoplay muted in feeds, only for the visible item, and pause videos that scroll off screen.
  • Preload carefully: the next video only, to save data.
  • Show the poster image while loading, so feeds don't flash black.

Scanning QR codes and barcodes

expo-camera can scan common code types directly, which is ideal for check-ins, tickets and product lookups. Throttle scan callbacks so one code triggers one action, and give users a manual-entry fallback for damaged codes.

FAQ

Which camera library should I use in React Native?

Start with expo-camera for photos, video and barcode scanning. Choose VisionCamera when you need real-time frame processing, such as on-device machine learning or filters, or fine control over capture formats and frame rates.

How do I upload large videos from a React Native app?

Get a pre-signed URL from your server, upload directly from the device to object storage with progress and retries (multipart for very large files), then notify your server to process the video. Avoid sending large files through your API server.

Do I need to transcode videos uploaded from the app?

Yes, for anything you'll play back to other users. Transcoding into streaming formats and several resolutions makes playback fast and reliable on different networks, and lets you generate thumbnails and run moderation before videos go public.

How do I let users pick photos without full library access?

Use the system photo picker through expo-image-picker. It lets users choose specific photos or videos without granting your app access to their whole library, which is better for privacy and aligns with Google Play's photo and video permissions policy.

Next steps

If you're building features around photos, video or scanning and want uploads and playback that hold up on real networks, I can design the pipeline from capture to CDN. Get in touch, or see how I work as a React Native developer.

Sources

Bhuwanesh Sisodia

Bhuwanesh Sisodia

Full-Stack, Mobile & AI Engineer

Bhuwanesh Sisodia is a Full-Stack, Mobile & AI Engineer based in Mumbai, with 7+ years of experience and 50+ apps shipped to the App Store and Google Play. He works independently with startups and product teams worldwide.

About meGitHubLinkedInX

Related