@vidtreo/recorder-vue

Vue 3 components and composables for @vidtreo/recorder - video recording SDK
8,482
Install
npm install @vidtreo/recorder-vue
Latest Version:1.13.0
Vue:3
License:MIT
Last Updated:Oct 22, 2026
Links: npm
Maintainer: kuze

@vidtreo/recorder-vue

Vue 3 components and composables for the Vidtreo video recording SDK. Drop the recorder into any Vue app with a single tag, or build a fully custom UI on top of the same battle-tested composables that power @vidtreo/recorder-react — same recording pipeline, same upload queue, same i18n, native Composition API ergonomics.

What you get out of the box

  • 🎥 Camera + screen capture with one-click source switching, mute, pause/resume, and device selection.
  • ⏱️ Countdown, timer, audio meter, transcoding progress, upload progress — all wired and styled.
  • 🔐 Permission flow with a polished overlay that walks the user through allowing camera + mic, plus a recovery guide when they were denied.
  • 📱 Mobile-aware — overlay modal, embedded mode, or the device's native camera (file input), selectable via the mobileMode prop.
  • 🌐 i18n out of the box (English + Spanish) and full per-string overrides for any language you want.
  • 🧪 SSR-safe — every browser API is gated to client-side mount. Drop it in Nuxt with @vidtreo/recorder-nuxt and forget about hydration mismatches.
  • 🛠️ Composable API for building your own UI — same shape as @vidtreo/recorder-react, so React-to-Vue migrations are 1:1.

Installation

npm install @vidtreo/recorder-vue @vidtreo/recorder

Peer dependencies:

  • @vidtreo/recorder >=1.9.0
  • vue >=3.0.0

Don't forget the stylesheet — either import it once in your entry, or rely on the built-in CSS injection (added to <head> automatically when the package loads).

// Optional explicit import — useful if you bundle styles separately
import "@vidtreo/recorder-vue/styles.css";

Quick start

Drop-in component (2 lines)

<script setup lang="ts">
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
</script>

<template>
  <VidtreoRecorder :recorder-props="{ apiKey: 'your-api-key' }" />
</template>

Using environment variables

For Vite-based apps, expose the key via import.meta.env:

# .env
VITE_VIDTREO_API_KEY=your-api-key
<script setup lang="ts">
import { VidtreoRecorder } from "@vidtreo/recorder-vue";

const apiKey = import.meta.env.VITE_VIDTREO_API_KEY as string;
</script>

<template>
  <VidtreoRecorder :recorder-props="{ apiKey }" />
</template>

Component API

The component accepts a single recorder-props object so the discriminated union (demo: true vs apiKey vs getAccessToken) stays type-safe at the call site. Events use the standard Vue @event-name listener syntax.

Props (recorder-props)

Prop Type Required Default Description
apiKey string Yes* – API key for authentication. *Optional when demo: true or when getAccessToken is used.
getAccessToken () => Promise<string> No* – Returns a short-lived desktop access token minted by your server. Use instead of apiKey (exactly one of the two). Called again whenever a fresh token is needed, including when a queued upload resumes after a reload.
demo boolean No false Demo mode. Skips upload and lets you download the local recording.
backendUrl string No https://core.vidtreo.com Backend API URL.
countdownDuration number No – Pre-recording countdown (milliseconds).
minTimeRecord number No – Minimum recording time in ms before Stop is allowed. Must not be greater than maxRecordingTime when both are positive.
maxRecordingTime number No – Maximum recording time in milliseconds.
userMetadata Record<string, unknown> No – Custom metadata attached to uploads.
recordingPrompt RecordingPrompt No – Prompt shown during recording. Use countdown: { show, placement: "above-countdown" } to float it over the countdown. A label field is still accepted for backward compatibility but is not displayed.
enableSourceSwitching boolean No true Toggle between camera and screen.
enableMute boolean No true Show the mute/unmute button.
enablePause boolean No true Show pause/resume buttons.
enableDeviceChange boolean No true Show the settings panel with cam/mic selectors.
enableTabVisibilityOverlay boolean No false Show overlay when the user switches tabs (camera recordings only).
tabVisibilityOverlayText string No localized default Custom message for the tab-visibility overlay.
mobileMode "embed" | "overlay" | "native" No "overlay" Mobile experience. "embed" = same as desktop, "overlay" = fullscreen modal, "native" = device's native camera (file input).
nativeCamera boolean No – Deprecated — use mobileMode: "native" instead.
audioOnly boolean No false Record audio only with the microphone (no camera). Requires audio recording enabled for the environment in the backend. See Audio-only recording.
maxFileSize number No – Maximum file size in MB (native camera mode).
lang string No "en" Language code ("en" or "es").
texts PartialTranslations No – Per-key text overrides.

