Vidtreo
Integrações

Integração React

Guia completo para integrar VIDTREO em aplicações React com componentes e hooks.

Integração React

O pacote @vidtreo/recorder-react fornece um componente React pronto para usar e um hook poderoso para implementações personalizadas.

Instalação

npm install @vidtreo/recorder-react

Início Rápido

A forma mais simples de adicionar gravação de vídeo é com o componente VidtreoRecorder:

import { VidtreoRecorder } from '@vidtreo/recorder-react';

function App() {
  return (
    <VidtreoRecorder
      apiKey={import.meta.env.VITE_VIDTREO_API_KEY}
      onUploadComplete={(result) => {
        console.log('Vídeo pronto:', result.uploadUrl);
      }}
    />
  );
}

Props do Componente

Obrigatórios

PropTipoDescrição
apiKeystringSua API key do VIDTREO

Opcionais

PropTipoPadrãoDescrição
backendUrlstringhttps://core.vidtreo.comURL do endpoint da API
enableSourceSwitchingbooleantruePermite troca câmera/tela
enableMutebooleantrueMostra botão de mudo
enablePausebooleantrueMostra botão pausar/retomar
enableDeviceChangebooleantruePermite seleção de dispositivos
maxRecordingTimenumberundefinedDuração máxima em milissegundos
countdownDurationnumber3000Contagem regressiva prévia em ms
userMetadataobjectundefinedMetadados personalizados do vídeo
langstring"en"Idioma da UI (en, es, pt)
textsobjectundefinedTextos personalizados
demobooleanfalseModo demo (sem upload)

Callbacks

CallbackParâmetrosDescrição
onRecordingStart()Dispara ao iniciar gravação
onRecordingStop()Dispara ao terminar gravação
onUploadProgress(progress: number)Progresso do upload (0-1)
onUploadComplete(result)Upload completado com sucesso
onUploadError(error: Error)Falha no upload
onError(error: Error)Qualquer erro ocorrido

Exemplo Completo

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>Grave uma Mensagem de Vídeo</h1>

      <VidtreoRecorder
        apiKey={import.meta.env.VITE_VIDTREO_API_KEY}
        enableSourceSwitching={true}
        enableMute={true}
        enablePause={true}
        enableDeviceChange={true}
        maxRecordingTime={120000} // 2 minutos
        countdownDuration={3000}
        lang="pt"
        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('Erro:', 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>Gravação Completa!</h2>
          <video src={videoUrl} controls />
        </div>
      )}
    </div>
  );
}

Usando o Hook

Para controle total sobre a UI, use o hook useVidtreoRecorder:

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('URL do Vídeo:', result.uploadUrl);
    },
  });

  // Conectar stream ao elemento vídeo
  useEffect(() => {
    if (videoRef.current && state.stream) {
      videoRef.current.srcObject = state.stream;
    }
  }, [state.stream]);

  // Inicializar ao montar
  useEffect(() => {
    actions.startPreview();
  }, []);

  return (
    <div className="custom-recorder">
      <video ref={videoRef} autoPlay muted playsInline />

      {/* Indicador de nível de áudio */}
      <div className="audio-meter" style={{ width: `${audioLevel * 100}%` }} />

      {/* Controles de gravação */}
      <div className="controls">
        {state.recordingState === 'idle' && (
          <button onClick={() => actions.startRecording()}>
            Iniciar Gravação
          </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 ? 'Ativar Áudio' : 'Silenciar'}
            </button>

            <button onClick={() =>
              state.isPaused ? actions.resumeRecording() : actions.pauseRecording()
            }>
              {state.isPaused ? 'Retomar' : 'Pausar'}
            </button>

            <button onClick={() => actions.stopRecording()}>
              Parar
            </button>
          </>
        )}
      </div>

      {/* Seleção de dispositivos */}
      <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>

      {/* Progresso do upload */}
      {state.uploadProgress !== null && (
        <div className="upload-progress">
          Enviando: {Math.round(state.uploadProgress * 100)}%
        </div>
      )}

      {state.error && (
        <div className="error">{state.error}</div>
      )}
    </div>
  );
}

Valores de Retorno do Hook

Objeto State

interface State {
  recordingState: 'idle' | 'countdown' | 'recording';
  stream: MediaStream | null;
  isMuted: boolean;
  isPaused: boolean;
  error: string | null;
  countdown: number | null;
  timer: string;                    // formato "00:00"
  uploadProgress: number | null;    // 0-1
  transitionMessage: string | null;
  isInitialized: boolean;
  recordedBlob: Blob | null;
  devices: {
    cameras: MediaDeviceInfo[];
    microphones: MediaDeviceInfo[];
    selectedCamera: string | null;
    selectedMic: string | null;
  };
}

Objeto Actions

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

Internacionalização

Idiomas Integrados

// Inglês (padrão)
<VidtreoRecorder apiKey="..." lang="en" />

// Espanhol
<VidtreoRecorder apiKey="..." lang="es" />

// Português
<VidtreoRecorder apiKey="..." lang="pt" />

Textos Personalizados

Sobrescreva qualquer texto da UI:

<VidtreoRecorder
  apiKey="..."
  lang="pt"
  texts={{
    record: 'Iniciar Captura',
    stop: 'Finalizar Captura',
    pause: 'Aguardar',
    resume: 'Continuar',
    mute: 'Silêncio',
    unmute: 'Com Som',
    switchSource: 'Trocar Fonte',
    uploading: 'Enviando...',
  }}
/>

Chaves de Texto Disponíveis

ChavePadrão (Português)
initializingCameraInicializando câmera...
grantPermissionsPor favor conceda permissões de câmera
switchingDeviceTrocando dispositivo...
recordingStartsInA gravação começa em
switchingSourceTrocando fonte...
recREC
settingsConfigurações
recordGravar
stopParar
pausePausar
resumeRetomar
muteSilenciar
unmuteAtivar Áudio
switchSourceTrocar Fonte
cameraCâmera
microphoneMicrofone
uploadingEnviando...

Suporte TypeScript

Todos os tipos são exportados:

import type {
  VidtreoRecorderProps,
  UseVidtreoRecorderConfig,
  UseVidtreoRecorderReturn,
  VidtreoRecorderState,
  VidtreoRecorderActions,
  PartialTranslations,
  TranslationKeys,
} from '@vidtreo/recorder-react';

Compatibilidade com Next.js

Para Next.js com App Router, garanta a renderização do lado do cliente:

'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('Vídeo:', result.uploadUrl);
      }}
    />
  );
}

O gravador VIDTREO requer APIs do navegador e deve ser renderizado no lado do cliente.

Próximos Passos

Nesta página