CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-expo-camera

A React component that renders a camera preview for React Native apps with photo/video capture, barcode scanning, and cross-platform support.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

camera-component.mddocs/

Camera Component

The CameraView component is the core camera interface that renders a live camera preview and provides comprehensive camera control functionality across iOS, Android, and Web platforms.

Capabilities

CameraView Component

The main React component for camera functionality.

/**
 * React component that renders a camera preview with full camera controls
 */
declare const CameraView: React.ForwardRefExoticComponent<
  CameraViewProps & React.RefAttributes<CameraViewRef>
>;

CameraView Props

Complete configuration interface for the camera component.

interface CameraViewProps extends ViewProps {
  /**
   * Camera facing direction
   * @default 'back'
   */
  facing?: CameraType;
  
  /**
   * Flash mode setting
   * @default 'off'
   */
  flash?: FlashMode;
  
  /**
   * Zoom level (0 to 1, where 1 is maximum zoom)
   * @default 0
   */
  zoom?: number;
  
  /**
   * Camera mode for capture
   * @default 'picture'
   */
  mode?: CameraMode;
  
  /**
   * Whether to mute video recording
   * @default false
   */
  mute?: boolean;
  
  /**
   * Whether to mirror the image (front camera)
   * @default false
   */
  mirror?: boolean;
  
  /**
   * Auto focus mode (iOS only)
   * @default 'off'
   */
  autofocus?: FocusMode;
  
  /**
   * Whether camera should be active (iOS only)
   * @default true
   */
  active?: boolean;
  
  /**
   * Video quality setting
   */
  videoQuality?: VideoQuality;
  
  /**
   * Video bitrate in bits per second
   */
  videoBitrate?: number;
  
  /**
   * Whether to animate shutter
   * @default true
   */
  animateShutter?: boolean;
  
  /**
   * Picture size string (use getAvailablePictureSizes to get options)
   */
  pictureSize?: string;
  
  /**
   * Selected lens identifier (iOS only)
   * @default 'builtInWideAngleCamera'
   */
  selectedLens?: string;
  
  /**
   * Whether to enable torch
   * @default false
   */
  enableTorch?: boolean;
  
  /**
   * Video stabilization mode (iOS only)
   */
  videoStabilizationMode?: VideoStabilization;
  
  /**
   * Barcode scanner configuration
   */
  barcodeScannerSettings?: BarcodeSettings;
  
  /**
   * Loading poster image URL (Web only)
   */
  poster?: string;
  
  /**
   * Allow responsive orientation when locked (iOS only)
   */
  responsiveOrientationWhenOrientationLocked?: boolean;
  
  /**
   * Camera preview aspect ratio (Android only)
   */
  ratio?: CameraRatio;
  
  /**
   * Callback when camera is ready
   */
  onCameraReady?: () => void;
  
  /**
   * Callback when camera mount fails
   */
  onMountError?: (event: CameraMountError) => void;
  
  /**
   * Callback when barcode is scanned
   */
  onBarcodeScanned?: (result: BarcodeScanningResult) => void;
  
  /**
   * Callback when orientation changes (iOS only)
   */
  onResponsiveOrientationChanged?: (event: ResponsiveOrientationChanged) => void;
  
  /**
   * Callback when available lenses change (iOS only)
   */
  onAvailableLensesChanged?: (event: AvailableLenses) => void;
}

Static Methods and Properties

Static methods and properties available on the CameraView class.

/**
 * Check whether the current device has a camera
 * This is useful for web and simulators cases
 * @platform web
 * @returns Promise resolving to boolean indicating camera availability
 */
static isAvailableAsync(): Promise<boolean>;

/**
 * Get available video codecs for the current device
 * @platform ios  
 * @returns Promise resolving to array of supported video codecs
 */
static getAvailableVideoCodecsAsync(): Promise<VideoCodec[]>;

/**
 * Property indicating if modern barcode scanner is available
 * @platform ios
 */
static readonly isModernBarcodeScannerAvailable: boolean;

/**
 * Launch the modern barcode scanner with options
 * @platform ios
 * @param options Scanner configuration options
 * @returns Promise resolving when scanner launches
 */
static launchScanner(options?: ScanningOptions): Promise<void>;

/**
 * Dismiss the modern barcode scanner
 * @platform ios  
 * @returns Promise resolving when scanner dismisses
 */
static dismissScanner(): Promise<void>;

/**
 * Listen for modern barcode scanner events
 * @platform ios
 * @param listener Event listener function
 * @returns Event subscription object
 */
static onModernBarcodeScanned(listener: (event: ScanningResult) => void): EventSubscription;

Component Ref Methods

Methods available through the component ref for programmatic camera control.

interface CameraViewRef {
  /**
   * Take a picture with the specified options
   * @param options Picture capture configuration
   * @returns Promise resolving to captured picture data
   */
  readonly takePicture: (options?: CameraPictureOptions) => Promise<CameraCapturedPicture>;
  
