Vidtreo

Vanilla JavaScript

Build custom video recording experiences with the core VIDTREO SDK.

Vanilla JavaScript

The @vidtreo/recorder package provides the core SDK for building fully custom video recording experiences.

Installation

npm install @vidtreo/recorder

Basic Usage

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

// Initialize the recorder
const recorder = new VidtreoRecorder({
  apiKey: 'your-api-key',
  onUploadComplete: (result) => {
    console.log('Video URL:', result.uploadUrl);
  },
  onError: (error) => {
    console.error('Error:', error);
  }
});

// Initialize and start preview
await recorder.initialize();
const stream = await recorder.startPreview();

// Attach to video element
const video = document.querySelector('video');
video.srcObject = stream;

// Start recording
await recorder.startRecording();

// Stop and upload
const result = await recorder.stopRecording();
console.log('Recording complete:', result);

Configuration Options

interface VidtreoRecorderConfig {
  // Required
  apiKey: string;

  // Optional
  apiUrl?: string;                        // Default: 'https://core.vidtreo.com'
  enableSourceSwitching?: boolean;        // Default: true
  enableMute?: boolean;                   // Default: true
  enablePause?: boolean;                  // Default: true
  enableDeviceChange?: boolean;           // Default: true
  maxRecordingTime?: number;              // Max duration in ms
  countdownDuration?: number;             // Pre-recording countdown in ms
  userMetadata?: Record<string, unknown>; // Custom metadata
  enableTabVisibilityOverlay?: boolean;   // Show overlay when tab hidden
  tabVisibilityOverlayText?: string;      // Custom overlay text

  // Callbacks
  onUploadComplete?: (result: UploadResult) => void;
  onUploadProgress?: (progress: number) => void;
  onUploadError?: (error: Error) => void;
  onRecordingStart?: () => void;
  onRecordingStop?: () => void;
  onError?: (error: Error) => void;
}

Core Methods

Initialization

// Initialize the recorder
await recorder.initialize();

Preview

// Start camera preview
const stream = await recorder.startPreview('camera');

// Start screen preview
const stream = await recorder.startPreview('screen');

Recording

// Start recording with options
await recorder.startRecording({
  video: {
    width: 1920,
    height: 1080,
    frameRate: 30
  },
  audio: true
}, 'camera'); // or 'screen'

// Stop recording
const result = await recorder.stopRecording();
// result: { recordingId, uploadUrl, blob }

Audio Control

// Mute audio
recorder.muteAudio();

// Unmute audio
recorder.unmuteAudio();

// Toggle mute
recorder.toggleMute();

// Check mute status
const isMuted = recorder.isMuted();

Pause/Resume

// Pause recording
recorder.pauseRecording();

// Resume recording
recorder.resumeRecording();

// Check pause status
const isPaused = recorder.isPaused();

Source Switching

// Switch to screen recording
await recorder.switchSource('screen');

// Switch back to camera
await recorder.switchSource('camera');

Device Management

// Get available devices
const devices = await recorder.getAvailableDevices();
// devices: { video: MediaDeviceInfo[], audio: MediaDeviceInfo[] }

State

// Get current recording state
const state = recorder.getRecordingState();
// state: 'idle' | 'countdown' | 'recording'

// Get current stream
const stream = recorder.getStream();

Cleanup

// Clean up resources
recorder.cleanup();

Complete Example

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

class VideoRecorderApp {
  private recorder: VidtreoRecorder;
  private videoElement: HTMLVideoElement;
  private recordButton: HTMLButtonElement;
  private stopButton: HTMLButtonElement;
  private muteButton: HTMLButtonElement;

  constructor() {
    this.videoElement = document.getElementById('preview') as HTMLVideoElement;
    this.recordButton = document.getElementById('record') as HTMLButtonElement;
    this.stopButton = document.getElementById('stop') as HTMLButtonElement;
    this.muteButton = document.getElementById('mute') as HTMLButtonElement;

    this.recorder = new VidtreoRecorder({
      apiKey: 'your-api-key',
      maxRecordingTime: 300000, // 5 minutes
      countdownDuration: 3000,
      userMetadata: {
        userId: 'user-123'
      },
      onRecordingStart: () => {
        this.updateUI('recording');
      },
      onRecordingStop: () => {
        this.updateUI('processing');
      },
      onUploadProgress: (progress) => {
        this.showProgress(progress);
      },
      onUploadComplete: (result) => {
        this.showResult(result);
      },
      onError: (error) => {
        this.showError(error);
      }
    });

    this.bindEvents();
    this.init();
  }

