Formats
Understanding different Camera Formats
A CameraDevice can capture content in different resolutions, frame-rates (FPS), dynamic ranges (HDR), output formats (JPEG vs RAW), and more - a specific supported combination of these specifications is called a CameraFormat.
Accessing a Camera Device's available Formats
To get all available CameraFormats, use CameraDevice.formats:
const device = ...
for (const format of device.formats) {
const { width, height } = format.videoResolution
console.log(`${width} x ${height} @ ${format.maxFps} FPS`)
}
// Output:
// 4096 x 2160 @ 30 FPS
// 3840 x 2160 @ 60 FPS
// 1920 x 1080 @ 60 FPS
// 720 x 480 @ 60 FPSKey-facts of a Format
Video Resolution
Each CameraFormat specifies its native Video Resolution, which is the resolution that affects all video/streaming outputs:
CameraPreviewOutput: The Preview's size will be set toCameraFormat.videoResolutionor the Preview View's size, whichever is smaller.CameraVideoOutput: The Video Output will record in theCameraFormat.videoResolutionsize.CameraFrameOutput: The Frame Output will streamFrames in theCameraFormat.videoResolutionsize.
Video FPS
In addition to the Video's Resolution, a CameraFormat also specifies all available FPS ranges at this video resolution via CameraFormat.supportedFpsRanges, with the maximum available frame rate being CameraFormat.maxFps.
Similar to Video Resolution, FPS affects Video-, Frame-, and Preview-Outputs, whereas the Preview's refresh rate is limited to the screen's refresh rate.
Photo Resolution
Each CameraFormat specifies a list of available Photo Resolutions it can capture Photos in, with the highest available Photo Resolution accessible via CameraFormat.photoResolution. Photo Resolution affects the following outputs:
CameraPhotoOutput: The Photo Output will capturePhotos in theCameraFormat.photoResolutionsize.
Depth Formats
Each CameraFormat specifies a list of available Depth Formats via CameraFormat.depthDataFormats.
If the CameraDevice (or CameraFormat) does not support Depth, this will be an empty array ([]).
Depth Formats affect the following outputs:
CameraDepthFrameOutput: The Depth Output will streamDepthframes in the Depth-CameraFormat.videoResolutionsize.
Selecting a Format
You can select a Format using VisionCamera's format-filter APIs, which compare individual formats using the given FormatFilter and rank them by priority:
const device = ...
const format = useCameraFormat(device, [
{ videoResolution: 'max' },
{ fps: 60 }
])const device = ...
const format = getCameraFormat(device, [
{ videoResolution: 'max' },
{ fps: 60 }
])Here, videoResolution is listed before fps, so it has higher priority.
Assuming our Device has the following Formats:
- 4096 x 2160 @ 30 FPS
- 3840 x 2160 @ 60 FPS
- 1920 x 1080 @ 60 FPS
- 720 x 480 @ 60 FPS
...VisionCamera will select the first format (4096x2160 @ 30 FPS), since videoResolution was more important than fps in our filter. If 60 FPS is more important for your use-case, flip the order of your filters:
const device = ...
const format = useCameraFormat(device, [
{ fps: 60 },
{ videoResolution: 'max' }
])const device = ...
const format = getCameraFormat(device, [
{ fps: 60 },
{ videoResolution: 'max' }
])Now VisionCamera will select the second format (3840x2160 @ 60 FPS), since fps was more important than videoResolution, but since videoResolution is still a criterion for us, VisionCamera chooses the next best resolution.
See FormatFilter for a list of all available filters.
Using Format Templates
To quickly choose a suitable CameraFormat, use one of the predefined Templates - for example, for 60 FPS Video Recordings, you can choose Video60Fps:
const device = ...
const format = useCameraFormat(device, Templates.Video60Fps)const device = ...
const format = getCameraFormat(device, Templates.Video60Fps)Manually selecting a Format
If the useCameraFormat(...) hook does not grant you enough control, you may also manually select a Format via your own filtering/reducer;
const device = ...
const format = device.formats.find((f) => f.isHighestPhotoFormat)Selecting a Depth Format
You can select a Depth Format via the CameraFormat.depthDataFormats property:
const device = ...
const format = device.formats.find((f) => f.isHighestPhotoFormat)
const depthFormat = format.depthDataFormats[0]Using the Format
To use your CameraFormat, pass it to your Camera's Configuration:
const device = useCameraDevice("external")As an external Camera is plugged in or plugged out from the device, the useCameraDevice(...) hook automatically updates.
const devices = getAllCameraDevices()
let device = getCameraDevice(devices, "external")
addOnCameraDevicesChangedListener((d) => {
device = getCameraDevice(d, "external")
})As an external Camera is plugged in or plugged out from the device, the addOnCameraDevicesChangedListener(...) listener fires and you can call getCameraDevice(...) again to possibly detect new devices, or avoid using removed devices.
Using the Camera Device
To use your CameraDevice, pass it to your Camera's Configuration:
function App() {
const device = useCameraDevice('back')
const format = useCameraFormat(device, [
{ videoResolution: 'max' },
{ fps: 60 }
])
return (
<Camera
style={StyleSheet.absoluteFill}
isActive={true}
device={device}
format={format}
/>
)
}function App() {
const device = useCameraDevice('back')
const format = useCameraFormat(device, [
{ videoResolution: 'max' },
{ fps: 60 }
])
const camera = useCamera({
isActive: true,
device: device,
format: format
})
}const session = await HybridCameraFactory.createCameraSession(false)
const device = await getDefaultCameraDevice('back')
const format = getCameraDevice(device, [
{ videoResolution: 'max' },
{ fps: 60 }
])
await session.configure([
{
input: device,
config: {
format: format
}
}
], {})
await session.start()