  /**
   * Take a picture and return a PictureRef for native image handling
   * @param options Picture capture configuration
   * @returns Promise resolving to picture reference
   */
  readonly takePictureRef?: (options?: CameraPictureOptions) => Promise<PictureRef>;
  
  /**
   * Get available picture sizes for the current camera
   * @returns Promise resolving to array of size strings
   */
  readonly getAvailablePictureSizes: () => Promise<string[]>;
  
  /**
   * Get available camera lenses (iOS only)
   * @returns Promise resolving to array of lens identifiers
   */
  readonly getAvailableLenses: () => Promise<string[]>;
  
  /**
   * Start video recording
   * @param options Recording configuration options
   * @returns Promise resolving to video file info
   */
  readonly record: (options?: CameraRecordingOptions) => Promise<{ uri: string }>;
  
  /**
   * Toggle video recording state (iOS 18+ only)
   * @platform ios
   * @returns Promise resolving when toggle completes
   */
  readonly toggleRecording: () => Promise<void>;
  
  /**
   * Stop video recording
   * @returns Promise resolving when recording stops
   */
  readonly stopRecording: () => Promise<void>;
  
  /**
   * Launch modern barcode scanner (iOS only)
   * @returns Promise resolving when scanner launches
   */
  readonly launchModernScanner: () => Promise<void>;
  
  /**
   * Resume camera preview
   * @returns Promise resolving when preview resumes
   */
  readonly resumePreview: () => Promise<void>;
  
  /**
   * Pause camera preview
   * @returns Promise resolving when preview pauses
   */
  readonly pausePreview: () => Promise<void>;
}

Type Definitions

Core types used by the camera component.

type CameraType = 'front' | 'back';

type FlashMode = 'off' | 'on' | 'auto';

type CameraMode = 'picture' | 'video';

type CameraRatio = '4:3' | '16:9' | '1:1';

type FocusMode = 'on' | 'off';

type VideoQuality = '2160p' | '1080p' | '720p' | '480p' | '4:3';

type VideoCodec = 'avc1' | 'hvc1' | 'jpeg' | 'apcn' | 'ap4h';

type VideoStabilization = 'off' | 'standard' | 'cinematic' | 'auto';

type CameraOrientation = 'portrait' | 'portraitUpsideDown' | 'landscapeLeft' | 'landscapeRight';

interface CameraMountError {
  message: string;
}

interface ResponsiveOrientationChanged {
  orientation: CameraOrientation;
}

interface AvailableLenses {
  lenses: string[];
}

interface BarcodeSettings {
  barcodeTypes: BarcodeType[];
}

interface ScanningOptions {
  /**
   * Array of barcode types to scan for
   */
  barcodeTypes: BarcodeType[];
  
  /**
   * Whether pinch-to-zoom gesture is enabled (iOS only)
   * @default true
   */
  isPinchToZoomEnabled?: boolean;
  
  /**
   * Whether guidance text appears over video (iOS only)  
   * @default true
   */
  isGuidanceEnabled?: boolean;
  
  /**
   * Whether highlights appear around recognized items (iOS only)
   * @default false
   */
  isHighlightingEnabled?: boolean;
}

interface ScanningResult {
  /**
   * The barcode type
   */
  type: string;
  
  /**
   * The parsed information encoded in the barcode
   */
  data: string;
  
  /**
   * The raw information encoded in the barcode (Android only)
   */
  raw?: string;
}

Usage Examples

Basic Camera Setup