Events

Event Payload Fired when
recording-start – Recording begins (after the countdown finishes).
recording-stop – Recording ends and processing starts.
upload-progress progress: number (0..1), phase: UploadProgressPhase | null Upload progress in every flow (desktop, mobile and native camera, including resumed uploads). phase is "preparing", "transferring", "finalizing", "completed", or null when the upload starts (progress 0).
upload-complete RecordingUploadResult Upload finishes. Same payload for the desktop/overlay recorder and native camera mode. See Upload completion payload.
upload-error error: Error Upload fails. Use getUploadErrorCode(error) to read the error code.
transcoding-progress progress: number (0..1) Transcoding progress after a recording stops (desktop and mobile) and native camera processing.
error error: Error Any unhandled error, including the credential conflict configuration error.

Example with listeners

<script setup lang="ts">
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
import type {
  RecordingUploadResult,
  UploadProgressPhase,
  VidtreoRecorderProps,
} from "@vidtreo/recorder-vue";

const recorderProps: VidtreoRecorderProps = {
  apiKey: "your-api-key",
  countdownDuration: 3,
  minTimeRecord: 10_000,
  lang: "en",
};

function onComplete(result: RecordingUploadResult) {
  console.log("Recording uploaded:", result.recordingId);
  console.log("View at:", result.uploadUrl);
}

function onProgress(progress: number, phase: UploadProgressPhase | null) {
  console.log(`Upload: ${Math.round(progress * 100)}% (${phase ?? "starting"})`);
}

function onError(error: Error) {
  console.error("Recorder error:", error.message);
}
</script>

<template>
  <VidtreoRecorder
    :recorder-props="recorderProps"
    @upload-complete="onComplete"
    @upload-progress="onProgress"
    @error="onError"
  />
</template>

Temporary access tokens

<script setup lang="ts">
import { VidtreoRecorder } from "@vidtreo/recorder-vue";

async function getAccessToken(): Promise<string> {
  const response = await fetch("/api/vidtreo-token");
  const { token } = await response.json();
  return token;
}
</script>

<template>
  <VidtreoRecorder :recorder-props="{ getAccessToken }" />
</template>

The token is never stored. If an upload is interrupted, the component calls getAccessToken again when the upload resumes.

Pass either apiKey or getAccessToken, not both. The props type rejects both at compile time; at runtime (plain JavaScript) the component renders a configuration error with the message Provide either apiKey or getAccessToken, not both and emits error once with an error whose code is CONFIG_ERROR_CREDENTIAL_CONFLICT ("config.credential-conflict"). Passing neither (outside demo mode, and without VIDTREO_API_KEY in the environment) renders the errorApiKeyRequired configuration error and emits error once instead of throwing. The same applies when StandardRecorder, MobileWebRecorderUI or NativeCameraUI are used directly. Demo mode ignores credentials. CONFIG_ERROR_CREDENTIAL_CONFLICT and isCredentialConflictError are re-exported from @vidtreo/recorder:

import { isCredentialConflictError } from "@vidtreo/recorder-vue";

function onError(error: Error) {
  if (isCredentialConflictError(error)) {
    reportMisconfiguration();
  }
}

Progress overlays

After you stop a recording the preview shows a progress overlay until the upload finishes:

Stage Label key Progress
Finalizing the recording (before transcoding reports progress) finishing 0%
Transcoding finishing transcoding progress
Uploading uploading, finalizing when the backend is finalizing, retryingUpload while a retry is pending upload progress

The same overlays show in the mobile overlay recorder. In native camera mode a resumed upload without a preview shows a standalone progress bar with the same labels.

Upload completion payload

upload-complete receives a RecordingUploadResult: every field of the backend upload result plus the backward-compatible recordingId and uploadUrl.

import type { RecordingUploadResult } from "@vidtreo/recorder-vue";

type RecordingUploadResult = {
  recordingId: string;           // same value as id
  uploadUrl: string;             // "" when the backend has no URL yet
  id: string;
  publicId: string;
  filename: string;
  fileSize: number;
  mimeType: string;
  duration: number | null;
  status: string;
  createdAt: string;
  transferStatus: "pending" | "transferring" | "transferred" | "failed" | null;
  transferError: string | null;
  transferredAt: string | null;
  r2DeleteAfter: string | null;
  r2DeletedAt: string | null;
  mediaType?: "audio";           // set for audio-only recordings
  audioId?: string;              // same value as id, set for audio-only recordings
};

