A powerful React SDK for screen recording with camera and audio support. Beautiful, draggable UI with real-time audio feedback.
npm install recordpanelA powerful React SDK for screen recording with camera and audio support



Features • Installation • Quick Start • API Reference • Examples
---
RecordPanel is a feature-rich React SDK that enables screen recording with camera and audio capture capabilities. It provides a beautiful, draggable floating UI with real-time audio feedback, making it perfect for creating video tutorials, bug reports, or any application that requires screen recording functionality.
✨ Core Features
- 🎥 Screen Recording - Capture your entire screen or specific windows
- 📹 Camera Support - Include your webcam feed with circular preview (Loom-style)
- 🎤 Audio Capture - Record microphone and system audio simultaneously
- 🎨 Beautiful UI - Modern, draggable floating panel with smooth animations
- 📊 Audio Feedback - Real-time visual audio level indicators
- ⏸️ Pause/Resume - Control recording playback on the fly
- 🔄 Restart - Quickly restart recordings without re-requesting permissions
- ⏱️ Duration Display - Real-time recording duration in MM:SS format
- 🎯 Simple API - One-line capture() method for quick integration
🎨 UI Features
- Draggable floating panel (drag anywhere except buttons)
- Circular camera preview (120px, Loom-style)
- Compact, modern design
- Real-time audio level visualization
- Recording indicator with pulsing red dot
- Configurable theme (light, dark, auto)
- Customizable stop button text
🔧 Technical Features
- TypeScript support with full type definitions
- Tree-shakeable (only imports what you use)
- Zero CSS conflicts (scoped styles)
- Browser permission management
- Automatic codec fallback (VP9 → VP8 → MP4)
- Memory-efficient blob handling
- Pause/resume duration tracking
``bash`
npm install recordpanel
or
`bash`
yarn add recordpanel
or
`bash`
pnpm add recordpanel
RecordPanel requires React 18+ or React 19+:
`bash`
npm install react react-dom
Wrap your application with RecordPanelHost at the root level:
`jsx
import { RecordPanelHost } from 'recordpanel'
import 'recordpanel/styles'
function App() {
return (
)
}
`
Use the useRecordPanel hook in any component:
`jsx
import { useRecordPanel } from 'recordpanel'
function MyComponent() {
const recorder = useRecordPanel()
const handleRecord = async () => {
// Simple one-line API
const result = await recorder.capture({
cameraEnabled: true,
audioEnabled: true
})
console.log('Recording:', result)
// result contains: { blob, url, mimeType, size }
}
return
}
`
`jsx
import { useState } from 'react'
import { RecordPanelHost, useRecordPanel } from 'recordpanel'
import 'recordpanel/styles'
function RecordingComponent() {
const [recording, setRecording] = useState(null)
const recorder = useRecordPanel()
const handleCapture = async () => {
try {
const result = await recorder.capture({
cameraEnabled: true,
audioEnabled: true
})
setRecording(result)
// Download the recording
const a = document.createElement('a')
a.href = result.url
a.download = recording-${Date.now()}.webm
a.click()
// Clean up
URL.revokeObjectURL(result.url)
} catch (error) {
console.error('Recording failed:', error)
}
}
return (
function App() {
return (
)
}
`
The root component that provides the recording context to your app.
#### Props
`typescript`
interface RecordPanelHostProps {
children: ReactNode
config?: RecorderConfig
}
#### Configuration
`typescript`
interface RecorderConfig {
theme?: 'light' | 'dark' | 'auto' // Default: 'auto'
stopButtonText?: string // Default: 'Send'
}
Example:
`jsx`
theme: 'dark',
stopButtonText: 'Finish'
}}
>
Returns the recorder API object. Must be used within a component wrapped by RecordPanelHost.
`typescript`
const recorder = useRecordPanel()
#### recorder.capture(options?)
The simplest way to record. Starts recording, shows UI, waits for user to stop, and returns the result.
`typescript
const result = await recorder.capture({
cameraEnabled?: boolean // Default: true
audioEnabled?: boolean // Default: true
})
// Returns: RecordingResult
`
Example:
`jsx`
const handleCapture = async () => {
try {
const result = await recorder.capture({
cameraEnabled: true,
audioEnabled: true
})
console.log('Recording complete:', result)
} catch (error) {
console.error('Capture failed:', error)
}
}
#### recorder.start(options?)
Starts recording. Requests permissions if not already granted.
`typescript`
await recorder.start({
cameraEnabled?: boolean // Default: true
audioEnabled?: boolean // Default: true
})
#### recorder.stop()
Stops recording and returns the result.
`typescript`
const result = await recorder.stop()
// Returns: RecordingResult | null
#### recorder.pause()
Pauses the current recording.
`typescript`
recorder.pause()
#### recorder.resume()
Resumes a paused recording.
`typescript`
recorder.resume()
#### recorder.restart()
Stops the current recording and starts a new one. Preserves permissions if already granted.
`typescript`
await recorder.restart()
#### recorder.show()
Shows the recorder UI overlay.
`typescript`
recorder.show()
#### recorder.hide()
Hides the recorder UI overlay.
`typescript`
recorder.hide()
#### recorder.setConfig(config)
Updates the recorder configuration dynamically.
`typescript`
recorder.setConfig({
theme: 'dark',
stopButtonText: 'Finish'
})
#### recorder.getState()
Returns the current recording state.
`typescript`
const state = recorder.getState()
// Returns: 'idle' | 'requesting' | 'recording' | 'paused' | 'stopped'
#### recorder.isRecording()
Checks if currently recording.
`typescript`
const isRecording = recorder.isRecording() // boolean
#### recorder.isPaused()
Checks if recording is paused.
`typescript`
const isPaused = recorder.isPaused() // boolean
#### recorder.isVisible()
Checks if the UI overlay is visible.
`typescript`
const isVisible = recorder.isVisible() // boolean
#### recorder.getRecordingDuration()
Gets the current recording duration in seconds (includes pause time handling).
`typescript`
const duration = recorder.getRecordingDuration() // number (seconds)
#### RecordingResult
`typescript`
interface RecordingResult {
blob: Blob // The recording blob
url: string // Object URL (revoke after use)
mimeType: string // e.g., 'video/webm' or 'video/mp4'
size: number // Size in bytes
}
#### RecorderState
`typescript`
type RecorderState = 'idle' | 'requesting' | 'recording' | 'paused' | 'stopped'
#### RecorderConfig
`typescript`
interface RecorderConfig {
theme?: 'light' | 'dark' | 'auto'
stopButtonText?: string
}
`jsx
function SimpleRecording() {
const recorder = useRecordPanel()
const handleRecord = async () => {
const result = await recorder.capture()
console.log('Recording:', result)
}
return
}
`
`jsx
function AdvancedRecording() {
const recorder = useRecordPanel()
const [isRecording, setIsRecording] = useState(false)
const handleStart = async () => {
await recorder.start({
cameraEnabled: true,
audioEnabled: true
})
setIsRecording(true)
}
const handleStop = async () => {
const result = await recorder.stop()
if (result) {
console.log('Recording:', result)
setIsRecording(false)
}
}
const handlePause = () => {
recorder.pause()
}
const handleResume = () => {
recorder.resume()
}
return (
$3
`jsx
function RecordingWithState() {
const recorder = useRecordPanel()
const [recording, setRecording] = useState(null)
const [duration, setDuration] = useState(0) useEffect(() => {
if (recorder.isRecording()) {
const interval = setInterval(() => {
setDuration(recorder.getRecordingDuration())
}, 1000)
return () => clearInterval(interval)
}
}, [recorder.isRecording()])
const handleCapture = async () => {
const result = await recorder.capture()
setRecording(result)
}
return (
{recorder.isRecording() && (
Recording: {Math.floor(duration / 60)}:{(duration % 60).toFixed(0).padStart(2, '0')}
)}
{recording && (
)}
)
}
`$3
`jsx
function ThemedApp() {
return (
config={{
theme: 'dark',
stopButtonText: 'Finish Recording'
}}
>
)
}
`UI Features
The RecordPanel UI provides a comprehensive set of controls:
$3
- Draggable - Click and drag anywhere on the panel (except buttons) to reposition
- Compact Design - Small footprint, doesn't obstruct your screen
- Smooth Animations - Slide-in animation when appearing
$3
- Circular Design - 120px circular preview (Loom-style)
- Positioned Above Controls - Appears above the control bar when enabled
- Recording Indicator - Red pulsing dot in the top-right corner
- Audio Feedback - Visual audio level bar at the bottom
$3
- Duration Display - Shows recording time in MM:SS format
- Audio Meter - Real-time audio level visualization (5 bars)
- Camera Toggle - Enable/disable camera feed
- Audio Toggle - Enable/disable microphone
- Pause/Resume - Control recording playback
- Restart - Restart recording (preserves permissions)
- Stop/Send - Stop recording and get result (configurable text)
- Close - Hide the UI overlay
Styling & Customization
$3
RecordPanel uses CSS variables that you can customize:
`css
:root {
--recordpanel-primary: 221 83 53;
--recordpanel-primary-foreground: 0 0 100;
--recordpanel-border: 214 218 222;
--recordpanel-muted: 248 249 250;
/ ... more variables /
}
`$3
`jsx
config={{
theme: 'auto', // 'light' | 'dark' | 'auto'
stopButtonText: 'Send'
}}
>
`The
auto theme automatically follows the system preference.$3
All RecordPanel styles are scoped with the
.recordpanel-* prefix to avoid conflicts. You can override styles if needed:`css
.recordpanel-overlay {
/ Your custom styles /
}
`Browser Support
RecordPanel works in all modern browsers that support:
- MediaRecorder API - Chrome 47+, Firefox 25+, Safari 14.1+, Edge 79+
- getDisplayMedia - Chrome 72+, Firefox 66+, Safari 13+, Edge 79+
- getUserMedia - Chrome 53+, Firefox 36+, Safari 11+, Edge 12+
$3
System audio capture is supported in:
- ✅ Chrome/Edge (Windows, macOS, Linux)
- ❌ Firefox (not supported)
- ❌ Safari (not supported)
$3
For the best experience, use:
- Chrome/Edge (full feature support)
- Firefox (screen + microphone only)
- Safari (screen + microphone only)
TypeScript Support
RecordPanel is written in TypeScript and provides full type definitions:
`typescript
import {
RecordPanelHost,
useRecordPanel,
type RecordingResult,
type RecorderConfig,
type RecorderState
} from 'recordpanel'
`Troubleshooting
$3
If permissions aren't being requested, ensure:
- You're using HTTPS (or localhost)
- The browser supports the required APIs
- No browser extensions are blocking permissions
$3
If recordings are shorter than expected:
- Check browser console for errors
- Ensure sufficient disk space
- Check if browser is closing the MediaRecorder
$3
- Verify microphone permissions are granted
- Check browser audio settings
- System audio requires Chrome/Edge on desktop
$3
- Ensure
RecordPanelHost wraps your app
- Check that recorder.show() is called
- Verify CSS is imported: import 'recordpanel/styles'$3
Always revoke object URLs after use:
`jsx
const result = await recorder.capture()
// Use result.url
URL.revokeObjectURL(result.url) // Important!
`Development
$3
`bash
npm run build:lib
`This creates a library build in the
dist folder.$3
`bash
npm run dev
`$3
`
src/
recordpanel/
├── index.ts # Main exports
├── RecorderHost.tsx # Host component
├── RecorderContext.tsx # Context & hook
├── RecorderUI.tsx # UI component
├── recorder.ts # Core recording logic
└── styles.css # Scoped styles
`Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (
git checkout -b feature/amazing-feature)
3. Commit your changes (git commit -m 'Add some amazing feature')
4. Push to the branch (git push origin feature/amazing-feature`)MIT License - see LICENSE file for details.
- Built with React
- Icons from Lucide React
- UI components inspired by shadcn/ui
---
Made with ❤️ by GeekyAnts