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.
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.
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])
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}
/>
)
}
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 usehdr
: Enables HDR photo or video capture and previewlowLightBoost
: Enables a night-mode/low-light-boost for photo or video capture and previewcolorSpace
: Uses the specified color-space for photo or video capture and preview (iOS only since Android only usesYUV
)videoStabilizationMode
: Specifies the video stabilization mode to use for this camera device