For audio-only recordings (audioOnly: true) the payload also has mediaType: "audio" and audioId.

Upload errors

When an upload fails with a known cause, the component shows a dialog (role="alertdialog") after recording and processing finish, and upload-error receives an error with a code:

<script setup lang="ts">
import {
  getUploadErrorCode,
  UPLOAD_ERROR_INSUFFICIENT_CREDITS,
  VidtreoRecorder,
} from "@vidtreo/recorder-vue";

function onUploadError(error: Error) {
  if (getUploadErrorCode(error) === UPLOAD_ERROR_INSUFFICIENT_CREDITS) {
    notifyAdmin();
  }
}
</script>

<template>
  <VidtreoRecorder
    :recorder-props="{ apiKey: 'your-api-key' }"
    @upload-error="onUploadError"
  />
</template>
Code Meaning
upload.insufficient-credits The account has no credits left (HTTP 402). The upload stays queued and is retried every 5 minutes; onUploadError fires on each rejected attempt. The first rejection of each queued upload per page session also sets the built-in dialog and uploadErrorCode; repeated rejections only call onUploadError (no onError, no state change).

getUploadErrorCode returns null for other errors. Network errors are retried automatically before they are reported; while a retry is in progress the progress bar shows the retryingUpload label.

Upload resume

Uploads are queued in IndexedDB before they are sent, in every mode (desktop, mobile overlay, mobile embed, and native camera). If the page is reloaded or the connection drops, the next mounted VidtreoRecorder resumes the upload with the same idempotency key and sends only the parts that are missing. Progress shows again while it resumes (in native camera mode as a standalone progress bar, since there is no preview), and upload-complete fires with the full payload when it finishes. Mount the component with the same credentials (apiKey or getAccessToken) so the upload can resume. If IndexedDB is unavailable, uploads go directly to the backend without persistence.

Composable API

When the default component doesn't fit your UI, drop down to the useVidtreoRecorder composable and assemble your own.

<script setup lang="ts">
import { useVidtreoRecorder } from "@vidtreo/recorder-vue";

const { state, actions, audioLevel, controller } = useVidtreoRecorder({
  apiKey: "your-api-key",
  onUploadComplete: (result) => console.log("Upload complete:", result),
});
</script>

<template>
  <div>
    <video v-if="state.stream" :srcObject="state.stream" autoplay muted playsinline />

    <button v-if="state.recordingState === 'idle'" @click="actions.startRecording()">
      Start
    </button>
    <button v-else @click="actions.stopRecording()">
      Stop
    </button>

    <div>Timer: {{ state.timer }}</div>
    <div>Audio level: {{ audioLevel }}</div>
    <div v-if="state.error" class="error">{{ state.error }}</div>
  </div>
</template>

What the composable returns

{
  state: Reactive<VidtreoRecorderState>;      // mutate freely, fully reactive
  actions: VidtreoRecorderActions;            // plain methods
  audioLevel: Ref<number>;                    // 0..1 — perfect for waveform UIs
  controller: ShallowRef<RecorderController>; // raw core SDK if you need it
}

state

{
  recordingState: "idle" | "countdown" | "recording";
  stream: MediaStream | null;
  isMuted: boolean;
  isPaused: boolean;
  isFinalizingRecording: boolean; // true from stop until the recording blob is ready
  isAudioReady: boolean;
  hasAudioFailed: boolean;
  error: string | null;
  errorCode: string | null;
  countdown: number | null;
  timer: string;                  // "00:12" format
  uploadProgress: number | null;  // 0..1 or null
  uploadPhase: UploadProgressPhase | null;   // "preparing" | "transferring" | "finalizing" | "completed"
  uploadRetryAttempt: number | null;
  uploadErrorCode: UploadErrorCode | null;   // "upload.insufficient-credits"
  transcodingProgress: number | null;        // 0..1 while transcoding, otherwise null
  transitionMessage: string | null;
  isInitialized: boolean;
  recordedBlob: Blob | null;      // populated in demo mode
  audioWarning: AudioWarning | null;
  audioRecovered: boolean;
  devices: {
    cameras: MediaDeviceInfo[];
    microphones: MediaDeviceInfo[];
    selectedCamera: string | null;
    selectedMic: string | null;
  };
}

actions

