最完整react-native-vision-camera指南:从入门到精通

【免费下载链接】react-native-vision-camera 📸 A powerful, high-performance React Native Camera library. 【免费下载链接】react-native-vision-camera 项目地址: https://gitcode.com/GitHub_Trending/re/react-native-vision-camera

引言:告别React Native相机开发痛点

你是否还在为React Native项目中的相机功能开发而烦恼?尝试过多个库却始终无法满足性能需求?react-native-vision-camera的出现彻底改变了这一现状。作为一款高性能、功能全面的相机库,它不仅支持4K视频录制、HDR模式和夜间模式,还创新性地引入了帧处理器(Frame Processors),让实时视频处理在React Native中成为可能。本文将带你从环境搭建到高级功能实现,全面掌握react-native-vision-camera的使用,让你的相机应用性能媲美原生应用。

读完本文,你将能够:

  • 快速搭建react-native-vision-camera开发环境
  • 实现相机权限请求与设备管理
  • 掌握高级拍摄功能(HDR、夜景模式、视频防抖)
  • 开发自定义帧处理器进行实时视频分析
  • 优化相机性能,解决常见性能瓶颈
  • 处理相机开发中的常见错误与异常

1. 环境搭建与安装

1.1 系统要求

react-native-vision-camera对开发环境有一定要求:

  • iOS 12.0+
  • Android API 21+ (Android 5.0+)
  • React Native 0.64+
  • Node.js 14+

1.2 安装步骤

<Tabs groupId="installation" defaultValue="rn" values={[ {label: 'React Native', value: 'rn'}, {label: 'Expo', value: 'expo'} ]}>

# 使用npm安装
npm install react-native-vision-camera

# 使用yarn安装
yarn add react-native-vision-camera

# iOS平台需要额外安装pod依赖
cd ios && pod install && cd ..
# Expo项目安装
npx expo install react-native-vision-camera

# 添加Expo插件配置
npx expo prebuild

1.3 权限配置

iOS配置

编辑ios/项目名称/Info.plist文件,添加以下权限描述:

<key>NSCameraUsageDescription</key>
<string>我们需要访问您的相机进行拍照和录像</string>
<key>NSMicrophoneUsageDescription</key>
<string>我们需要访问您的麦克风进行录像</string>
Android配置

编辑android/app/src/main/AndroidManifest.xml文件,添加权限声明:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2. 基础使用:从权限请求到相机渲染

2.1 权限请求

react-native-vision-camera提供了两种权限请求方式:钩子API和命令式API,可根据项目需求选择。

钩子API(推荐)
import { useCameraPermission, useMicrophonePermission } from 'react-native-vision-camera';

function CameraPermissionPage() {
  const { hasPermission: hasCameraPermission, requestPermission: requestCameraPermission } = useCameraPermission();
  const { hasPermission: hasMicPermission, requestPermission: requestMicPermission } = useMicrophonePermission();
  
  const requestAllPermissions = async () => {
    const cameraGranted = await requestCameraPermission();
    const micGranted = await requestMicPermission();
    return cameraGranted && micGranted;
  };
  
  if (!hasCameraPermission || !hasMicPermission) {
    return (
      <View style={styles.container}>
        <Text>需要相机和麦克风权限才能使用相机功能</Text>
        <Button title="授予权限" onPress={requestAllPermissions} />
      </View>
    );
  }
  
  return <CameraPage />;
}
命令式API
import { Camera } from 'react-native-vision-camera';

async function checkAndRequestPermissions() {
  // 检查相机权限状态
  const cameraPermissionStatus = Camera.getCameraPermissionStatus();
  // 检查麦克风权限状态
  const micPermissionStatus = Camera.getMicrophonePermissionStatus();
  
  // 如果权限未确定,则请求权限
  if (cameraPermissionStatus === 'not-determined') {
    const cameraResult = await Camera.requestCameraPermission();
    if (cameraResult !== 'granted') {
      console.error('相机权限被拒绝');
      return false;
    }
  }
  
  if (micPermissionStatus === 'not-determined') {
    const micResult = await Camera.requestMicrophonePermission();
    if (micResult !== 'granted') {
      console.error('麦克风权限被拒绝');
      return false;
    }
  }
  
  return true;
}

