Ejemplos
UI Personalizada
Construye tu propia interfaz de grabación de video con hooks de VIDTREO.
UI Personalizada
Usa el hook useVidtreoRecorder para construir interfaces de grabación completamente personalizadas.
Grabador Personalizado Completo
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,
countdownDuration: 3000,
maxRecordingTime: 120000,
onUploadComplete: (result) => {
console.log('Video listo:', result.uploadUrl);
},
});
useEffect(() => {
if (videoRef.current && state.stream) {
videoRef.current.srcObject = state.stream;
}
}, [state.stream]);
useEffect(() => {
actions.startPreview();
return () => actions.cleanup();
}, []);
return (
<div className="custom-recorder">
{/* Vista previa de video */}
<div className="video-container">
<video ref={videoRef} autoPlay muted playsInline />
{state.recordingState === 'recording' && (
<div className="recording-indicator">
<span className="rec-dot" />
<span className="timer">{state.timer}</span>
</div>
)}
{state.recordingState === 'countdown' && (
<div className="countdown-overlay">
<span className="countdown-number">{state.countdown}</span>
</div>
)}
</div>
{/* Medidor de audio */}
<div className="audio-meter">
<div
className="audio-level"
style={{
width: `${audioLevel * 100}%`,
backgroundColor: audioLevel > 0.8 ? '#ef4444' : '#22c55e'
}}
/>
</div>
{/* Controles */}
<div className="controls">
{state.recordingState === 'idle' && (
<>
<button onClick={() => actions.startRecording('camera')}>
Grabar Cámara
</button>
<button onClick={() => actions.startRecording('screen')}>
Grabar Pantalla
</button>
</>
)}
{state.recordingState === 'recording' && (
<>
<button onClick={() => actions.toggleMute()}>
{state.isMuted ? 'Activar Audio' : 'Silenciar'}
</button>
<button onClick={() =>
state.isPaused ? actions.resumeRecording() : actions.pauseRecording()
}>
{state.isPaused ? 'Reanudar' : 'Pausar'}
</button>
<button onClick={() => actions.stopRecording()}>
Detener
</button>
</>
)}
</div>
{/* Selección de dispositivos */}
{state.recordingState === 'idle' && (
<div className="device-selection">
<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 || 'Cámara'}
</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 || 'Micrófono'}
</option>
))}
</select>
</div>
)}
{/* Progreso de subida */}
{state.uploadProgress !== null && (
<div className="upload-progress">
Subiendo: {Math.round(state.uploadProgress * 100)}%
</div>
)}
{state.error && <div className="error">{state.error}</div>}
</div>
);
}Ejemplo Mínimo
function MinimalRecorder() {
const { state, actions } = useVidtreoRecorder({
apiKey: import.meta.env.VITE_VIDTREO_API_KEY,
});
return (
<div>
<video
ref={(el) => el && state.stream && (el.srcObject = state.stream)}
autoPlay
muted
/>
<button
onClick={() =>
state.recordingState === 'idle'
? actions.startRecording()
: actions.stopRecording()
}
>
{state.recordingState === 'idle' ? 'Grabar' : 'Detener'}
</button>
</div>
);
}Próximos Pasos
- Uso Avanzado — Manejo de errores
- API de Hooks — Referencia completa del hook