Action Signature What it does
startRecording (sourceType?: "camera" | "screen" | "audio") => Promise<void> Begin recording (after countdown if configured). Defaults to "audio" when audioOnly is set, otherwise "camera".
stopRecording () => Promise<RecordingStopResult> Stop and trigger upload. The result has blob and mediaType ("audio" or "video").
pauseRecording () => void Pause an active recording.
resumeRecording () => void Resume from pause.
toggleMute () => void Toggle the audio mute state.
switchSource (sourceType: "camera" | "screen") => Promise<void> Swap between camera and screen during preview/recording.
changeCamera (deviceId: string) => Promise<void> Switch to a different camera.
changeMic (deviceId: string) => Promise<void> Switch to a different microphone.
startPreview (sourceType?: "camera" | "screen" | "audio") => Promise<void> Open the stream without recording. "audio" opens a microphone-only stream.
stopPreview () => void Tear the preview stream down.
downloadVideo () => void Download the last recordedBlob (demo mode).
clearUploadError () => void Clear uploadErrorCode after the user dismisses the upload error.
cleanup () => void Release all resources. Useful before unmounting.

Specialized composables

Composable Purpose
useMobileWebRecorder(config) Wraps useVidtreoRecorder and adds isModalOpen, openModal, closeModal, canCloseModal for the mobile overlay experience.
useNativeCamera(config) File-input + transcoding flow used when mobileMode: "native". Returns { state, actions } with handleFileSelect, processAndUpload, downloadVideo, reset. Resumes queued native uploads on mount (except in demo mode); state includes uploadPhase, uploadRetryAttempt and uploadErrorCode.
usePermissionFlow(options) Drives the camera/mic permission overlay. Returns { isActive, isComplete, currentStep, steps, recoveryData, requestPermission, retryPermission } — useful if you want to build a fully custom permission UI.
useRecorderTranslations(translations) Splits a TranslationKeys object into preview, buttons, and settings subsets as ComputedRefs. Accepts MaybeRefOrGetter<TranslationKeys> so it stays reactive when the language changes.

Internationalization

Built-in: English (en) and Spanish (es). Use the lang prop to switch, and texts to override individual strings or to ship a brand-new language entirely.

Switch language

<template>
  <VidtreoRecorder :recorder-props="{ apiKey, lang: 'es' }" />
</template>

Override individual strings

<script setup lang="ts">
import { VidtreoRecorder } from "@vidtreo/recorder-vue";

const recorderProps = {
  apiKey: "your-api-key",
  lang: "en",
  texts: {
    record: "🔴 Start Capture",
    stop: "⏹️ End Capture",
    settings: "Options",
  },
};
</script>

<template>
  <VidtreoRecorder :recorder-props="recorderProps" />
</template>

Ship a completely custom language (e.g., French)

<script setup lang="ts">
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
import type { PartialTranslations } from "@vidtreo/recorder-vue";

const french: PartialTranslations = {
  initializingCamera: "Initialisation de la caméra...",
  grantPermissions: "Accordez les autorisations de caméra et de microphone",
  switchingDevice: "Changement d'appareil...",
  recordingStartsIn: "L'enregistrement commence dans...",
  switchingSource: "Changement de source...",
  rec: "ENREG",
  settings: "Paramètres",
  record: "Enregistrer",
  stop: "Arrêter",
  pause: "Pause",
  resume: "Reprendre",
  mute: "Muet",
  unmute: "Activer le son",
  switchSource: "Changer de source",
  camera: "Caméra",
  microphone: "Microphone",
  uploading: "Téléchargement...",
};
</script>

<template>
  <VidtreoRecorder
    :recorder-props="{ apiKey: 'your-api-key', lang: 'fr', texts: french }"
  />
</template>

Dynamic language switching

The component is fully reactive — change lang and the UI re-localizes without a remount:

<script setup lang="ts">
import { ref } from "vue";
import { VidtreoRecorder } from "@vidtreo/recorder-vue";

const language = ref<"en" | "es">("en");
</script>

<template>
  <select v-model="language">
    <option value="en">English</option>
    <option value="es">Español</option>
  </select>

  <VidtreoRecorder :recorder-props="{ apiKey: 'your-api-key', lang: language }" />
</template>

Translation keys

Every key is identical (name and default copy) across @vidtreo/recorder-react, @vidtreo/recorder-vue and @vidtreo/recorder-wc.

