diff --git a/docs/content/docs/multi-camera.mdx b/docs/content/docs/multi-camera.mdx index e0b2abf273..891037c7ac 100644 --- a/docs/content/docs/multi-camera.mdx +++ b/docs/content/docs/multi-camera.mdx @@ -5,7 +5,7 @@ description: Using multiple Camera Devices in a single Camera Session import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -A [`CameraSession`](/api/react-native-vision-camera/hybrid-objects/CameraSession) allows attaching multiple connections to stream from multiple [`CameraDevice`](/api/react-native-vision-camera/hybrid-objects/CameraDevice)s at the same time (e.g. Picture-in-Picture mode via front + back Camera) - if the system supports it. +A [`CameraSession`](/api/react-native-vision-camera/hybrid-objects/CameraSession) allows attaching multiple connections to stream from multiple [`CameraDevice`](/api/react-native-vision-camera/hybrid-objects/CameraDevice)s at the same time - if the system supports it. ### Creating a Multi-Camera Session @@ -19,35 +19,14 @@ if (VisionCamera.supportsMultiCamSessions) { ### Using multiple Connections -Due to hardware constraints, not every [`CameraDevice`](/api/react-native-vision-camera/hybrid-objects/CameraDevice) can be paired with every other [`CameraDevice`](/api/react-native-vision-camera/hybrid-objects/CameraDevice) - therefore VisionCamera exposes a fixed array of supported combinations via [`CameraDeviceFactory.supportedMultiCamDeviceCombinations`](/api/react-native-vision-camera/hybrid-objects/CameraDeviceFactory#supportedmulticamdevicecombinations) upfront: +With a multi-cam [`CameraSession`](/api/react-native-vision-camera/hybrid-objects/CameraSession), you can now attach multiple [`CameraSessionConnection`](/api/react-native-vision-camera/interfaces/CameraSessionConnection)s - for example to stream and capture from the Front- and Back-Camera at the same time, attach both devices: ```ts -if (!VisionCamera.supportsMultiCamSessions) - return - -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') -``` - -Then, knowing `frontDevice` and `backDevice` can be used simultaneously in a Multi-Cam session, create the [`CameraSession`](/api/react-native-vision-camera/hybrid-objects/CameraSession), and attach the [`CameraSessionConnection`](/api/react-native-vision-camera/interfaces/CameraSessionConnection)s: - -```ts -const session = await VisionCamera.createCameraSession(true) -const frontPreviewOutput = VisionCamera.createPreviewOutput() -const frontPhotoOutput = VisionCamera.createPhotoOutput({}) -const backPreviewOutput = VisionCamera.createPreviewOutput() -const backPhotoOutput = VisionCamera.createPhotoOutput({}) +const session = ... +const frontDevice = useCameraDevice('front') +const backDevice = useCameraDevice('back') +const frontPreview = usePreviewOutput() +const backPreview = usePreviewOutput() const [frontController, backController] = await session.configure([ // Front Camera @@ -72,26 +51,6 @@ const [frontController, backController] = await session.configure([ await session.start() ``` -Each returned [`CameraController`](/api/react-native-vision-camera/hybrid-objects/CameraController) correlates to the connection at that index - e.g. `frontController` allows zooming/exposure/focus the `frontDevice`, and vice-versa. - -Then, ensure you display both `frontPreviewOutput` and `backPreviewOutput` in separate [``](/api/react-native-vision-camera/views/NativePreviewView) views: - -```tsx -function App() { - const frontPreviewOutput = ... - const backPreviewOutput = ... +Then, ensure you display both `frontPreview` and `backPreview` in separate [``](/api/react-native-vision-camera/views/NativePreviewView) views. - return ( - - - - - ) -} -``` +Each returned [`CameraController`](/api/react-native-vision-camera/hybrid-objects/CameraController) correlates to the connection at that index. diff --git a/packages/react-native-vision-camera/android/src/main/java/com/margelo/nitro/camera/HybridCameraDeviceFactory.kt b/packages/react-native-vision-camera/android/src/main/java/com/margelo/nitro/camera/HybridCameraDeviceFactory.kt index 5e700b83ac..ce693d37ce 100644 --- a/packages/react-native-vision-camera/android/src/main/java/com/margelo/nitro/camera/HybridCameraDeviceFactory.kt +++ b/packages/react-native-vision-camera/android/src/main/java/com/margelo/nitro/camera/HybridCameraDeviceFactory.kt @@ -38,13 +38,6 @@ class HybridCameraDeviceFactory( override val cameraDevices: Array get() = cameraProvider.availableCameraInfos.mapToArray { HybridCameraDevice(it) } - override val supportedMultiCamDeviceCombinations: Array> - get() { - return cameraProvider.availableConcurrentCameraInfos.mapToArray { devices -> - return@mapToArray devices.mapToArray { HybridCameraDevice(it) } - } - } - override var userPreferredCamera: HybridCameraDeviceSpec? get() { val preferredCameraId = diff --git a/packages/react-native-vision-camera/ios/Hybrid Objects/HybridCameraDeviceFactory.swift b/packages/react-native-vision-camera/ios/Hybrid Objects/HybridCameraDeviceFactory.swift index 42ef2f8014..37af6deab6 100644 --- a/packages/react-native-vision-camera/ios/Hybrid Objects/HybridCameraDeviceFactory.swift +++ b/packages/react-native-vision-camera/ios/Hybrid Objects/HybridCameraDeviceFactory.swift @@ -9,6 +9,11 @@ import Foundation import NitroModules class HybridCameraDeviceFactory: HybridCameraDeviceFactorySpec { + let discoverySession: AVCaptureDevice.DiscoverySession + var cameraDevices: [any HybridCameraDeviceSpec] { + return discoverySession.devices.map { HybridCameraDevice(device: $0) } + } + override init() { self.discoverySession = AVCaptureDevice.DiscoverySession( deviceTypes: AVCaptureDevice.DeviceType.all, @@ -17,17 +22,6 @@ class HybridCameraDeviceFactory: HybridCameraDeviceFactorySpec { super.init() } - let discoverySession: AVCaptureDevice.DiscoverySession - var cameraDevices: [any HybridCameraDeviceSpec] { - return discoverySession.devices.map { HybridCameraDevice(device: $0) } - } - - var supportedMultiCamDeviceCombinations: [[any HybridCameraDeviceSpec]] { - return discoverySession.supportedMultiCamDeviceSets.map { devices in - return devices.map { HybridCameraDevice(device: $0) } - } - } - var userPreferredCamera: (any HybridCameraDeviceSpec)? { get { guard #available(iOS 17.0, *) else { @@ -42,7 +36,7 @@ class HybridCameraDeviceFactory: HybridCameraDeviceFactorySpec { guard #available(iOS 17.0, *) else { return } - guard let hybridDevice = newValue as? any NativeCameraDevice else { + guard let hybridDevice = newValue as? HybridCameraDevice else { return } AVCaptureDevice.userPreferredCamera = hybridDevice.device diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/c++/JHybridCameraDeviceFactorySpec.cpp b/packages/react-native-vision-camera/nitrogen/generated/android/c++/JHybridCameraDeviceFactorySpec.cpp index f0256d7dd8..3f96d33a4d 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/c++/JHybridCameraDeviceFactorySpec.cpp +++ b/packages/react-native-vision-camera/nitrogen/generated/android/c++/JHybridCameraDeviceFactorySpec.cpp @@ -88,29 +88,6 @@ namespace margelo::nitro::camera { static const auto method = _javaPart->javaClassStatic()->getMethod /* userPreferredCamera */)>("setUserPreferredCamera"); method(_javaPart, userPreferredCamera.has_value() ? std::dynamic_pointer_cast(userPreferredCamera.value())->getJavaPart() : nullptr); } - std::vector>> JHybridCameraDeviceFactorySpec::getSupportedMultiCamDeviceCombinations() { - static const auto method = _javaPart->javaClassStatic()->getMethod>>()>("getSupportedMultiCamDeviceCombinations"); - auto __result = method(_javaPart); - return [&]() { - size_t __size = __result->size(); - std::vector>> __vector; - __vector.reserve(__size); - for (size_t __i = 0; __i < __size; __i++) { - auto __element = __result->getElement(__i); - __vector.push_back([&]() { - size_t __size = __element->size(); - std::vector> __vector; - __vector.reserve(__size); - for (size_t __i = 0; __i < __size; __i++) { - auto __element = __element->getElement(__i); - __vector.push_back(__element->getJHybridCameraDeviceSpec()); - } - return __vector; - }()); - } - return __vector; - }(); - } // Methods ListenerSubscription JHybridCameraDeviceFactorySpec::addOnCameraDevicesChangedListener(const std::function>& /* newDevices */)>& listener) { diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/c++/JHybridCameraDeviceFactorySpec.hpp b/packages/react-native-vision-camera/nitrogen/generated/android/c++/JHybridCameraDeviceFactorySpec.hpp index 19a60bea95..df9b7b23c1 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/c++/JHybridCameraDeviceFactorySpec.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/android/c++/JHybridCameraDeviceFactorySpec.hpp @@ -53,7 +53,6 @@ namespace margelo::nitro::camera { std::vector> getCameraDevices() override; std::optional> getUserPreferredCamera() override; void setUserPreferredCamera(const std::optional>& userPreferredCamera) override; - std::vector>> getSupportedMultiCamDeviceCombinations() override; public: // Methods diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/HybridCameraDeviceFactorySpec.kt b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/HybridCameraDeviceFactorySpec.kt index b41306e76c..f610aeb748 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/HybridCameraDeviceFactorySpec.kt +++ b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/HybridCameraDeviceFactorySpec.kt @@ -35,10 +35,6 @@ abstract class HybridCameraDeviceFactorySpec: HybridObject() { @set:DoNotStrip @set:Keep abstract var userPreferredCamera: HybridCameraDeviceSpec? - - @get:DoNotStrip - @get:Keep - abstract val supportedMultiCamDeviceCombinations: Array> // Methods abstract fun addOnCameraDevicesChangedListener(listener: (newDevices: Array) -> Unit): ListenerSubscription diff --git a/packages/react-native-vision-camera/nitrogen/generated/ios/VisionCamera-Swift-Cxx-Bridge.hpp b/packages/react-native-vision-camera/nitrogen/generated/ios/VisionCamera-Swift-Cxx-Bridge.hpp index 5abcd00279..5bde895e9d 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/ios/VisionCamera-Swift-Cxx-Bridge.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/ios/VisionCamera-Swift-Cxx-Bridge.hpp @@ -1426,17 +1426,6 @@ namespace margelo::nitro::camera::bridge::swift { return Result::withError(error); } - // pragma MARK: std::vector>> - /** - * Specialized version of `std::vector>>`. - */ - using std__vector_std__vector_std__shared_ptr_HybridCameraDeviceSpec___ = std::vector>>; - inline std::vector>> create_std__vector_std__vector_std__shared_ptr_HybridCameraDeviceSpec___(size_t size) noexcept { - std::vector>> vector; - vector.reserve(size); - return vector; - } - // pragma MARK: std::function>& /* newDevices */)> /** * Specialized version of `std::function>&)>`. diff --git a/packages/react-native-vision-camera/nitrogen/generated/ios/c++/HybridCameraDeviceFactorySpecSwift.hpp b/packages/react-native-vision-camera/nitrogen/generated/ios/c++/HybridCameraDeviceFactorySpecSwift.hpp index f166161e87..a13436fca5 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/ios/c++/HybridCameraDeviceFactorySpecSwift.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/ios/c++/HybridCameraDeviceFactorySpecSwift.hpp @@ -89,10 +89,6 @@ namespace margelo::nitro::camera { inline void setUserPreferredCamera(const std::optional>& userPreferredCamera) noexcept override { _swiftPart.setUserPreferredCamera(userPreferredCamera); } - inline std::vector>> getSupportedMultiCamDeviceCombinations() noexcept override { - auto __result = _swiftPart.getSupportedMultiCamDeviceCombinations(); - return __result; - } public: // Methods diff --git a/packages/react-native-vision-camera/nitrogen/generated/ios/swift/HybridCameraDeviceFactorySpec.swift b/packages/react-native-vision-camera/nitrogen/generated/ios/swift/HybridCameraDeviceFactorySpec.swift index ce0ba0d904..62708a1149 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/ios/swift/HybridCameraDeviceFactorySpec.swift +++ b/packages/react-native-vision-camera/nitrogen/generated/ios/swift/HybridCameraDeviceFactorySpec.swift @@ -12,7 +12,6 @@ public protocol HybridCameraDeviceFactorySpec_protocol: HybridObject { // Properties var cameraDevices: [(any HybridCameraDeviceSpec)] { get } var userPreferredCamera: (any HybridCameraDeviceSpec)? { get set } - var supportedMultiCamDeviceCombinations: [[(any HybridCameraDeviceSpec)]] { get } // Methods func addOnCameraDevicesChangedListener(listener: @escaping (_ newDevices: [(any HybridCameraDeviceSpec)]) -> Void) throws -> ListenerSubscription diff --git a/packages/react-native-vision-camera/nitrogen/generated/ios/swift/HybridCameraDeviceFactorySpec_cxx.swift b/packages/react-native-vision-camera/nitrogen/generated/ios/swift/HybridCameraDeviceFactorySpec_cxx.swift index ae6fb283ad..658132f915 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/ios/swift/HybridCameraDeviceFactorySpec_cxx.swift +++ b/packages/react-native-vision-camera/nitrogen/generated/ios/swift/HybridCameraDeviceFactorySpec_cxx.swift @@ -167,28 +167,6 @@ open class HybridCameraDeviceFactorySpec_cxx { }() } } - - public final var supportedMultiCamDeviceCombinations: bridge.std__vector_std__vector_std__shared_ptr_HybridCameraDeviceSpec___ { - @inline(__always) - get { - return { () -> bridge.std__vector_std__vector_std__shared_ptr_HybridCameraDeviceSpec___ in - var __vector = bridge.create_std__vector_std__vector_std__shared_ptr_HybridCameraDeviceSpec___(self.__implementation.supportedMultiCamDeviceCombinations.count) - for __item in self.__implementation.supportedMultiCamDeviceCombinations { - __vector.push_back({ () -> bridge.std__vector_std__shared_ptr_HybridCameraDeviceSpec__ in - var __vector = bridge.create_std__vector_std__shared_ptr_HybridCameraDeviceSpec__(__item.count) - for __item in __item { - __vector.push_back({ () -> bridge.std__shared_ptr_HybridCameraDeviceSpec_ in - let __cxxWrapped = __item.getCxxWrapper() - return __cxxWrapped.getCxxPart() - }()) - } - return __vector - }()) - } - return __vector - }() - } - } // Methods @inline(__always) diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/HybridCameraDeviceFactorySpec.cpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/HybridCameraDeviceFactorySpec.cpp index f0435f7356..d50c1b5a4f 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/HybridCameraDeviceFactorySpec.cpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/HybridCameraDeviceFactorySpec.cpp @@ -17,7 +17,6 @@ namespace margelo::nitro::camera { prototype.registerHybridGetter("cameraDevices", &HybridCameraDeviceFactorySpec::getCameraDevices); prototype.registerHybridGetter("userPreferredCamera", &HybridCameraDeviceFactorySpec::getUserPreferredCamera); prototype.registerHybridSetter("userPreferredCamera", &HybridCameraDeviceFactorySpec::setUserPreferredCamera); - prototype.registerHybridGetter("supportedMultiCamDeviceCombinations", &HybridCameraDeviceFactorySpec::getSupportedMultiCamDeviceCombinations); prototype.registerHybridMethod("addOnCameraDevicesChangedListener", &HybridCameraDeviceFactorySpec::addOnCameraDevicesChangedListener); prototype.registerHybridMethod("getCameraForId", &HybridCameraDeviceFactorySpec::getCameraForId); prototype.registerHybridMethod("getSupportedExtensions", &HybridCameraDeviceFactorySpec::getSupportedExtensions); diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/HybridCameraDeviceFactorySpec.hpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/HybridCameraDeviceFactorySpec.hpp index cde15be396..823a998870 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/HybridCameraDeviceFactorySpec.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/HybridCameraDeviceFactorySpec.hpp @@ -63,7 +63,6 @@ namespace margelo::nitro::camera { virtual std::vector> getCameraDevices() = 0; virtual std::optional> getUserPreferredCamera() = 0; virtual void setUserPreferredCamera(const std::optional>& userPreferredCamera) = 0; - virtual std::vector>> getSupportedMultiCamDeviceCombinations() = 0; public: // Methods diff --git a/packages/react-native-vision-camera/src/specs/inputs/CameraDeviceFactory.nitro.ts b/packages/react-native-vision-camera/src/specs/inputs/CameraDeviceFactory.nitro.ts index 6d04537536..0a6f3c0852 100644 --- a/packages/react-native-vision-camera/src/specs/inputs/CameraDeviceFactory.nitro.ts +++ b/packages/react-native-vision-camera/src/specs/inputs/CameraDeviceFactory.nitro.ts @@ -1,5 +1,4 @@ import type { HybridObject } from 'react-native-nitro-modules' -import type { CameraFactory } from '../CameraFactory.nitro' import type { CameraPosition } from '../common-types/CameraPosition' import type { ListenerSubscription } from '../common-types/ListenerSubscription' import type { CameraSession } from '../session/CameraSession.nitro' @@ -13,12 +12,8 @@ import type { CameraExtension } from './CameraExtension.nitro' export interface CameraDeviceFactory extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> { /** - * Get a list of all {@linkcode CameraDevice}s on this platform. - * - * This list may change as {@linkcode CameraDevice}s get plugged in/out (e.g. - * {@linkcode CameraPosition | 'external'} Cameras via USB/UVC), devices - * become available/unavailable (e.g. continuity Cameras), or Camera positions - * change (e.g. on foldable phones). + * Get a list of all devices. + * This list may change as camera devices get plugged in/out. */ readonly cameraDevices: CameraDevice[] /** @@ -27,64 +22,6 @@ export interface CameraDeviceFactory */ userPreferredCamera?: CameraDevice - /** - * A list of all {@linkcode CameraDevice} combinations that are supported - * in Multi-Cam {@linkcode CameraSession}s. - * - * This list always contains a subset of {@linkcode cameraDevices}, often - * less. - * - * @discussion - * For example, on many platforms only a {@linkcode CameraPosition | 'front'} - * and a {@linkcode CameraPosition | 'back'} {@linkcode CameraDevice} are - * supported to be used in a Multi-Cam {@linkcode CameraSession} - in this case, - * the returned 2D Array looks something like this: - * ``` - * [ - * [{ position: 'back', ... }, { position: 'front', ... }] - * ] - * ``` - * Two {@linkcode CameraPosition | 'back'}-, or two {@linkcode CameraPosition | 'front'} - * {@linkcode CameraDevice}s are often not supported together in a Multi-Cam - * {@linkcode CameraSession}. - * - * When creating a Multi-Cam {@linkcode CameraSession}, you must ensure - * that you are using Device combinations that are actually supported - * on the platform, otherwise the session might fail to configure. - * - * @discussion - * If the platform does not support Multi-Cam {@linkcode CameraSession}s, - * an empty array (`[]`) will be returned. - * - * - * @example - * ```ts - * if (VisionCamera.supportsMultiCamSessions) { - * const deviceFactory = await VisionCamera.createDeviceFactory() - * const deviceCombinations = deviceFactory.supportedMultiCamDeviceCombinations[0] - * if (deviceCombinations != null) { - * const connections = deviceCombinations.map((device) => { - * const previewOutput = VisionCamera.createPreviewOutput() - * return { - * input: device, - * outputs: [ - * { output: previewOutput, mirrorMode: 'auto' } - * ], - * constraints: [] - * } satisfies CameraSessionConnection - * }) - * - * const session = await VisionCamera.createCameraSession(true) - * const controllers = await session.configure(connections) - * await session.start() - * } - * } - * ``` - * - * @see {@linkcode CameraFactory.supportsMultiCamSessions} - */ - readonly supportedMultiCamDeviceCombinations: CameraDevice[][] - /** * Add a listener to be called whenever the * available {@linkcode cameraDevices} change, diff --git a/packages/react-native-vision-camera/src/specs/session/CameraSession.nitro.ts b/packages/react-native-vision-camera/src/specs/session/CameraSession.nitro.ts index 8390dac2b9..6b19b9ab29 100644 --- a/packages/react-native-vision-camera/src/specs/session/CameraSession.nitro.ts +++ b/packages/react-native-vision-camera/src/specs/session/CameraSession.nitro.ts @@ -68,10 +68,6 @@ export type InterruptionReason = * and back-Camera using the imperative API: * ```ts * if (VisionCamera.supportsMultiCamSessions) { - * const deviceFactory = await VisionCamera.createDeviceFactory() - * const deviceCombinations = deviceFactory.supportedMultiCamDeviceCombinations - * // ... get `frontDevice` and `backDevice` from one of - * // the combinations in `deviceCombinations`. * const session = await VisionCamera.createCameraSession(true) * const [frontController, backController] = await session.configure([ * // Front Camera @@ -114,12 +110,6 @@ export interface CameraSession * from one {@linkcode CameraDevice} (the _input_) to multiple * {@linkcode CameraOutput}s (the _outputs_). * - * @note In a Multi-Cam Camera Session, the given {@linkcode connections}' input devices - * must be supported to be used together in a Multi-Cam Camera Session, as not every - * {@linkcode CameraDevice} can be used with every other {@linkcode CameraDevice} - * simultaneously. See {@linkcode CameraDeviceFactory.supportedMultiCamDeviceCombinations} - * for a full list of supported combinations. - * * @param connections The list of connections from one _input_ to * multiple _outputs_. If this {@linkcode CameraSession} was created * as a multi-cam session (see {@linkcode CameraFactory.createCameraSession | createCameraSession(enableMultiCam)}), @@ -132,9 +122,6 @@ export interface CameraSession * @throws If Camera Permission has not been granted - see {@linkcode CameraFactory.cameraPermissionStatus} * @throws If multiple {@linkcode connections} are added, but the * {@linkcode CameraSession} was not created as a multi-cam session. - * @throws If hardware resources are being exhausted by too large connection graphs. - * @throws If this is a Multi-Cam session, but the connection inputs are not supported to - * be used together - see {@linkcode CameraDeviceFactory.supportedMultiCamDeviceCombinations} * * @example * Creating a simple Preview + Photo connection: @@ -175,10 +162,6 @@ export interface CameraSession * Creating a multi-cam session with front- and back Camera: * ```ts * if (VisionCamera.supportsMultiCamSessions) { - * const deviceFactory = await VisionCamera.createDeviceFactory() - * const deviceCombinations = deviceFactory.supportedMultiCamDeviceCombinations - * // ... get `frontDevice` and `backDevice` from one of - * // the combinations in `deviceCombinations`. * const session = await VisionCamera.createCameraSession(true) * const [frontController, backController] = await session.configure([ * // Front Camera