2.2 相机组件基础使用

以下是一个基础的相机组件使用示例,包含设备选择、权限检查和相机渲染:

import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { Camera, useCameraDevice, useCameraPermission } from 'react-native-vision-camera';

function BasicCamera() {
  // 获取相机权限状态
  const { hasPermission, requestPermission } = useCameraPermission();
  // 获取后置摄像头设备
  const device = useCameraDevice('back');
  // 相机是否激活
  const [isActive, setIsActive] = useState(false);
  
  useEffect(() => {
    // 组件挂载时请求权限
    const getPermissions = async () => {
      const granted = await requestPermission();
      if (granted) {
        // 权限获取后激活相机
        setIsActive(true);
      }
    };
    
    getPermissions();
  }, [requestPermission]);
  
  // 无相机权限时显示
  if (!hasPermission) {
    return <Text>请授予相机权限以使用相机功能</Text>;
  }
  
  // 无可用相机设备时显示
  if (device == null) {
    return <Text>未找到可用相机设备</Text>;
  }
  
  return (
    <View style={styles.container}>
      {/* 相机组件 */}
      <Camera
        style={StyleSheet.absoluteFill}
        device={device}
        isActive={isActive}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#000',
  },
});

export default BasicCamera;

3. 相机设备与格式管理

3.1 相机设备类型

react-native-vision-camera将相机设备分为物理设备和虚拟设备:

设备类型 描述 示例
物理设备 手机上的实际摄像头镜头 后置广角摄像头、前置摄像头
虚拟设备 多个物理设备的组合 三摄系统(超广角+广角+长焦)

每个相机设备包含以下关键属性:

interface CameraDevice {
  id: string;                 // 设备唯一标识符
  position: 'back' | 'front' | 'external';  // 设备位置
  physicalDevices: PhysicalDeviceType[];  // 包含的物理设备
  minZoom: number;            // 最小变焦倍数
  maxZoom: number;            // 最大变焦倍数
  neutralZoom: number;        // 中性变焦倍数(默认1x)
  hasFlash: boolean;          // 是否有闪光灯
  supportsLowLightBoost: boolean;  // 是否支持低光增强
  formats: CameraDeviceFormat[];  // 支持的格式列表
}

3.2 设备选择策略

选择合适的相机设备对应用性能至关重要。以下是不同场景下的设备选择策略:

基础设备选择
// 使用钩子API选择设备
const backDevice = useCameraDevice('back');
const frontDevice = useCameraDevice('front');

// 命令式API选择设备
const allDevices = Camera.getAvailableCameraDevices();
const wideAngleDevices = allDevices.filter(device => 
  device.physicalDevices.includes('wide-angle-camera')
);
多摄像头选择
// 优先选择包含多个物理设备的虚拟设备(如三摄系统)
const multiCameraDevice = useCameraDevice('back', {
  physicalDevices: [
    'ultra-wide-angle-camera',
    'wide-angle-camera',
    'telephoto-camera'
  ]
});

// 仅选择单广角摄像头(启动更快)
const simpleDevice = useCameraDevice('back', {
  physicalDevices: ['wide-angle-camera']
});

3.3 相机格式配置

相机格式决定了视频分辨率、帧率和其他图像属性。合理的格式选择对性能影响很大:

import { useCameraFormat } from 'react-native-vision-camera';

function OptimizedCamera() {
  const device = useCameraDevice('back');
  
  // 为视频通话选择优化的格式(平衡分辨率和帧率)
  const videoChatFormat = useCameraFormat(device, [
    { fps: 30 },  // 优先30fps帧率
    { videoResolution: { width: 1280, height: 720 } },  // 720p分辨率
    { pixelFormat: 'yuv' }  // 使用高效的YUV格式
  ]);
  
  // 为照片拍摄选择优化的格式(高分辨率)
  const photoFormat = useCameraFormat(device, [
    { photoResolution: 'max' },  // 最高照片分辨率
    { fps: 30 },  // 至少30fps
    { videoResolution: { width: 1920, height: 1080 } }  // 视频至少1080p
  ]);
  
  // 根据使用场景选择不同格式
  const format = useMemo(() => {
    return isTakingPhoto ? photoFormat : videoChatFormat;
  }, [isTakingPhoto, photoFormat, videoChatFormat]);
  
  // ... 渲染相机组件
}