Key English Default Spanish Default
initializingCamera Initializing camera... Inicializando cámara...
grantPermissions Grant camera and microphone permissions when prompted Otorga permisos de cámara y micrófono cuando se solicite
browserUnsupported This browser is not supported Este navegador no es compatible
browserUnsupportedDynamic {browser} ({version}) is not supported, please use <a href="https://www.google.com/chrome/" target="_blank" rel="noopener noreferrer">Chrome</a> {browser} ({version}) no es compatible, por favor usa <a href="https://www.google.com/chrome/" target="_blank" rel="noopener noreferrer">Chrome</a>
browserUnsupportedSafari Safari (latest stable) is supported. If you experience issues, please use <a href="https://www.google.com/chrome/" target="_blank" rel="noopener noreferrer">Chrome</a> Safari (última versión estable) es compatible. Si experimentas problemas, por favor usa <a href="https://www.google.com/chrome/" target="_blank" rel="noopener noreferrer">Chrome</a>
browserUnsupportedFirefox Firefox is not supported, please use <a href="https://www.google.com/chrome/" target="_blank" rel="noopener noreferrer">Chrome</a> Firefox no es compatible, por favor use <a href="https://www.google.com/chrome/" target="_blank" rel="noopener noreferrer">Chrome</a>
retryCamera Retry Camera Reintentar Cámara
cameraInUse Your camera is being used by another application. Close other apps using the camera (Zoom, Teams, Discord) and try again. Tu cámara está siendo usada por otra aplicación. Cierra otras apps que usen la cámara (Zoom, Teams, Discord) e intenta de nuevo.
cameraNotFound No camera detected. Connect a camera or check your device settings. No se detectó ninguna cámara. Conecta una cámara o revisa la configuración de tu dispositivo.
cameraPermissionDenied Camera access was denied. Allow camera access in your browser settings and try again. Se denegó el acceso a la cámara. Permite el acceso a la cámara en la configuración de tu navegador e intenta de nuevo.
cameraTimeout The camera took too long to start. Close other apps using the camera and try again. La cámara tardó demasiado en iniciar. Cierra otras apps que usen la cámara e intenta de nuevo.
failedToStartCamera Failed to start camera Error al iniciar la cámara
audioInUse Your microphone is being used by another application. Close other apps using the microphone (Zoom, Teams, Discord) and try again. Tu micrófono está siendo usado por otra aplicación. Cierra otras apps que usen el micrófono (Zoom, Teams, Discord) e intenta de nuevo.
audioNotFound No microphone detected. Connect a microphone or check your device settings. No se detectó ningún micrófono. Conecta un micrófono o revisa la configuración de tu dispositivo.
audioPermissionDenied Microphone access was denied. Allow microphone access in your browser settings and try again. Se denegó el acceso al micrófono. Permite el acceso al micrófono en la configuración de tu navegador e intenta de nuevo.
audioTimeout The microphone took too long to start. Close other apps using the microphone and try again. El micrófono tardó demasiado en iniciar. Cierra otras apps que usen el micrófono e intenta de nuevo.
failedToStartAudio Failed to start microphone Error al iniciar el micrófono
audioErrorTitle Microphone unavailable Micrófono no disponible
audioErrorMessage We couldn't access your microphone. It may be in use by another app like Zoom, Teams, or Discord. Please close it and try again. No pudimos acceder a tu micrófono. Puede estar en uso por otra app como Zoom, Teams o Discord. Ciérrala e inténtalo de nuevo.
audioErrorRetry Try again Intentar de nuevo
audioMissingTitle Recording has no audio La grabación no tiene audio
audioMissingMessage We couldn't capture audio in this recording. Your microphone may have been disconnected or blocked by the browser. Check your microphone and record again. No pudimos capturar audio en esta grabación. Es posible que el micrófono se haya desconectado o que el navegador lo haya bloqueado. Verifica tu micrófono y vuelve a grabar.
audioSilentTitle Recording is silent La grabación quedó en silencio
audioSilentMessage We didn't detect any sound during the recording. Make sure your microphone is working and not muted by your operating system, then record again. No detectamos sonido durante la grabación. Verifica que tu micrófono esté funcionando y no esté silenciado por el sistema, luego vuelve a grabar.
audioProcessingErrorTitle Audio processing error Error al procesar el audio
audioProcessingErrorMessage We couldn't process the audio in this recording. Please record again. No pudimos procesar el audio de esta grabación. Por favor vuelve a grabar.
audioMissingRetry Record again Grabar de nuevo
audioWarningNoSignalTitle No microphone signal Sin señal del micrófono
audioWarningNoSignalMessage We're not detecting any sound. Check that your microphone is active. No estamos detectando sonido. Verifica que tu micrófono esté activo.
audioWarningLowSignalTitle Audio is very quiet Audio muy bajo
audioWarningLowSignalMessage Move closer to the microphone or turn up the input volume. Acércate al micrófono o sube el volumen de entrada.
audioWarningSpeakingMutedTitle You're speaking while muted Estás hablando muteado
audioWarningSpeakingMutedMessage Unmute your microphone if you want your voice in the recording. Activa el micrófono si quieres que tu voz se escuche en la grabación.
audioWarningTrackEndedTitle Microphone disconnected Micrófono desconectado
audioWarningTrackEndedMessage The microphone was disconnected. Reconnect it before continuing. Se desconectó el micrófono. Reconéctalo antes de continuar.
audioWarningNoChunksTitle No microphone input Sin entrada del micrófono
audioWarningNoChunksMessage We're not receiving audio from the microphone. Check browser permissions. No estamos recibiendo audio del micrófono. Revisa los permisos del navegador.
audioWarningTrackMutedTitle Microphone muted by browser Micrófono silenciado por el navegador
audioWarningTrackMutedMessage The browser muted your microphone. Check site settings. El navegador silenció tu micrófono. Revisa la configuración del sitio.
audioWarningDismiss Dismiss Cerrar
cameraErrorTitle Camera unavailable Cámara no disponible
cameraErrorMessage We couldn't access your camera. It may be in use by another app. Please close it and try again. No pudimos acceder a tu cámara. Puede estar en uso por otra app. Ciérrala e inténtalo de nuevo.
browserErrorTitle Browser not supported Navegador no compatible
browserErrorMessage Your browser doesn't support video recording. Please use the latest version of Chrome for the best experience. Tu navegador no es compatible con la grabación de video. Por favor usa la última versión de Chrome.
recordingCodecUnsupportedTitle Recording format not supported Formato de grabación no compatible
recordingCodecUnsupportedMessage This device can't use the selected video format. Close other apps, update Chrome if possible, and record again. Este dispositivo no puede usar el formato de video seleccionado. Cierra otras apps, actualiza Chrome si es posible y vuelve a grabar.
recordingMediaEmptyTitle No video was produced No se generó ningún video
recordingMediaEmptyMessage The browser didn't produce a usable video. Check your camera and record again. El navegador no produjo un video utilizable. Verifica la cámara y vuelve a grabar.
recordingMediaErrorTitle Recording could not be finished No se pudo finalizar la grabación
recordingMediaErrorMessage The browser reported an error before the video was ready to upload. Record again. El navegador informó un error antes de preparar el video para subirlo. Vuelve a grabar.
recordingServerTranscodeFallbackTitle Video processing failed No se pudo procesar el video
recordingServerTranscodeFallbackMessage We couldn't prepare this video for upload on your device. Record again. No pudimos preparar este video para subirlo en tu dispositivo. Vuelve a grabar.
recordingTrackEndedTitle Camera stopped during recording La cámara se detuvo durante la grabación
recordingTrackEndedMessage The camera feed ended before the recording finished. Check that the camera is still connected and record again. La señal de la cámara terminó antes de finalizar la grabación. Verifica que la cámara siga conectada y vuelve a grabar.
recordingFinalizeTimeoutTitle Recording took too long to finish La grabación tardó demasiado en finalizar
recordingFinalizeTimeoutMessage This device may be low on memory or processing power. Close other apps or browser tabs, then record again. Es posible que este dispositivo tenga poca memoria o potencia de procesamiento. Cierra otras apps o pestañas del navegador y vuelve a grabar.
recordingStateRaceTitle Recording did not start correctly La grabación no inició correctamente
recordingStateRaceMessage The recording could not be finalized because it did not start cleanly. Please refresh the page and record again. No se pudo finalizar la grabación porque no inició correctamente. Actualiza la página y vuelve a grabar.
recordingNoFramesTitle No video was captured No se capturó video
recordingNoFramesMessage We couldn't receive video frames from the camera. Check your camera connection and record again. No pudimos recibir fotogramas de video de la cámara. Verifica la conexión de la cámara y vuelve a grabar.
recordingUnsupportedTitle Recording not available Grabación no disponible
recordingUnsupportedMessage This device or browser can't record video reliably right now. Check your connection, update Chrome if possible, or use another device. Este dispositivo o navegador no puede grabar video de forma estable ahora. Revisa tu conexión, actualiza Chrome si es posible o usa otro dispositivo.
recordingPipelineRetry Record again Grabar de nuevo
genericErrorTitle Something went wrong Algo salió mal
genericErrorMessage An unexpected error occurred. Please try again. Ocurrió un error inesperado. Por favor inténtalo de nuevo.
errorRetry Try again Intentar de nuevo
switchingDevice Switching device... Cambiando dispositivo...
recordingStartsIn Recording starts in... La grabación comienza en...
switchingSource Switching source... Cambiando fuente...
rec REC GRAB
settings Settings Configuración
record Record Grabar
stop Stop Detener
pause Pause Pausar
resume Resume Reanudar
mute Mute Silenciar
unmute Unmute Activar sonido
switchSource Switch Source Cambiar Fuente
camera Camera Cámara
microphone Microphone Micrófono
microphoneConnecting Connecting microphone... Conectando micrófono...
minimumRecordingTimeNotReached You have not met the minimum recording time yet Aun no cumples el tiempo minimo de grabacion
uploading Uploading... Subiendo...
finalizing Finalizing… Finalizando…
retryingUpload Retrying upload... Reintentando subida...
uploadInsufficientCredits This video couldn't be uploaded. Please contact the site administrator. No se pudo subir el video. Contacta al administrador del sitio.
uploadInsufficientCreditsTitle Video couldn't be uploaded No se pudo subir el video
uploadErrorClose Close Cerrar
finishing Finishing... Finalizando...
userInAnotherTab User in another tab Usuario en otra pestaña
download Download Descargar
nativeCameraSelectVideo Select Video from Gallery Seleccionar Video de la Galería
nativeCameraRecordVideo Record with Camera Grabar con Cámara
nativeCameraProcessing Processing video... Procesando video...
nativeCameraConfigLoading Loading settings... Cargando configuración...
nativeCameraConfigLoadError Failed to load settings No se pudo cargar la configuración
nativeCameraPreviewAlt Video preview Vista previa del video
errorTitle Configuration Error Error de Configuración
errorApiKeyRequired An API Key or access token provider is required. Se requiere una API Key o un proveedor de token de acceso.
errorGeneric An error occurred while initializing the recorder Ocurrió un error al inicializar la grabadora
mobileOpenCamera Allow Access Permitir Acceso
mobileOpenCameraTitle Camera & Microphone Cámara y Micrófono
mobileOpenCameraDescription We need access to your camera and microphone to start recording Necesitamos acceso a tu cámara y micrófono para comenzar a grabar
mobileCloseCamera Close Cerrar
mobileHideRecordingPrompt Hide prompt Ocultar pregunta
mobileShowRecordingPrompt Show prompt Mostrar pregunta
mobilePermissionDenied Camera Access Denied Acceso a Cámara Denegado
mobilePermissionDeniedDescription Please allow camera access in your browser settings to record video. Por favor permite el acceso a la cámara en la configuración de tu navegador para grabar video.
permissionFlowTitle Set Up Your Camera Configurar tu Cámara
permissionFlowCameraTitle Camera & Microphone Cámara y Micrófono
permissionFlowMicrophoneTitle Camera & Microphone Cámara y Micrófono
permissionFlowCameraLabel We need access to your camera and microphone to start recording Necesitamos acceso a tu cámara y micrófono para comenzar a grabar
permissionFlowMicrophoneLabel We need access to your camera and microphone to start recording Necesitamos acceso a tu cámara y micrófono para comenzar a grabar
permissionFlowStatusPending Pending Pendiente
permissionFlowStatusGranted Ready Listo
permissionFlowStatusDenied Blocked Bloqueado
permissionFlowStatusRequesting Click "Allow" in the browser popup above Haz clic en "Permitir" en el aviso del navegador
permissionFlowAllowCamera Allow Access Permitir Acceso
permissionFlowAllowMicrophone Allow Access Permitir Acceso
permissionFlowRetry Try Again Reintentar
permissionFlowRecoveryTitle Allow access to continue Permite el acceso para continuar
permissionFlowRecoveryInstructions Open your browser settings and allow camera and microphone access, then try again. Abre la configuración de tu navegador y permite el acceso a la cámara y micrófono, luego intenta de nuevo.
permissionFlowConnecting Setting up... Preparando...
initializingMicrophone Initializing microphone... Iniciando micrófono...
grantMicrophonePermission Grant microphone permission when prompted Concede el permiso de micrófono cuando se te solicite
retryMicrophone Retry Microphone Reintentar micrófono
audioOnlyReady Ready to record Listo para grabar
audioOnlyRecording Recording Grabando
audioOnlyPaused Paused En pausa
audioOnlyUploading Uploading {progress}% Subiendo {progress}%
audioOnlyUploaded Upload complete Subida completada
audioOnlyElapsedTime Elapsed time Tiempo transcurrido
audioOnlyNoMicrophones No microphones available No hay micrófonos disponibles
audioRecordingDisabledTitle Audio recording unavailable Grabación de audio no disponible
audioRecordingDisabled Audio recording is not enabled for this environment La grabación de audio no está habilitada para este entorno
permissionFlowMicrophoneOnlyTitle Microphone Micrófono
permissionFlowMicrophoneOnlyLabel We need access to your microphone to start recording Necesitamos acceso a tu micrófono para comenzar a grabar
permissionFlowMicrophoneOnlyRecoveryInstructions Open your browser settings and allow microphone access, then try again. Abre la configuración de tu navegador y permite el acceso al micrófono, luego intenta de nuevo.
mobileOpenMicrophoneTitle Microphone Micrófono
mobileOpenMicrophoneDescription We need access to your microphone to start recording Necesitamos acceso a tu micrófono para comenzar a grabar

