Skip to content

useCamera

Saurav-TB-Pandey edited this page Aug 10, 2026 · 2 revisions

useCamera

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.

Usage Examples

Basic

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>
  );
}

Common

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>
  );
}

Advanced

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>
  );
}

API Reference

Parameters

  • constraints (Optional)
    • Type: MediaStreamConstraints
    • Default: { video: true }
    • Description: Configures the camera request (e.g., { video: { facingMode: "environment" } } for mobile rear cameras).

Return Object

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): A blob: URL for the captured image.
  • recordedVideoBlob (Blob | null): The binary data of the final recorded video.
  • recordedVideoUrl (string | null): A blob: 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.

Core Working

  1. Live Preview: requestCamera fetches the MediaStream. A useEffect binds this stream directly to the videoRef.current.srcObject, auto-piping the video to the UI.
  2. Snapshot Capturing: captureImage utilizes an invisible HTML5 <canvas>. It writes the current frame of the <video> element onto the canvas using drawImage, and then converts it to a blob via canvas.toBlob.
  3. Video Recording: startRecording checks if the current stream has audio tracks. If not, it actively queries navigator.mediaDevices.getUserMedia({ audio: true }) and merges the new audio tracks with the existing video tracks into a composite MediaStream. This stream is fed to MediaRecorder to generate a WebM/MP4 file.
  4. Memory Management: Like useMicrophone, this hook strictly terminates all hardware tracks (track.stop()) on unmount and proactively revokes all URL.createObjectURL references to prevent browser memory leaks.

Clone this wiki locally