React Integration
Complete guide to integrating VIDTREO in React applications with components and hooks.
React Integration
The @vidtreo/recorder-react package provides a ready-to-use React component and a powerful hook for custom implementations.
Installation
npm install @vidtreo/recorder-reactQuick Start
The simplest way to add video recording is with the VidtreoRecorder component:
import { VidtreoRecorder } from '@vidtreo/recorder-react';
function App() {
return (
<VidtreoRecorder
apiKey={import.meta.env.VITE_VIDTREO_API_KEY}
onUploadComplete={(result) => {
console.log('Video ready:', result.uploadUrl);
}}
/>
);
}Component Props
Required
| Prop | Type | Description |
|---|---|---|
apiKey | string | Your VIDTREO API key |
Optional
| Prop | Type | Default | Description |
|---|---|---|---|
backendUrl | string | https://core.vidtreo.com | API endpoint URL |
enableSourceSwitching | boolean | true | Allow camera/screen switching |
enableMute | boolean | true | Show mute button |
enablePause | boolean | true | Show pause/resume button |
enableDeviceChange | boolean | true | Allow device selection |
maxRecordingTime | number | undefined | Max duration in milliseconds |
countdownDuration | number | 3000 | Pre-recording countdown in ms |
userMetadata | object | undefined | Custom metadata for the video |
lang | string | "en" | UI language (en, es, pt) |
texts | object | undefined | Custom text overrides |
demo | boolean | false | Demo mode (no upload) |
Callbacks
| Callback | Parameters | Description |
|---|---|---|
onRecordingStart | () | Fired when recording begins |
onRecordingStop | () | Fired when recording ends |
onUploadProgress | (progress: number) | Upload progress (0-1) |
onUploadComplete | (result) | Upload finished successfully |
onUploadError | (error: Error) | Upload failed |
onError | (error: Error) | Any error occurred |
Complete Example
import { VidtreoRecorder } from '@vidtreo/recorder-react';
import { useState } from 'react';
function VideoRecorderPage() {
const [videoUrl, setVideoUrl] = useState<string | null>(null);
const [uploadProgress, setUploadProgress] = useState(0);
const [isRecording, setIsRecording] = useState(false);
return (
<div className="container">
<h1>Record a Video Message</h1>
<VidtreoRecorder
apiKey={import.meta.env.VITE_VIDTREO_API_KEY}
enableSourceSwitching={true}
enableMute={true}
enablePause={true}
enableDeviceChange={true}
maxRecordingTime={120000} // 2 minutes
countdownDuration={3000}
lang="en"
userMetadata={{
userId: 'user-123',
sessionId: 'session-456',
}}
onRecordingStart={() => {
setIsRecording(true);
setVideoUrl(null);
}}
onRecordingStop={() => {
setIsRecording(false);
}}
onUploadProgress={(progress) => {
setUploadProgress(progress);
}}
onUploadComplete={(result) => {
setVideoUrl(result.uploadUrl);
setUploadProgress(0);
}}
onError={(error) => {
console.error('Error:', error);
}}
/>
{uploadProgress > 0 && uploadProgress < 1 && (
<div className="progress-bar">
<div style={{ width: `${uploadProgress * 100}%` }} />
<span>{Math.round(uploadProgress * 100)}%</span>
</div>
)}
{videoUrl && (
<div className="result">
<h2>Recording Complete!</h2>
<video src={videoUrl} controls />
</div>
)}
</div>
);
}Using the Hook
For full control over the UI, use the useVidtreoRecorder hook:
import { useVidtreoRecorder } from '@vidtreo/recorder-react';
import { useRef, useEffect } from 'react';
function CustomRecorder() {
const videoRef = useRef<HTMLVideoElement>(null);
const { state, actions, audioLevel } = useVidtreoRecorder({
apiKey: import.meta.env.VITE_VIDTREO_API_KEY,
onUploadComplete: (result) => {
console.log('Video URL:', result.uploadUrl);
},
});
// Attach stream to video element
useEffect(() => {
if (videoRef.current && state.stream) {
videoRef.current.srcObject = state.stream;
}
}, [state.stream]);
// Initialize on mount
useEffect(() => {
actions.startPreview();
}, []);
return (
<div className="custom-recorder">
<video ref={videoRef} autoPlay muted playsInline />
{/* Audio level indicator */}
<div className="audio-meter" style={{ width: `${audioLevel * 100}%` }} />
{/* Recording controls */}
<div className="controls">
{state.recordingState === 'idle' && (
<button onClick={() => actions.startRecording()}>
Start Recording
</button>
)}
{state.recordingState === 'countdown' && (
<div className="countdown">{state.countdown}</div>
)}
{state.recordingState === 'recording' && (
<>
<span className="timer">{state.timer}</span>
<button onClick={() => actions.toggleMute()}>
{state.isMuted ? 'Unmute' : 'Mute'}
</button>
<button onClick={() =>
state.isPaused ? actions.resumeRecording() : actions.pauseRecording()
}>
{state.isPaused ? 'Resume' : 'Pause'}
</button>
<button onClick={() => actions.stopRecording()}>
Stop
</button>
</>
)}
</div>
{/* Device selection */}
<div className="devices">
<select
value={state.devices.selectedCamera || ''}
onChange={(e) => actions.changeCamera(e.target.value)}
>
{state.devices.cameras.map((camera) => (
<option key={camera.deviceId} value={camera.deviceId}>
{camera.label}
</option>
))}
</select>
<select
value={state.devices.selectedMic || ''}
onChange={(e) => actions.changeMic(e.target.value)}
>
{state.devices.microphones.map((mic) => (
<option key={mic.deviceId} value={mic.deviceId}>
{mic.label}
</option>
))}
</select>
</div>
{/* Upload progress */}
{state.uploadProgress !== null && (
<div className="upload-progress">
Uploading: {Math.round(state.uploadProgress * 100)}%
</div>
)}
{state.error && (
<div className="error">{state.error}</div>
)}
</div>
);
}Hook Return Values
State Object
interface State {
recordingState: 'idle' | 'countdown' | 'recording';
stream: MediaStream | null;
isMuted: boolean;
isPaused: boolean;
error: string | null;
countdown: number | null;
timer: string; // "00:00" format
uploadProgress: number | null; // 0-1
transitionMessage: string | null;
isInitialized: boolean;
recordedBlob: Blob | null;
devices: {
cameras: MediaDeviceInfo[];
microphones: MediaDeviceInfo[];
selectedCamera: string | null;
selectedMic: string | null;
};
}Actions Object
interface Actions {
startRecording(sourceType?: 'camera' | 'screen'): Promise<void>;
stopRecording(): Promise<RecordingStopResult>;
pauseRecording(): void;
resumeRecording(): void;
toggleMute(): void;
switchSource(sourceType: 'camera' | 'screen'): Promise<void>;
changeCamera(deviceId: string): Promise<void>;
changeMic(deviceId: string): Promise<void>;
startPreview(sourceType?: 'camera' | 'screen'): Promise<void>;
downloadVideo(): void;
cleanup(): void;
}Internationalization
Built-in Languages
// English (default)
<VidtreoRecorder apiKey="..." lang="en" />
// Spanish
<VidtreoRecorder apiKey="..." lang="es" />
// Portuguese
<VidtreoRecorder apiKey="..." lang="pt" />Custom Texts
Override any UI text:
<VidtreoRecorder
apiKey="..."
lang="en"
texts={{
record: 'Start Capture',
stop: 'End Capture',
pause: 'Hold',
resume: 'Continue',
mute: 'Silence',
unmute: 'Sound On',
switchSource: 'Toggle Source',
uploading: 'Sending...',
}}
/>Available Text Keys
| Key | Default (English) |
|---|---|
initializingCamera | Initializing camera... |
grantPermissions | Please grant camera permissions |
switchingDevice | Switching device... |
recordingStartsIn | Recording starts in |
switchingSource | Switching source... |
rec | REC |
settings | Settings |
record | Record |
stop | Stop |
pause | Pause |
resume | Resume |
mute | Mute |
unmute | Unmute |
switchSource | Switch Source |
camera | Camera |
microphone | Microphone |
uploading | Uploading... |
TypeScript Support
All types are exported:
import type {
VidtreoRecorderProps,
UseVidtreoRecorderConfig,
UseVidtreoRecorderReturn,
VidtreoRecorderState,
VidtreoRecorderActions,
PartialTranslations,
TranslationKeys,
} from '@vidtreo/recorder-react';Next.js Compatibility
For Next.js with App Router, ensure client-side rendering:
'use client';
import { VidtreoRecorder } from '@vidtreo/recorder-react';
export default function RecorderPage() {
return (
<VidtreoRecorder
apiKey={process.env.NEXT_PUBLIC_VIDTREO_API_KEY!}
onUploadComplete={(result) => {
console.log('Video:', result.uploadUrl);
}}
/>
);
}The VIDTREO recorder requires browser APIs and must render on the client side.
Next Steps
- Configuration Options — All available settings
- Callbacks Reference — Handle all events
- Custom UI Example — Build your own interface