TranslationKeys lists every available key. The full key list lives in src/i18n/translations.ts — there's a key for every visible string, including the permission flow recovery guide.

Mobile experience

mobileMode controls how the recorder behaves on mobile devices:

Value Behavior
"overlay" (default) A landing screen with "Allow Access". On tap, a fullscreen modal opens (via <Teleport>) with the same UI as desktop.
"embed" The recorder embeds inline, identical to desktop.
"native" Skips the SDK UI entirely and opens the device's native camera via a file input. Useful when WebCodecs isn't reliable on the user's browser.

The <VidtreoRecorder> component probes browser capabilities on mobile and falls back gracefully when WebCodecs isn't available.

Audio-only recording

Set audioOnly: true to record audio with the microphone only:

<template>
  <VidtreoRecorder :recorder-props="{ apiKey: 'your-api-key', audioOnly: true }" />
</template>
  • Audio recording must be enabled for the environment in the backend. The environment's audio settings (format, bitrate, max duration) apply, and the max duration is shown next to the timer (for example 00:12 / 10:00).
  • Only microphone permission is requested. The recorder renders as a compact voice-note pill (about 56px high, at most 20rem wide, light and dark aware): a red record/stop button, a live 18-bar waveform, the timer with the max duration (for example 00:12 / 10:00) and a microphone button that opens a menu. The menu lists microphones when idle and holds pause/resume and mute/unmute while recording. Status text, permission prompts, errors and the upload-complete message appear on a caption line below the pill, and upload progress runs along the pill; there is no video area. The camera selector, source switching and the tab visibility overlay are not used.
  • On mobile, mobileMode: "native" (and nativeCamera) is not used; the recorder falls back to "overlay".
  • upload-complete receives mediaType: "audio" and audioId.
  • Demo mode has no environment audio config, so audio-only recording is unavailable there.

