Skip to main content

Camera Formats

What are camera formats?

Each camera device (see Camera Devices) provides a number of capture formats that have different specifications. There are formats specifically designed for high-resolution photo capture, which have very high photo output quality but in return only support frame-rates of up to 30 FPS. On the other side, there might be formats that are designed for slow-motion video capture which have frame-rates up to 240 FPS.

What if I don't want to choose a format?

If you don't want to specify the best format for your camera device, you don't have to. The Camera automatically chooses the best matching format for the current camera device. This is why the Camera's format property is optional.

If you don't want to do a lot of filtering, but still want to let the camera know what your intentions are, you can use the Camera's preset property.

For example, use the 'medium' preset if you want to create a video-chat application that shouldn't excessively use mobile data:

function App() {
const devices = useCameraDevices()
const device = devices.back

if (device == null) return <LoadingView />
return (
<Camera
style={StyleSheet.absoluteFill}
device={device}
preset="medium"
/>
)
}
note

See the CameraPreset.ts type for more information about presets

warning

You cannot set preset and format at the same time; if format is set, preset must be undefined and vice versa!

What you need to know about cameras

To understand a bit more about camera formats, you first need to understand a few "general camera basics":

  • Each camera device is built differently, e.g. Telephoto devices often don't provide frame-rates as high as Wide-Angle devices.
  • Formats are designed for specific use-cases, so formats with high resolution photo output don't support frame-rates as high as formats with lower resolution.
  • Different formats provide different field-of-views (FOV), maximum zoom factors, color spaces (iOS only), resolutions, frame rate ranges, and systems to assist with capture (auto-focus systems, video stabilization systems, ...)

Get started

Each application has different needs, so the format filtering is up to you.

To get all available formats, simply use the CameraDevice's .formats property. See how to get a camera device in the Camera Devices guide.

note

You can also manually get all camera devices and decide which device to use based on the available formats.

This example shows how you would pick the format with the highest frame rate:

function getMaxFps(format: CameraDeviceFormat): number {
return format.frameRateRanges.reduce((prev, curr) => {
if (curr.maxFrameRate > prev) return curr.maxFrameRate
else return prev
}, 0)
}

function App() {
const devices = useCameraDevices('wide-angle-camera')
const device = devices.back

const format = useMemo(() => {
return device?.formats.reduce((prev, curr) => {
if (prev == null) return curr
if (getMaxFps(curr) > getMaxFps(prev)) return curr
else return prev
}, undefined)
}, [device?.formats])

if (device == null) return <LoadingView />
return (
<Camera
style={StyleSheet.absoluteFill}
device={device}
format={format}
/>
)
}

Note that you don't want to simply pick the highest frame rate, as those formats often have incredibly low resolutions. You want to find a balance between high frame rate and high resolution, so instead you might want to use the .sort function.

Sort

To sort your formats, create a custom comparator function which will be used as the .sort function's argument. The custom comparator then compares formats, preferring ones with higher frame rate AND higher resolution.

Implement this however you want, I personally use a "point-based system":

export const sortFormatsByResolution = (left: CameraDeviceFormat, right: CameraDeviceFormat): number => {
// in this case, points aren't "normalized" (e.g. higher resolution = 1 point, lower resolution = -1 points)
let leftPoints = left.photoHeight * left.photoWidth
let rightPoints = right.photoHeight * right.photoWidth

// we also care about video dimensions, not only photo.
leftPoints += left.videoWidth * left.videoHeight
rightPoints += right.videoWidth * right.videoHeight

// you can also add points for FPS, etc

return rightPoints - leftPoints
}

// and then call it:
const formats = useMemo(() => device?.formats.sort(sortFormatsByResolution), [device?.formats])
caution

Be careful that you don't filter out a lot of formats since you might end up having no format to use at all. (Remember; not all devices support e.g. 240 FPS.) Always carefully sort instead of filter, and pick the best available format - that way you are guaranteed to have a format available, even if your desired specifications aren't fully met.

Props

The Camera View provides a few props that depend on the specified format. For example, you can only set the fps prop to a value that is supported by the current format. So if you have a format that supports 240 FPS, you can set the fps to 240:

function App() {
// ...
return (
<Camera
style={StyleSheet.absoluteFill}
device={device}
format={format}
fps={240}
/>
)
}
note

You should always verify that the format supports the desired FPS, and fall back to undefined (or a value that is supported, like 30) if it doesn't.

Other props that depend on the format:

  • fps: Specifies the frame rate to use
  • hdr: Enables HDR photo or video capture and preview
  • lowLightBoost: Enables a night-mode/low-light-boost for photo or video capture and preview
  • colorSpace: Uses the specified color-space for photo or video capture and preview (iOS only since Android only uses YUV)
  • videoStabilizationMode: Specifies the video stabilization mode to use for this camera device

🚀 Next section: Taking Photos/Recording Videos