-
Notifications
You must be signed in to change notification settings - Fork 0
useCamera
Saurav-TB-Pandey edited this page Aug 10, 2026
·
2 revisions
A comprehensive hook that handles the complete lifecycle of the browser's Camera API. It allows you to request permissions, stream the live video feed, capture high-quality picture snapshots, and even record video (with optional audio) directly into a Blob for immediate playback or uploading.
Requesting access to the camera and rendering a live preview.
import { useCamera } from "react-hook-lab";
function CameraPreview() {
const { status, videoRef, requestCamera, stopCamera } = useCamera();
if (status !== "granted") {
return <button onClick={requestCamera}>Enable Camera</button>;
}
return (
<div>
{/* The videoRef automatically pipes the MediaStream to this element */}
<video ref={videoRef} autoPlay playsInline muted />
<button onClick={stopCamera}>Turn Off Camera</button>
</div>
);
}Capturing a still image snapshot from the live video feed.
import { useCamera } from "react-hook-lab";
function PhotoBooth() {
const {
status, videoRef, requestCamera,
captureImage, imageUrl, clearCapturedImage
} = useCamera();
const handleCapture = async () => {
// Captures a high quality JPEG
await captureImage("image/jpeg", 0.95);
};
return (
<div>
{status !== "granted" ? (
<button onClick={requestCamera}>Start Camera</button>
) : (
<video ref={videoRef} autoPlay playsInline muted />
)}
{status === "granted" && <button onClick={handleCapture}>Take Photo</button>}
{imageUrl && (
<div className="preview-modal">
<h3>Your Photo</h3>
<img src={imageUrl} alt="Captured" />
<button onClick={clearCapturedImage}>Retake</button>
</div>
)}
</div>
);
}Recording a video. useCamera will automatically request microphone access if it needs to record sound along with the video!
import { useCamera } from "react-hook-lab";
function VideoRecorder() {
const {
status, videoRef, requestCamera,
isRecording, startRecording, stopRecording,
recordedVideoUrl, clearRecordedVideo
} = useCamera();
return (
<div>
{status !== "granted" && <button onClick={requestCamera}>Start</button>}
<video ref={videoRef} autoPlay playsInline muted />
{status === "granted" && !isRecording && (
<button onClick={startRecording}>Record Video</button>
)}
{isRecording && (
<button onClick={stopRecording} style={{ color: "red" }}>
Stop Recording
</button>
)}
{recordedVideoUrl && (
<div>
<h3>Playback</h3>
<video src={recordedVideoUrl} controls />
<button onClick={clearRecordedVideo}>Delete</button>
</div>
)}
</div>
);
}-
constraints(Optional)- Type:
MediaStreamConstraints - Default:
{ video: true } - Description: Configures the camera request (e.g.,
{ video: { facingMode: "environment" } }for mobile rear cameras).
- Type:
Returns an object of type UseCameraReturn containing:
-
videoRef(RefObject<HTMLVideoElement>): Attach this to a<video>element to view the live preview. -
stream(MediaStream | null): The raw hardware stream. -
status(CameraStatus): The current hardware state ("idle" | "unsupported" | "prompting" | "granted" | "denied" | "error"). -
error(string | null): A human-readable error message. -
isRecording(boolean): True if currently capturing video. -
isPreparingRecording(boolean): True while requesting microphone access to start recording. -
imageBlob(Blob | null): The binary data of the last captured snapshot. -
imageUrl(string | null): Ablob:URL for the captured image. -
recordedVideoBlob(Blob | null): The binary data of the final recorded video. -
recordedVideoUrl(string | null): Ablob:URL for the recorded video. -
requestCamera(() => Promise<void>): Initiates the browser permission prompt and camera startup. -
stopCamera(() => void): Completely shuts down the hardware. -
captureImage((type?: string, quality?: number) => Promise<Blob | null>): Takes a snapshot of the current video frame. -
startRecording(() => Promise<boolean>): Begins capturing video. Prompts for Microphone access if audio is needed. -
stopRecording(() => void): Stops capturing and generates the final video Blob. -
clearCapturedImage(() => void): Deletes the stored image and revokes the blob URL. -
clearRecordedVideo(() => void): Deletes the stored video and revokes the blob URL.
-
Live Preview:
requestCamerafetches theMediaStream. AuseEffectbinds this stream directly to thevideoRef.current.srcObject, auto-piping the video to the UI. -
Snapshot Capturing:
captureImageutilizes an invisible HTML5<canvas>. It writes the current frame of the<video>element onto the canvas usingdrawImage, and then converts it to a blob viacanvas.toBlob. -
Video Recording:
startRecordingchecks if the current stream has audio tracks. If not, it actively queriesnavigator.mediaDevices.getUserMedia({ audio: true })and merges the new audio tracks with the existing video tracks into a compositeMediaStream. This stream is fed toMediaRecorderto generate a WebM/MP4 file. -
Memory Management: Like
useMicrophone, this hook strictly terminates all hardware tracks (track.stop()) on unmount and proactively revokes allURL.createObjectURLreferences to prevent browser memory leaks.
Built with ❤️ by Saurav-TB-Pandey. | Report an Issue | NPM