If audio recording is disabled for the environment, starting the recorder fails with the error code recording.audio-disabled (ERROR_AUDIO_RECORDING_DISABLED in @vidtreo/recorder). The bar shows the audioRecordingDisabled message without a retry button, and error is emitted with the original error.

SSR (Nuxt, Astro-Vue, etc.)

Every browser API is gated to onMounted/if (typeof window !== "undefined"). If you're on Nuxt 3, the cleanest path is the @vidtreo/recorder-nuxt module — it registers the component as client-only and injects the CSS for you.

For other SSR setups, wrap the component in <ClientOnly> (Nuxt) or guard it behind a mount check in your framework's equivalent.

TypeScript

Every public surface is typed. The package also re-exports getUploadErrorCode and UPLOAD_ERROR_INSUFFICIENT_CREDITS from @vidtreo/recorder. Import types directly:

import type {
  AccessTokenProvider,
  RecordingUploadResult,
  UploadErrorCode,
  UploadProgressPhase,
  VidtreoRecorderProps,
  VidtreoRecorderState,
  VidtreoRecorderActions,
  UseVidtreoRecorderConfig,
  UseVidtreoRecorderReturn,
  PartialTranslations,
  TranslationKeys,
  MobileMode,
  AudioWarning,
  RecordingStopResult,
} from "@vidtreo/recorder-vue";

Package structure

What Where
Top-level component src/components/VidtreoRecorder.vue
Desktop / embed UI src/components/StandardRecorder.vue
Mobile overlay src/components/MobileWebRecorderUI.vue
Native camera src/components/NativeCameraUI.vue
Composables src/composables/
UI primitives src/components/ui/
i18n data src/i18n/translations.ts
Framework-agnostic helpers src/utils/, src/services/

The recording engine, transcoding worker, and upload pipeline live in @vidtreo/recorder.

License

MIT

Related Packages

@vidtreo/recorder-nuxt

Nuxt module for @vidtreo/recorder-vue - video recording SDK

1,469
@vt7/vue2-composables

Vue2 composables

523 1
@shopware/composables

Shopware Frontends composables for Vue

141,216 230
@tb-dev/vue

Vue utilities

12,617
vue-videobg

Video Background component for Vue.js

4,724 245

Version History

Version Released License
1.13.0 MIT
1.12.1 MIT
1.12.0 MIT
1.11.0 MIT
1.10.0 MIT