Recording Videos
Camera Functions​
The Camera provides certain functions which are available through a ref object:
function App() {
const camera = useRef<Camera>(null)
// ...
return (
<Camera
ref={camera}
{...cameraProps}
/>
)
}
To use these functions, you need to wait until the onInitialized
event has been fired.
Recording Videos​
To start a video recording you first have to enable video capture:
<Camera
{...props}
video={true}
audio={true} // <-- optional
/>
Then, simply use the Camera's startRecording(...)
function:
camera.current.startRecording({
onRecordingFinished: (video) => console.log(video),
onRecordingError: (error) => console.error(error)
})
You can customize capture options such as video codec, file type, enable flash and more using the RecordVideoOptions
parameter.
For any error that occured while recording the video, the onRecordingError
callback will be invoked with a CaptureError
and the recording is therefore cancelled.
To stop the video recording, you can call stopRecording(...)
:
await camera.current.stopRecording()
Once a recording has been stopped, the onRecordingFinished
callback passed to the startRecording(...)
function will be invoked with a VideoFile
which you can then use to display in a <Video>
component, uploaded to a backend, or saved to the Camera Roll using react-native-cameraroll.
Pause/Resume​
To pause/resume the recordings, you can use pauseRecording()
and resumeRecording()
:
await camera.current.pauseRecording()
...
await camera.current.resumeRecording()
Cancel​
To cancel the recording, you can use cancelRecording()
, which will stop the recording, delete the temporary video file and call the startRecording
's onRecordingError
callback with a capture/recording-canceled
error.
await camera.current.cancelRecording()
Flash​
The startRecording(...)
function can be configured to enable the flash while recording, which natively just enables the torch
under the hood:
camera.current.startRecording({
flash: 'on',
...
})
Note that flash is only available on camera devices where hasTorch
is true
; for example most front cameras don't have a torch.
Video Codec​
By default, videos are recorded in the H.264 video codec which is a widely adopted video codec.
VisionCamera also supports H.265 (HEVC), which is much more efficient in encoding performance and can be up to 50% smaller in file size. If you can handle H.265 on your backend, configure the video recorder to encode in H.265:
camera.current.startRecording({
...props,
videoCodec: 'h265'
})
If the device does not support h265
, VisionCamera will automatically fall-back to a supported codec like h264
instead.
Video Bit Rate​
Videos are recorded with a target bit-rate, which the encoder aims to match as closely as possible. A lower bit-rate means less quality (and less file size), a higher bit-rate means higher quality (and larger file size) since it can assign more bits to moving pixels.
To simply record videos with higher quality, use a videoBitRate
of 'high'
, which effectively increases the bit-rate by 20%:
<Camera {...props} videoBitRate="high" />
To use a lower bit-rate for lower quality and lower file-size, use a videoBitRate
of 'low'
, which effectively decreases the bit-rate by 20%:
<Camera {...props} videoBitRate="low" />
Custom Bit Rate​
If you want to use a custom bit-rate, you first need to understand how bit-rate is calculated.
The bit-rate is a product of multiple factors such as resolution, FPS, pixel-format (HDR or non HDR), and video codec. As a good starting point, those are the recommended base bit-rates for their respective resolutions:
- 480p: 2 Mbps
- 720p: 5 Mbps
- 1080p: 10 Mbps
- 4K: 30 Mbps
- 8K: 100 Mbps
These bit-rates assume a frame rate of 30 FPS, a non-HDR pixel-format, and a H.264 video codec.
To calculate your target bit-rate, you can use this formula:
let bitRate = baseBitRate
bitRate = bitRate / 30 * fps // FPS
if (videoHdr === true) bitRate *= 1.2 // 10-Bit Video HDR
if (codec === 'h265') bitRate *= 0.8 // H.265
bitRate *= yourCustomFactor // e.g. 0.5x for half the bit-rate
And then pass it to the <Camera>
component (in Mbps):
<Camera {...props} videoBitRate={bitRate} />
Video Frame Rate (FPS)​
The resulting video will be recorded at the frame rate provided to the fps
prop.
<Camera {...props} fps={60} />
See FPS for more information.
Path​
It is possible to specify a custom path used to save the temp files. By default it saves this to the temp folder. If you are using expo, it is not possible to delete and manipulate the files saved in the temp folder, therefore you can provide one using the expo file system:
import * as FileSystem from "expo-file-system";
...
// Set up the temp directory (you can skip this if you want to just use ${FileSystem.documentDirectory})
useEffect(() => {
const setupTempDirectory = async () => {
const tempDir = `${FileSystem.documentDirectory}temp_videos/`; // use either documentDirectory or cacheDirectory
try {
const dirInfo = await FileSystem.getInfoAsync(tempDir);
if (!dirInfo.exists) {
await FileSystem.makeDirectoryAsync(tempDir, {
intermediates: true,
});
}
} catch (error) {
console.error("Error creating temp directory:", error);
}
};
setupTempDirectory();
}, []);
// Specify this new path when calling startRecording
camera.current.startRecording({
...
path: `${FileSystem.documentDirectory}temp_videos/`,
...
})
Saving the Video to the Camera Roll​
Since the Video is stored as a temporary file, you need save it to the Camera Roll to permanentely store it. You can use react-native-cameraroll for this:
camera.current.startRecording({
...props,
onRecordingFinished: (video) => {
const path = video.path
await CameraRoll.save(`file://${path}`, {
type: 'video',
})
},
})