Multi-Camera

Using multiple Camera Devices in a single Camera Session

A CameraSession allows attaching multiple connections to stream from multiple CameraDevices at the same time (e.g. Picture-in-Picture mode via front + back Camera) - if the system supports it.

Creating a Multi-Camera Session

To create a multi-camera CameraSession, use createCameraSession(true). Make sure supportsMultiCamSessions is true:

if (VisionCamera.supportsMultiCamSessions) {
  const session = await VisionCamera.createCameraSession(true)
}

Getting Multi-Cam capable CameraDevices

Due to hardware constraints, not every CameraDevice can be paired with every other CameraDevice, therefore VisionCamera exposes a list of supported device combinations via supportedMultiCamDeviceCombinations upfront:

const deviceFactory = await VisionCamera.createDeviceFactory()
const frontAndBackCombination =
  deviceFactory.supportedMultiCamDeviceCombinations.find((devices) => {
    return (
      devices.some((d) => d.position === 'front') &&
      devices.some((d) => d.position === 'back')
    )
  })
if (frontAndBackCombination == null)
  return

const frontDevice = frontAndBackCombination.find((d) => d.position === 'front')
const backDevice = frontAndBackCombination.find((d) => d.position === 'back')

Using multiple Connections

Then, knowing frontDevice and backDevice can be used simultaneously in a Multi-Cam session, create the outputs and build the CameraSessionConnections:

const frontPreviewOutput = VisionCamera.createPreviewOutput()
const frontPhotoOutput = VisionCamera.createPhotoOutput({})
const backPreviewOutput = VisionCamera.createPreviewOutput()
const backPhotoOutput = VisionCamera.createPhotoOutput({})

const [frontController, backController] = await session.configure([
  // Front Camera
  {
    input: frontDevice,
    outputs: [
      { output: frontPreviewOutput, mirrorMode: 'on' },
      { output: frontPhotoOutput, mirrorMode: 'off' },
    ],
    constraints: []
  },
  // Back Camera
  {
    input: backDevice,
    outputs: [
      { output: backPreviewOutput, mirrorMode: 'off' },
      { output: backPhotoOutput, mirrorMode: 'off' },
    ],
    constraints: []
  }
])
await session.start()

Each returned CameraController correlates to the connection at that index - e.g. frontController allows zooming/exposure/focus the frontDevice, and vice-versa.

Picture-in-Picture Multi-Previews

Then, ensure you display both frontPreviewOutput and backPreviewOutput in separate <NativePreviewView /> views:

function App() {
  const frontPreviewOutput = ...
  const backPreviewOutput = ...

  return (
    <View style={StyleSheet.absoluteFill}>
      <NativePreviewView
        style={{ flex: 1 }}
        previewOutput={frontPreviewOutput}
      />
      <NativePreviewView
        style={{ flex: 1 }}
        previewOutput={backPreviewOutput}
      />
    </View>
  )
}