react-native-vision-camera
Version:
VisionCamera is the fastest and most powerful Camera for react-native.
240 lines (239 loc) • 9.4 kB
TypeScript
import type { HybridObject } from 'react-native-nitro-modules';
import type { CameraController } from '../CameraController.nitro';
import type { ListenerSubscription } from '../common-types/ListenerSubscription';
import type { CameraSessionConfiguration } from './CameraSessionConfiguration';
import type { CameraSessionConnection } from './CameraSessionConnection';
export type InterruptionReason = 'video-device-not-available-in-background' | 'audio-device-in-use-by-another-client' | 'video-device-in-use-by-another-client' | 'video-device-not-available-with-multiple-foreground-apps' | 'video-device-not-available-due-to-system-pressure' | 'sensitive-content-mitigation-activated' | 'unknown';
/**
* Represents a Camera Session.
*
* A Camera Session can have {@linkcode CameraSessionConnection}s
* to stream from an input device ({@linkcode CameraDevice})
* to an output ({@linkcode CameraOutput}).
*
* It is recommended to configure the {@linkcode CameraSession}
* properly before starting it ({@linkcode start | start()}) to
* avoid reconfiguration hiccups.
*
* You can create and use a Camera Session via the
* {@linkcode useCamera | useCamera(...)} hook, or by
* using the imperative APIs directly, which gives you
* more control over individual properties like
* {@linkcode CameraOutputConfiguration.mirrorMode | mirrorMode}
* per output, or multi-cam {@linkcode CameraSession}s.
*
* @example
* Create a Camera Session using the hooks:
* ```ts
* const device = ...
* const photoOutput = ...
* const camera = useCamera({
* isActive: true,
* input: device,
* outputs: [photoOutput]
* })
* ```
* @example
* Create a single Camera Session using the imperative API:
* ```ts
* const session = await VisionCamera.createCameraSession(false)
* const [controller] = await session.configure([
* {
* input: device,
* outputs: [
* { output: previewOutput, mirrorMode: 'auto' },
* { output: photoOutput, mirrorMode: 'auto' },
* ],
* constraints: []
* }
* ])
* await session.start()
* ```
* @example
* Create a multi-cam Camera Session to stream from both the front-,
* 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
* {
* 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()
* }
* ```
*/
export interface CameraSession extends HybridObject<{
ios: 'swift';
android: 'kotlin';
}> {
/**
* Gets whether this {@linkcode CameraSession} is currently
* running, or not.
*/
readonly isRunning: boolean;
/**
* Configures the {@linkcode CameraSession} with the given
* {@linkcode connections}, and returns one {@linkcode CameraController}
* per {@linkcode CameraSessionConnection}.
*
* One {@linkcode CameraSessionConnection} defines a connection
* 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.
*
* @note Some supported combinations can contain a single virtual
* {@linkcode CameraDevice}, such as an iOS Dual- or Triple-Camera. Pass the
* returned devices directly to {@linkcode configure | configure(...)} instead
* of expanding virtual devices via {@linkcode CameraDevice.physicalDevices}.
*
* @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)}),
* you can add multiple {@linkcode CameraSessionConnection}s.
* @param config Configures session-wide configuration,
* such as {@linkcode CameraSessionConfiguration.allowBackgroundAudioPlayback}.
*
* @returns One {@linkcode CameraController} per {@linkcode CameraSessionConnection}.
*
* @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:
* ```ts
* const session = ...
* const device = ...
* const [controller] = await session.configure([
* {
* input: device,
* outputs: [
* { output: previewOutput, mirrorMode: 'auto' },
* { output: photoOutput, mirrorMode: 'auto' },
* ],
* constraints: []
* }
* ])
* ```
* @example
* Configuring constraints (e.g. 60 FPS):
* ```ts
* const session = ...
* const device = ...
* const [controller] = await session.configure([
* {
* input: device,
* outputs: [
* { output: previewOutput, mirrorMode: 'auto' },
* { output: photoOutput, mirrorMode: 'auto' },
* ],
* constraints: [
* { fps: 60 }
* ]
* }
* ])
* await session.start()
* ```
* @example
* 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
* {
* 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()
* }
* ```
*/
configure(connections: CameraSessionConnection[], config?: CameraSessionConfiguration): Promise<CameraController[]>;
/**
* Starts the {@linkcode CameraSession}.
*
* To avoid any runtime hiccups, it's good practice
* to configure everything via {@linkcode configure | configure(...)}
* before starting the {@linkcode CameraSession}.
*/
start(): Promise<void>;
/**
* Stops the {@linkcode CameraSession}.
*/
stop(): Promise<void>;
/**
* Adds a listener to when the {@linkcode CameraSession}
* started running.
*/
addOnStartedListener(onStarted: () => void): ListenerSubscription;
/**
* Adds a listener to when the {@linkcode CameraSession}
* stopped running.
*/
addOnStoppedListener(onStopped: () => void): ListenerSubscription;
/**
* Adds a listener to when the {@linkcode CameraSession}
* encountered an error.
*/
addOnErrorListener(onError: (error: Error) => void): ListenerSubscription;
/**
* Adds a listener to when the {@linkcode CameraSession}
* was interrupted, for example when the phone overheated,
* or the user received a FaceTime call.
*/
addOnInterruptionStartedListener(onInterruptionStarted: (reason: InterruptionReason) => void): ListenerSubscription;
/**
* Adds a listener to when a {@linkcode CameraSession}
* interruption has ended and the Camera continues
* to run again.
*/
addOnInterruptionEndedListener(onInterruptionEnded: () => void): ListenerSubscription;
}