Overview

The HeadlessVideoRecorder component is a React component that provides a simple and customizable interface for recording videos. It supports functionalities like previewing, recording, and downloading the recorded videos.

Installation

To use HeadlessVideoRecorder component , install it in your project:

npm install @locoworks/reusejs-react-video-recorder
or
yarn add @locoworks/reusejs-react-video-recorder

Importing

Import the HeadlessVideoRecorder component and necessary ref types:

import { HeadlessVideoRecorder, HeadlessVideoRecorderRef, VideoState } from "@locoworks/reusejs-react-video-recorder";

External Dependencies

The VideoRecorder uses the useTimer hook to achieve functionality of timer that we see for the video recording. Thus, make sure to install the @locoworks/reusejs-toolkit-react-hooks module.

npm install @locoworks/reusejs-toolkit-react-hooks
or
yarn add @locoworks/reusejs-toolkit-react-hooks

Types/Exported Components

  • HeadlessVideoRecorderProps :Various configurable properties to customize the behavior and appearance of the HeadlessVideoRecorder component. Refer to the component's source code for a complete list of props.
  • HeadlessVideoRecorderRef represents the reference interface for the HeadlessVideoRecorder component.
    • recording: Current state of the video recording ("inactive" | "preview" | "recording" | "recorded").
    • handleDownload: Function to trigger the download of the recorded video.
    • showPreview: Function to display the video preview.
interface HeadlessVideoRecorderRef {
	recording: VideoState;
	handleDownload: () => void;
	showPreview: () => void;
}
  • VideoState type is an enum that defines the possible states of the video recorder.
type VideoState = "inactive" | "preview" | "recording" | "recorded";

Props

  • autoStop (optional, default: true): Automatically stops recording after a specified time.
  • autoPreview (optional, default: true): Automatically shows a preview.
  • timeInMs (optional, default: 15000): Time in milliseconds for recording (only applicable if autoStop is true).
  • videoBitsPerSecond (optional, default: 2500000): The video encoding bit rate used to determine both the quality and size of the recorded video.
  • loader (optional, default: "Loading Preview..."): Loader component to display while the preview is loading.
  • handleStateChange (optional): Callback function triggered on state change.
  • customhandleDownload (optional): Custom function for handling the download of the recorded file.
  • customCountDown (optional): Custom component or function for displaying the countdown during recording.
  • customRetakeButton (optional): Custom component or function for the retake button.
  • customStopRecording (optional): Custom component or function for the stop recording button.
  • customStartRecording (optional): Custom component or function for the start recording button.
  • customDownloadButton (optional): Custom component or function for the download button.
  • recorderContainerClasses (optional): Classes or styles for the recorder container.
  • videoRecorderClasses (optional): Classes or styles for the video recorder element.
  • playbackVideoClasses (optional): Classes or styles for the playback video element.
  • footerContainerClasses (optional): Classes or styles for the footer container.
  • recordingFooterClasses (optional): Classes or styles for the recording footer.
  • previewFooterClasses (optional): Classes or styles for the preview footer.
  • recordedFooterClasses (optional): Classes or styles for the recorded footer.
  • startRecordingbuttonClasses (optional): Classes or styles for the start recording button.
  • retakeButtonClasses (optional): Classes or styles for the retake button.
  • downloadButtonClasses (optional): Classes or styles for the download button.
  • retakeLabel (optional, default: "Retake Video"): Label for the retake button.
  • downloadLabel (optional, default: "Download Video"): Label for the download button.
  • stopLabel (optional, default: "Stop Recording"): Label for the stop recording button.
  • startLabel (optional, default: "Start Recording"): Label for the start recording button.
  • mediaConstraints (optional): Media constraints to customize video and audio settings. The format of the mediaConstraints can be as follows:
    • video (optional): A boolean value indicating whether to include video in the media stream. It can also be an object of type MediaTrackConstraintSet to specify additional constraints for the video track.
    • audio (optional): A boolean value indicating whether to include audio in the media stream. It can also be an object of type MediaTrackConstraintSet to specify additional constraints for the audio track. Refer MediaTrackConstraints Documentation for details.
      interface MediaStreamConstraints {
        video?: boolean | MediaTrackConstraintSet;
        audio?: boolean | MediaTrackConstraintSet;
      }
      

Usage/Examples

Sample Code Fragment

import React, { useRef } from "react";
import {
	HeadlessVideoRecorder,
	HeadlessVideoRecorderRef,
} from "@locoworks/reusejs-react-video-recorder";

