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, video bit-rate, 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 stopRecording(...)
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()
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'
})
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.current.startRecording({
...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.current.startRecording({
...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 startRecording(...)
function (in Mbps):
camera.current.startRecording({
...props,
videoBitRate: bitRate // Mbps
})
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',
})
},
})