3.4 多摄像头切换

实现前后摄像头切换功能:

function CameraWithSwitch() {
  const [cameraPosition, setCameraPosition] = useState<'back' | 'front'>('back');
  const device = useCameraDevice(cameraPosition);
  
  const toggleCamera = () => {
    setCameraPosition(prev => prev === 'back' ? 'front' : 'back');
  };
  
  return (
    <View style={styles.container}>
      {device && (
        <Camera
          style={StyleSheet.absoluteFill}
          device={device}
          isActive={true}
        />
      )}
      <TouchableOpacity 
        style={styles.switchButton}
        onPress={toggleCamera}
      >
        <Text style={styles.buttonText}>切换摄像头</Text>
      </TouchableOpacity>
    </View>
  );
}

4. 高级拍摄功能实现

4.1 拍照与录像功能

完整的拍照与录像实现:

function CameraCapture() {
  const camera = useRef<Camera>(null);
  const device = useCameraDevice('back');
  const [isRecording, setIsRecording] = useState(false);
  const [flashMode, setFlashMode] = useState<'off' | 'on'>('off');
  
  // 拍照功能
  const takePhoto = async () => {
    if (camera.current == null) return;
    
    try {
      const photo = await camera.current.takePhoto({
        flash: flashMode,
        enableAutoRedEyeReduction: true,
        qualityPrioritization: 'quality'
      });
      console.log('照片保存路径:', photo.path);
      // 导航到预览页面
      navigation.navigate('PhotoPreview', { photo });
    } catch (e) {
      console.error('拍照失败:', e);
    }
  };
  
  // 开始录像
  const startRecording = async () => {
    if (camera.current == null) return;
    
    setIsRecording(true);
    try {
      camera.current.startRecording({
        flash: flashMode,
        onRecordingFinished: (video) => {
          console.log('视频保存路径:', video.path);
          setIsRecording(false);
          navigation.navigate('VideoPreview', { video });
        },
        onRecordingError: (error) => {
          console.error('录像错误:', error);
          setIsRecording(false);
        }
      });
    } catch (e) {
      console.error('开始录像失败:', e);
      setIsRecording(false);
    }
  };
  
  // 停止录像
  const stopRecording = async () => {
    if (camera.current == null) return;
    
    try {
      await camera.current.stopRecording();
    } catch (e) {
      console.error('停止录像失败:', e);
    }
  };
  
  return (
    <View style={styles.container}>
      <Camera
        ref={camera}
        style={StyleSheet.absoluteFill}
        device={device}
        isActive={true}
        video={true}
        photo={true}
      />
      
      <View style={styles.controls}>
        <TouchableOpacity 
          style={styles.flashButton}
          onPress={() => setFlashMode(prev => prev === 'on' ? 'off' : 'on')}
        >
          <Text style={styles.buttonText}>{flashMode === 'on' ? '关闭闪光灯' : '打开闪光灯'}</Text>
        </TouchableOpacity>
        
        <TouchableOpacity 
          style={[styles.captureButton, { backgroundColor: isRecording ? 'red' : 'white' }]}
          onPress={isRecording ? stopRecording : takePhoto}
          onLongPress={startRecording}
        />
        
        <TouchableOpacity 
          style={styles.switchButton}
          onPress={toggleCamera}
        >
          <Ionicons name="camera-reverse" size={24} color="white" />
        </TouchableOpacity>
      </View>
    </View>
  );
}

4.2 高级拍摄模式

