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/recorderBasic 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
- API Reference — Complete API documentation
- Types Reference — All TypeScript types
- Custom UI Example — Build custom interfaces