const Example = () => {
	const videoRecorderRef = useRef<HeadlessVideoRecorderRef>(null);
	const mediaConstraints = {
		video: {
			width: { ideal: 440, max: 440 },
			height: { ideal: 280, max: 280 },
		},
		audio: false,
	};

	const showPreview = () => {
		if (videoRecorderRef.current) {
			videoRecorderRef.current.showPreview();
		} else {
			console.error("videoRecorderRef is null");
		}
	};

	return (
		<div className="flex flex-col items-center justify-center py-10 mt-10 border rounded gap-x-3 bg-gray-50">
			<button className="p-2 bg-blue-300 border" onClick={showPreview}>
				Show Preview
			</button>
			<HeadlessVideoRecorder
				ref={videoRecorderRef}
				mediaConstraints={mediaConstraints}
				autoPreview={false}
			/>
		</div>
	);
};

export default Example;

AutoStop VideoRecorder

import React, { useRef, useState } from "react";
import {
	HeadlessVideoRecorder,
	HeadlessVideoRecorderRef,
	VideoState,
} from "@locoworks/reusejs-react-video-recorder";

const AutoStopVideoRecorder: React.FC = () => {
	const videoRecorderRef = useRef<HeadlessVideoRecorderRef>(null);
	const [recordingState, setRecordingState] = useState<VideoState>("inactive");

	const downloadHandler = () => {
		if (videoRecorderRef.current) {
			videoRecorderRef.current.handleDownload();
		} else {
			console.error("videoRecorderRef is null");
		}
	};

	const showPreview = () => {
		if (videoRecorderRef.current) {
			videoRecorderRef.current.showPreview();
		} else {
			console.error("videoRecorderRef is null");
		}
	};

	const RetakeButton = ({ onRetake }: any) => {
		return (
			<button className="p-2 bg-blue-200 border" onClick={onRetake}>
				Retake Recording
			</button>
		);
	};

	const CountDown = ({ count }: any) => {
		return (
			<div className="flex p-2 font-semibold border">
				00:{count < 10 ? `0${count}` : count}
			</div>
		);
	};

	const StartRecording = ({ onStart }: any) => {
		return (
			<button className="p-2 bg-blue-200 border" onClick={onStart}>
				Start Recording
			</button>
		);
	};
	return (
		<div className="flex flex-col items-center justify-center py-10 mt-10 border rounded gap-x-3 bg-gray-50">
			<HeadlessVideoRecorder
				ref={videoRecorderRef}
				autoPreview={false}
				autoStop={true}
				timeInMs={8000}
				customDownloadButton={() => <></>}
				handleStateChange={(state) => setRecordingState(state)}
				customRetakeButton={(onRetake: any) => (
					<RetakeButton onRetake={onRetake} />
				)}
				customCountDown={(count) => <CountDown count={count} />}
				customStartRecording={(onStart) => <StartRecording onStart={onStart} />}
			/>

			{recordingState == "inactive" && (
				<button className="p-2 bg-blue-300 border" onClick={showPreview}>
					Show Preview
				</button>
			)}
			{recordingState == "recorded" && (
				<button className="bg-blue-300 border-2 " onClick={downloadHandler}>
					Download Video in Parent
				</button>
			)}
		</div>
	);
};

export default AutoStopVideoRecorder;

ManualStop VideoRecorder

import React, { useRef, useState } from "react";
import {
	HeadlessVideoRecorder,
	HeadlessVideoRecorderRef,
	VideoState,
} from "@locoworks/reusejs-react-video-recorder";

const ManualStopVideoRecorder: React.FC = () => {
	const videoRecorderRef = useRef<HeadlessVideoRecorderRef>(null);
	const [recordingState, setRecordingState] = useState<VideoState>("inactive");

	const showPreview = () => {
		if (videoRecorderRef.current) {
			videoRecorderRef.current.showPreview();
		} else {
			console.error("videoRecorderRef is null");
		}
	};

	const RetakeButton = ({ onRetake }: any) => {
		return (
			<button className="w-auto p-2 bg-blue-200 border " onClick={onRetake}>
				Retake Recording
			</button>
		);
	};

	const DownloadButton = ({ onDownload }: any) => {
		return (
			<button className="p-2 bg-blue-200 border" onClick={onDownload}>
				Download Recording
			</button>
		);
	};

	const CountDown = ({ count }: any) => {
		return (
			<div className="flex p-2 font-semibold border">
				00:{count < 10 ? `0${count}` : count}
			</div>
		);
	};

	const StopRecording = ({ onStop }: any) => {
		return (
			<button className="p-2 bg-blue-200 border" onClick={onStop}>
				Stop Recording
			</button>
		);
	};

	const StartRecording = ({ onStart }: any) => {
		return (
			<button className="p-2 bg-blue-200 border" onClick={onStart}>
				Start Recording
			</button>
		);
	};

	return (
		<div className="flex flex-col items-center justify-center py-10 mt-10 border rounded gap-x-3 bg-gray-50">
			<HeadlessVideoRecorder
				ref={videoRecorderRef}
				autoStop={false}
				autoPreview={false}
				handleStateChange={(state) => setRecordingState(state)}
				customRetakeButton={(onRetake: any) => (
					<RetakeButton onRetake={onRetake} />
				)}
				customDownloadButton={(onDownload) => (
					<DownloadButton onDownload={onDownload} />
				)}
				customCountDown={(count) => <CountDown count={count} />}
				customStopRecording={(onStop) => <StopRecording onStop={onStop} />}
				customStartRecording={(onStart) => <StartRecording onStart={onStart} />}
			/>

			{recordingState == "inactive" && (
				<button className="p-2 bg-blue-300 border" onClick={showPreview}>
					Show Preview
				</button>
			)}
		</div>
	);
};

