見出し画像

react-native-vision-camera の使い方

「react-native-vision-camera」の使い方をまとめました。

【注意】最新版のreact-native@0.74ではビルド失敗するため、react-native@0.73.6で動作確認しました。


前回

1. react-native-vision-camera

react-native-vision-camera」は、React Native用のカメラライブラリです。機能は次のとおりです。

・写真と動画のキャプチャ
・QR・バーコードスキャナー
・カスタマイズ可能なデバイスとマルチカメラ (魚眼/ズーム)
・カスタマイズ可能な解像度とアスペクト比 (4k/8k)
・カスタマイズ可能な FPS (30..240 FPS)
・フレームプロセッサ (顔認識、AIオブジェクト検出、リアルタイム動画チャットなどを実行するJSワークレット)
・カメラに図形・テキスト・フィルタ・シェーダーを描画
・スムーズなズーム (再アニメーション)
・高速一時停止と再開
・HDR および夜間モード
・カスタムC++/GPUアクセラレーション動画パイプライン

2. カメラの使用手順

カメラの使用手順は、次のとおりです。

(1) パッケージのインストール。

$ npm install react-native-vision-camera
$ cd ios
$ pod install
$ cd ..

(2) iosプロジェクトの Info.plist を開き、最も外側の <dict> 内に次の行を追加。

<key>NSCameraUsageDescription</key>
<string>写真を撮るためにカメラを使用します</string>
<key>NSMicrophoneUsageDescription</key>
<string>動画を撮影するためにマイクを使用します。</string>

(3) androidプロジェクトの AndroidManifest.xml を開き、<manifest> 内に次の行を追加。

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

(4) コードの編集。

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

// アプリ
export default function App() {
  const { hasPermission, requestPermission } = useCameraPermission(); // カメラの権限の取得
  const device = useCameraDevice('back'); // カメラデバイスの取得
  const camera = useRef<Camera>(null); // カメラの参照の取得

  // 初回起動時に呼ばれる
  useEffect(() => {
    if (hasPermission === false) {
      // 権限を要求
      requestPermission();
    }
  }, []);

  // 写真撮影ボタン押下時に呼ばれる
  const takePhoto = async () => {
    if (camera.current) {
      const photo = await camera.current.takePhoto();
      console.log(photo);
    }
  };

  // デバイスなし
  if (device == null) {
    return <View />;
  }

  // 権限を拒否
  if (hasPermission == false) {
    return (
      <View>
        <Text>カメラの権限が必要です。</Text>
        <Button title="設定を開く" onPress={() => Linking.openSettings()} />
      </View>
    );
  }

  // 権限を許可
  return (
    <View style={styles.container}>
      <Camera
        style={StyleSheet.absoluteFill}
        device={device}
        isActive={true}
        ref={camera}
        photo={true}
      />
      <Button title="撮影" onPress={takePhoto} />
    </View>
  );
}

// スタイル
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'flex-end',
  },
});

◎ カメラの権限の取得
カメラを使用する場合はuseCameraPermission()、マイクを使用する場合はuseMicrophonePermission()をフックします。

これらは次の3つの状態を持ちます。

(1) アプリの初回起動時、hasPermission は false です。今すぐ requestPermission() を呼び出してください。
(2) ユーザーが許可した場合は、hasPermission は true です。<Camera> ビューでプレビューを表示してください。
(3) ユーザーが拒否した場合は、hasPermission は false です。Linking API を使用してアプリ設定を開き、カメラ権限を付与する必要があることをユーザーに伝えます。

◎ プレビューの表示
useCameraDevice()でカメラデバイス、useRef<Camera>()でカメラの参照をを取得し、<Camera>でカメラのビューを表示します。

(5) 実行。
撮影ボタンを押すと、photoオブジェクトの情報がログ出力されます。

{"height": 3024, "isMirrored": false, "isRawPhoto": false, "orientation": "portrait", "path": "/data/user/0/com.awesomeproject/cache/mrousavy-9174041254606867901.jpg", "width": 4032}

3. カメラデバイス

「カメラデバイス」は、写真・動画の撮影に使用できる物理 (または仮想) デバイスです。

3-1. 物理カメラデバイス

「物理カメラデバイス」は、携帯電話のカメラレンズです。物理カメラデバイスごとに、キャプチャ形式、解像度、ズームレベルなどの仕様が異なります。一部の携帯電話には、複数の物理カメラデバイスが搭載されています。

【例】

・Backside Wide-Angle Camera
・Frontside Wide-Angle Camera (FaceTime HD)
・Ultra-Wide-Angle back camera

3-2. 仮想カメラデバイス

「仮想カメラデバイス」は、1つ以上の物理カメラデバイスを組み合わせたもので、ズーム中に仮想デバイスを切り替える機能や、すべての物理カメラからの写真を組み合わせて、より高品質の画像を生成する機能などを提供します。

【例】

・Triple-Camera
・Dual-Wide-Angle Camera

3-3. カメラデバイスの取得

カメラデバイスはuseCameraDevice()で取得できます。

const device = useCameraDevice('back')

カメラデバイスは次の仕様で構成されます。
console.log(device)で確認できます。