HDR与夜景模式
function AdvancedCameraModes() {
  const device = useCameraDevice('back');
  const [enableHdr, setEnableHdr] = useState(false);
  const [enableNightMode, setEnableNightMode] = useState(false);
  
  // 根据设备支持情况过滤格式
  const format = useCameraFormat(device, [
    { photoHdr: enableHdr ? 'supported' : undefined },
    { lowLightBoost: enableNightMode ? 'supported' : undefined },
    { fps: 30 },
    { videoResolution: 'max' }
  ]);
  
  // 检查设备是否支持HDR
  const supportsHdr = format?.supportsPhotoHdr || false;
  // 检查设备是否支持夜景模式
  const supportsNightMode = device?.supportsLowLightBoost || false;
  
  return (
    <View style={styles.container}>
      <Camera
        style={StyleSheet.absoluteFill}
        device={device}
        isActive={true}
        format={format}
        photoHdr={enableHdr}
        lowLightBoost={enableNightMode}
      />
      
      <View style={styles.modeControls}>
        {supportsHdr && (
          <TouchableOpacity
            style={[styles.modeButton, enableHdr && styles.activeMode]}
            onPress={() => setEnableHdr(!enableHdr)}
          >
            <Text style={styles.modeText}>HDR {enableHdr ? '开启' : '关闭'}</Text>
          </TouchableOpacity>
        )}
        
        {supportsNightMode && (
          <TouchableOpacity
            style={[styles.modeButton, enableNightMode && styles.activeMode]}
            onPress={() => setEnableNightMode(!enableNightMode)}
          >
            <Text style={styles.modeText}>夜景 {enableNightMode ? '开启' : '关闭'}</Text>
          </TouchableOpacity>
        )}
      </View>
    </View>
  );
}

4.3 变焦功能实现

实现平滑变焦功能:

import React, { useRef } from 'react';
import { StyleSheet, View } from 'react-native';
import { Camera } from 'react-native-vision-camera';
import Reanimated, { 
  useAnimatedGestureHandler, 
  useSharedValue, 
  useAnimatedProps 
} from 'react-native-reanimated';

// 创建动画相机组件
const AnimatedCamera = Reanimated.createAnimatedComponent(Camera);
Reanimated.addWhitelistedNativeProps({ zoom: true });

function ZoomableCamera() {
  const camera = useRef<AnimatedCamera>(null);
  const device = useCameraDevice('back');
  const zoom = useSharedValue(1);
  
  // 处理捏合手势进行变焦
  const onPinchGesture = useAnimatedGestureHandler({
    onStart: (_, context) => {
      context.startZoom = zoom.value;
    },
    onActive: (event, context) => {
      // 计算新的变焦值,限制在设备支持范围内
      const newZoom = context.startZoom * event.scale;
      zoom.value = Math.max(
        device?.minZoom || 1, 
        Math.min(newZoom, device?.maxZoom || 10)
      );
    }
  });
  
  // 创建动画属性
  const animatedProps = useAnimatedProps(() => ({
    zoom: zoom.value
  }));
  
  return (
    <View style={styles.container}>
      <PinchGestureHandler onGestureEvent={onPinchGesture}>
        <AnimatedCamera
          ref={camera}
          style={StyleSheet.absoluteFill}
          device={device}
          isActive={true}
          animatedProps={animatedProps}
        />
      </PinchGestureHandler>
      
      {/* 显示当前变焦倍数 */}
      <View style={styles.zoomIndicator}>
        <Text style={styles.zoomText}>{zoom.value.toFixed(1)}x</Text>
      </View>
    </View>
  );
}

5. 帧处理器(Frame Processors)开发

5.1 帧处理器基础

帧处理器是react-native-vision-camera最强大的功能之一,允许你直接在视频流上运行实时图像处理。要使用帧处理器,首先需要安装依赖:

# 安装工作let核心库
npm install react-native-worklets-core

# 更新babel配置
# babel.config.js
module.exports = {
  plugins: [
    ['react-native-worklets-core/plugin'],
    // ...其他插件
  ],
};

5.2 基础帧处理器

【免费下载链接】react-native-vision-camera 📸 A powerful, high-performance React Native Camera library. 【免费下载链接】react-native-vision-camera 项目地址: https://gitcode.com/GitHub_Trending/re/react-native-vision-camera

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