export default ManualStopVideoRecorder;

Styling

The HeadlessVideoRecorder component provides styling flexibility through Tailwind CSS. Customize the appearance by applying Tailwind classes to relevant props. Below are the key styling props:

  • recorderContainerClasses (optional): Classes or styles for the recorder container.
  • videoRecorderClasses (optional): Classes or styles for the video recorder element.
  • playbackVideoClasses (optional): Classes or styles for the playback video element.
  • footerContainerClasses (optional): Classes or styles for the footer container.
  • recordingFooterClasses (optional): Classes or styles for the recording footer.
  • previewFooterClasses (optional): Classes or styles for the preview footer.
  • recordedFooterClasses (optional): Classes or styles for the recorded footer.
  • startRecordingbuttonClasses (optional): Classes or styles for the start recording button.
  • retakeButtonClasses (optional): Classes or styles for the retake button.
  • downloadButtonClasses (optional): Classes or styles for the download button.

Best Practices

  • Ensure that the required permissions to camera and microphone are granted.
  • Utilize the provided customization options to tailor the component to your application's requirements.

Props Table

The following table lists the props available for the HeadlessVideoRecorder component:

PropTypeDefaultDescription
autoStopbooleantrueAutomatically stops recording after a specified time.
autoPreviewbooleantrueAutomatically shows a preview.
timeInMsnumber15000Time in milliseconds for recording (only applicable if autoStop is true).
videoBitsPerSecondnumber2500000The video encoding bit rate used to determine both the quality and size of the recorded video.
handleStateChange(state: VideoState) => voidCallback function triggered on state change.
customhandleDownload(file: any) => voidCustom function for handling the download of the recorded file.
customCountDown(count: number) => React.ReactNodeCustom component or function for displaying the countdown during recording.
customRetakeButton(onRetake: any) => React.ReactNodeCustom component or function for the retake button.
customStopRecording(onStop: any) => React.ReactNodeCustom component or function for the stop recording button.
customStartRecording(onStart: any) => React.ReactNodeCustom component or function for the start recording button.
customDownloadButton(onDownload: any) => React.ReactNodeCustom component or function for the download button.
mediaConstraintsMediaStreamConstraintsMedia constraints to customize video and audio settings.
recorderContainerClassesstring | CSSPropertiesClasses or styles for the recorder container.
videoRecorderClassesstring | CSSPropertiesClasses or styles for the video recorder element.
playbackVideoClassesstring | CSSPropertiesClasses or styles for the playback video element.
footerContainerClassesstring | CSSPropertiesClasses or styles for the footer container.
recordingFooterClassesstring | CSSPropertiesClasses or styles for the recording footer.
previewFooterClassesstring | CSSPropertiesClasses or styles for the preview footer.
recordedFooterClassesstring | CSSPropertiesClasses or styles for the recorded footer.
startRecordingbuttonClassesstring | CSSPropertiesClasses or styles for the start recording button.
retakeButtonClassesstring | CSSPropertiesClasses or styles for the retake button.
downloadButtonClassesstring | CSSPropertiesClasses or styles for the download button.
loaderReact.ReactNode"Loading Preview..."Loader component to display while the preview is loading.
retakeLabelstring"Retake Video"Label for the retake button.
downloadLabelstring"Download Video"Label for the download button.
stopLabelstring"Stop Recording"Label for the stop recording button.
startLabelstring"Start Recording"Label for the start recording button.

Notes

  • Ensure that the component is used within a secure (HTTPS) environment to access the user's camera and microphone.