・id : カメラデバイスのID
・position : 携帯電話に対する位置
 ・back : 携帯電話の背面
 ・front : 携帯電話の前面
 ・external : 外部デバイス
・physicalDevices : レンズ
 ・ultra-wide-angle-camera : 魚眼カメラ (0.5x zoom)
 ・wide-angle-camera : デフォルトカメラ (1x zoom)
 ・telephoto-camera : ズームインカメラ (3x zoom)
・sensorOrientation : 携帯電話に対する向き
 ・landscape-left : 横長左向き (90° 回転)
・minZoom : 最小ズーム係数 (1)
・maxZoom : 最大ズーム係数 (8)
・neutralZoom : minZoom と maxZoom の間の値 (1)
・formats : サポートするCamera Formatsのリスト
 ・Video Resolution
 ・Photo Resolution
 ・FPS
 ・Video Stabilization Mode参照
 ・Pixel Format参照

4. プレビュー

<Camera> で、カメラのプレビューをレンダリングします。
ほとんどの場合は style={{ flex: 1 }} で済みます。

4-1. ライフサイクル

CameraのisActiveで、セッションを一時停止しながら、ウォームな状態に維持することができます。これは、カメラを完全にアンマウントするよりも望ましい方法です。セッションの再開は、カメラビューを再マウントするよりもはるかに高速です。

ユーザーがアプリを最小化した時 (useAppState())、新しい画面に移動した時 (useIsFocused()) に、カメラを一時停止することができます。

function App() {
  const isFocused = useIsFocused()
  const appState = useAppState()
  const isActive = isFocused && appState === "active"

  return <Camera {...props} isActive={isActive} />
}

4-2. リサイズモード

「cover」(ビューを埋めるために中央に切り取る) または「contain」(ビュー内に収まるようにスケーリング) のいずれかを指定します。

4-3. プレビューの無効化

preview={false} で無効化できます。

4-4. FPS

fpsでフレームレートを指定できます。デフォルトは30FPSです。

<Camera {...props} fps={60} />

4-5. 解像度

iOSでは動画解像度でプレビュー解像度が決まるため、動画解像度が低い場合は、プレビュー解像度も低くなります。

const lowResolutionFormat = useCameraFormat(device, [
  { videoResolution: { width: 640, height: 480 } },
])

Androidでは、プレビューは常にフル HD またはプレビューのサイズのいずれか小さい方になります。

4-6. オーバーレイとマスク

Androidでは、プレビュービューは androidPreviewViewType を通じて制御可能な2つの実装モードをサポートしています。

・surface-view : レンダリングにSurfaceView を使用。これはより効率的で、HDRレンダリングをサポートするが、マスク、透明度、回転、クリッピングをサポートしない
・texture-view : レンダリングにTextureViewを使用。これは効率が低く、HDRレンダリングはサポートしないが、マスク、透明度、回転、クリッピングをサポートする

<Camera {...props} androidPreviewViewType="texture-view" />

5. 撮影

5-1. 写真撮影

写真撮影には、写真キャプチャを有効にする必要があります。

<Camera
  {...props}
  photo={true}
/>

takePhoto() で撮影します。

const photo = await camera.current.takePhoto()

TakePhotoOptionsでフラッシュの有効化、シャッター音の無効化などをカスタマイズできます。

この関数は、一時フォルダに保存される PhotoFile を返します。この PhotoFile は、<Image> または <FastImage> を使用して表示したり、バックエンドにアップロードしたり、react-native-cameraroll でカメラロールに保存したりできます。

5-2. フォーカス

カメラで特定ポイントをフォーカスするには、focus()を使用します。

await camera.current.focus({ x: tapEvent.x, y: tapEvent.y })

5-3. 解像度

カスタム解像度を使用する場合は、Cameraのformatを設定します。

const format = useCameraFormat(device, [
  { photoResolution: { width: 1280, height: 720 } }
])

return <Camera {...props} format={format} />

5-4. フラッシュ

takePhoto()には、auto (フラッシュを自動的に有効)、on (常に有効)、off (有効にしない)を設定できます。

const photo = await camera.current.takePhoto({
  flash: 'on' // 'auto' | 'off'
})

フラッシュは hasFlashがtrueであるカメラデバイスでのみ使用できるます。

5-5. 写真品質バランス

photoQualityBalanceで、速度と品質どちらを優先するか設定できます。

return <Camera {...props} photoQualityBalance="speed" />

5-6. スナップショット

スナップショットは、最大16ミリ秒の速度で写真撮影できます。カメラのプレビューから取得され、AE/AF/AWB のプリキャプチャシーケンスは実行されません。

const snapshot = await camera.current.takeSnapshot({
  quality: 90
})

5-7. 写真のカメラロール保存

写真をカメラロールに保存するには、react-native-cameraroll を使用できます。

const file = await camera.current.takePhoto()
await CameraRoll.save(`file://${file.path}`, {
  type: 'photo',
})

5-8. 写真のデータの取得

写真のピクセルデータを取得するには、ローカルファイルをfetch() でBlobとして読み取ります。

const file = await camera.current.takePhoto()
const result = await fetch(`file://${file.path}`)
const data = await result.blob();

次回



この記事が気に入ったらサポートをしてみませんか?