import React, { useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import { CameraView, CameraType } from 'expo-camera';

export function BasicCamera() {
  const cameraRef = useRef<CameraView>(null);

  return (
    <View style={styles.container}>
      <CameraView
        ref={cameraRef}
        style={styles.camera}
        facing="back"
        flash="off"
        mode="picture"
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  camera: { flex: 1 },
});

Advanced Camera Configuration

import React, { useState, useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import { CameraView, CameraType, FlashMode, VideoQuality } from 'expo-camera';

export function AdvancedCamera() {
  const [facing, setFacing] = useState<CameraType>('back');
  const [flash, setFlash] = useState<FlashMode>('off');
  const [zoom, setZoom] = useState(0);
  const cameraRef = useRef<CameraView>(null);

  const handleCameraReady = () => {
    console.log('Camera is ready');
  };

  const handleMountError = (error: { message: string }) => {
    console.error('Camera mount error:', error.message);
  };

  return (
    <View style={styles.container}>
      <CameraView
        ref={cameraRef}
        style={styles.camera}
        facing={facing}
        flash={flash}
        zoom={zoom}
        mode="picture"
        animateShutter={true}
        enableTorch={false}
        mirror={facing === 'front'}
        videoQuality="1080p"
        videoBitrate={10000000}
        onCameraReady={handleCameraReady}
        onMountError={handleMountError}
        barcodeScannerSettings={{
          barcodeTypes: ['qr', 'ean13', 'code128']
        }}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  camera: { flex: 1 },
});

Using Component Ref Methods

import React, { useRef } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import { CameraView } from 'expo-camera';

export function CameraWithControls() {
  const cameraRef = useRef<CameraView>(null);

  const getAvailableSizes = async () => {
    if (cameraRef.current) {
      const sizes = await cameraRef.current.getAvailablePictureSizes();
      console.log('Available picture sizes:', sizes);
    }
  };

  const getAvailableLenses = async () => {
    if (cameraRef.current) {
      try {
        const lenses = await cameraRef.current.getAvailableLenses();
        console.log('Available lenses:', lenses);
      } catch (error) {
        console.log('Lenses not supported on this platform');
      }
    }
  };

  const togglePreview = async () => {
    if (cameraRef.current) {
      // Example: pause and resume preview
      await cameraRef.current.pausePreview();
      setTimeout(async () => {
        await cameraRef.current?.resumePreview();
      }, 2000);
    }
  };

  return (
    <View style={{ flex: 1 }}>
      <CameraView
        ref={cameraRef}
        style={{ flex: 1 }}
        facing="back"
      />
      <View style={{ flexDirection: 'row', justifyContent: 'space-around', padding: 20 }}>
        <TouchableOpacity onPress={getAvailableSizes}>
          <Text>Get Sizes</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={getAvailableLenses}>
          <Text>Get Lenses</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={togglePreview}>
          <Text>Toggle Preview</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
}

Using Static Methods

import React, { useEffect, useState } from 'react';
import { View, Text, TouchableOpacity, Platform } from 'react-native';
import { CameraView, VideoCodec, ScanningResult } from 'expo-camera';

export function CameraCapabilities() {
  const [isCameraAvailable, setIsCameraAvailable] = useState<boolean | null>(null);
  const [videoCodecs, setVideoCodecs] = useState<VideoCodec[]>([]);
  const [isModernScannerAvailable, setIsModernScannerAvailable] = useState(false);

  useEffect(() => {
    checkCameraCapabilities();
  }, []);

  const checkCameraCapabilities = async () => {
    // Check camera availability (Web only)
    if (Platform.OS === 'web') {
      try {
        const available = await CameraView.isAvailableAsync();
        setIsCameraAvailable(available);
      } catch (error) {
        console.log('Camera availability check not supported');
      }
    }

    // Check available video codecs (iOS only)
    if (Platform.OS === 'ios') {
      try {
        const codecs = await CameraView.getAvailableVideoCodecsAsync();
        setVideoCodecs(codecs);
      } catch (error) {
        console.log('Video codecs not available');
      }
    }

    // Check modern scanner availability
    setIsModernScannerAvailable(CameraView.isModernBarcodeScannerAvailable);
  };

  const launchScanner = async () => {
    if (Platform.OS === 'ios' && CameraView.isModernBarcodeScannerAvailable) {
      try {
        // Listen for scan results
        const subscription = CameraView.onModernBarcodeScanned((result: ScanningResult) => {
          console.log('Scanned:', result.data);
          subscription.remove();
        });

        // Launch the scanner
        await CameraView.launchScanner({
          barcodeTypes: ['qr', 'ean13'],
          isPinchToZoomEnabled: true,
          isGuidanceEnabled: true,
          isHighlightingEnabled: true,
        });
      } catch (error) {
        console.error('Failed to launch scanner:', error);
      }
    }
  };

  return (
    <View style={{ flex: 1, padding: 20 }}>
      <Text>Camera Available: {isCameraAvailable?.toString() ?? 'N/A'}</Text>
      <Text>Video Codecs: {videoCodecs.join(', ') || 'N/A'}</Text>
      <Text>Modern Scanner: {isModernScannerAvailable.toString()}</Text>
      
      {isModernScannerAvailable && (
        <TouchableOpacity onPress={launchScanner} style={{ marginTop: 20, padding: 10, backgroundColor: 'blue' }}>
          <Text style={{ color: 'white' }}>Launch Scanner</Text>
        </TouchableOpacity>
      )}
      
      <CameraView style={{ flex: 1, marginTop: 20 }} facing="back" />
    </View>
  );
}

Platform-Specific Features

import React, { useRef } from 'react';
import { Platform } from 'react-native';
import { CameraView, VideoStabilization } from 'expo-camera';

export function PlatformSpecificCamera() {
  const cameraRef = useRef<CameraView>(null);

  const iosSpecificProps = Platform.OS === 'ios' ? {
    autofocus: 'on' as const,
    active: true,
    selectedLens: 'builtInWideAngleCamera',
    videoStabilizationMode: 'standard' as VideoStabilization,
    responsiveOrientationWhenOrientationLocked: true,
  } : {};

  const androidSpecificProps = Platform.OS === 'android' ? {
    ratio: '16:9' as const,
  } : {};

  const webSpecificProps = Platform.OS === 'web' ? {
    poster: 'https://example.com/camera-loading.png',
  } : {};

  return (
    <CameraView
      ref={cameraRef}
      style={{ flex: 1 }}
      facing="back"
      {...iosSpecificProps}
      {...androidSpecificProps}
      {...webSpecificProps}
    />
  );
}

docs

barcode-scanning.md

camera-component.md

index.md

media-capture.md

permissions.md

tile.json