  async init() {
    await this.recorder.initialize();
    const stream = await this.recorder.startPreview();
    this.videoElement.srcObject = stream;
    this.updateUI('ready');
  }

  bindEvents() {
    this.recordButton.addEventListener('click', () => this.startRecording());
    this.stopButton.addEventListener('click', () => this.stopRecording());
    this.muteButton.addEventListener('click', () => this.toggleMute());
  }

  async startRecording() {
    await this.recorder.startRecording();
  }

  async stopRecording() {
    await this.recorder.stopRecording();
  }

  toggleMute() {
    this.recorder.toggleMute();
    this.muteButton.textContent = this.recorder.isMuted() ? 'Unmute' : 'Mute';
  }

  updateUI(state: string) {
    // Update UI based on state
    this.recordButton.disabled = state !== 'ready';
    this.stopButton.disabled = state !== 'recording';
  }

  showProgress(progress: number) {
    console.log(`Upload: ${Math.round(progress * 100)}%`);
  }

  showResult(result: { uploadUrl: string; recordingId: string }) {
    console.log('Video ready:', result.uploadUrl);
  }

  showError(error: Error) {
    console.error('Error:', error);
  }
}

// Initialize when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
  new VideoRecorderApp();
});

HTML Template

<!DOCTYPE html>
<html>
<head>
  <title>Video Recorder</title>
  <style>
    .recorder {
      max-width: 640px;
      margin: 0 auto;
    }
    video {
      width: 100%;
      background: #000;
      border-radius: 8px;
    }
    .controls {
      margin-top: 1rem;
      display: flex;
      gap: 0.5rem;
    }
    button {
      padding: 0.5rem 1rem;
      border-radius: 4px;
      border: none;
      cursor: pointer;
    }
    button:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
  </style>
</head>
<body>
  <div class="recorder">
    <video id="preview" autoplay muted playsinline></video>
    <div class="controls">
      <button id="record">Record</button>
      <button id="stop" disabled>Stop</button>
      <button id="mute">Mute</button>
    </div>
  </div>

  <script type="module" src="./recorder.ts"></script>
</body>
</html>

Advanced: Using Individual Modules

For maximum control, import individual modules:

import {
  RecorderController,
  DeviceManager,
  AudioLevelAnalyzer,
  UploadService,
  StorageManager,
  VideoTranscoder
} from '@vidtreo/recorder';

// Device management
const deviceManager = new DeviceManager();
const devices = await deviceManager.enumerateDevices();

// Audio visualization
const analyzer = new AudioLevelAnalyzer(audioTrack);
analyzer.start((level) => {
  // level: 0-1
  updateAudioMeter(level);
});

// Manual transcoding
const transcoder = new VideoTranscoder();
const mp4Blob = await transcoder.transcode(webmBlob, {
  format: 'mp4',
  fps: 30,
  width: 1920,
  height: 1080
});

// Custom upload
const uploadService = new UploadService({
  apiKey: 'your-api-key',
  apiUrl: 'https://core.vidtreo.com'
});
const result = await uploadService.upload(mp4Blob, {
  onProgress: (progress) => console.log(progress)
});

Type Definitions

// Recording states
type RecordingState = 'idle' | 'countdown' | 'recording';
type SourceType = 'camera' | 'screen';

// Recording result
interface RecordingStopResult {
  recordingId: string;
  uploadUrl: string;
  blob: Blob;
}

// Device info
interface AvailableDevices {
  video: MediaDeviceInfo[];
  audio: MediaDeviceInfo[];
}

// Recording options
interface RecordingStartOptions {
  video?: {
    width?: number;
    height?: number;
    frameRate?: number;
  };
  audio?: boolean | MediaTrackConstraints;
}

The core SDK is the foundation for both the React and Web Component packages. All features available in the wrapper packages are built on these APIs.

Next Steps

On this page