voxlink
v1.0.0
Published
A reusable npm package for real-time audio and video calling using WebRTC and Socket.IO.
Maintainers
Readme
VoxLink
VoxLink is a reusable npm package for real-time audio and video calling, built on WebRTC and Socket.IO. It is designed for modern React applications but supports vanilla JavaScript/TypeScript as well.
Features
- WebRTC-based peer-to-peer media streaming.
- Socket.IO signaling for connection management.
- React Hooks & Components for easy integration.
- TypeScript Support for full type safety.
- Modular & Configurable.
Installation
npm install voxlink socket.io-clientUsage
React Integration
VoxLink provides a useCall hook and pre-built components.
Important: Import the styles at the root of your application (e.g., App.tsx or index.tsx).
import 'voxlink/dist/styles.css'; import React, { useState } from 'react';
import { useCall, VideoCall, ControlBar, MuteButton, EndCallButton, CameraFlipButton } from 'voxlink';
import 'voxlink/dist/styles.css'; // Basic styling
const App = () => {
const [targetId, setTargetId] = useState('');
const {
localStream,
remoteStream,
status,
startCall,
endCall,
toggleMute,
toggleVideo,
isMuted,
isVideoEnabled
} = useCall('http://localhost:3000'); // Your Socket.IO server URL
return (
<div style={{ height: '100vh', width: '100vw' }}> {/* Container should have height */}
<VideoCall
localStream={localStream}
remoteStream={remoteStream}
className="my-video-call"
/>
<ControlBar>
{status === 'idle' ? (
<>
<input
type="text"
placeholder="Target ID"
value={targetId}
onChange={(e) => setTargetId(e.target.value)}
style={{ padding: '8px', borderRadius: '4px' }}
/>
<button onClick={() => startCall(targetId)}>Start</button>
</>
) : (
<>
<MuteButton isMuted={isMuted} toggleMute={toggleMute} />
<CameraFlipButton toggleVideo={toggleVideo} />
<EndCallButton endCall={endCall} />
</>
)}
</ControlBar>
</div>
);
};
export default App;Vanilla JS / TypeScript Usage
You can use the core VoxLinkClient directly.
import { VoxLinkClient } from 'voxlink';
const client = new VoxLinkClient({ serverUrl: 'http://localhost:3000' });
// Handle incoming streams
client.on('stream-added', (stream) => {
const videoElement = document.getElementById('remote-video') as HTMLVideoElement;
videoElement.srcObject = stream;
videoElement.play();
});
// Start a call
async function startCall(targetId: string) {
const localStream = await client.startLocalStream();
// Attach local stream to video element...
await client.call(targetId);
}API Reference
useCall(serverUrl: string, iceServers?: RTCIceServer[])
Returns an object with:
localStream:MediaStream | nullremoteStream:MediaStream | nullstatus:'idle' | 'calling' | 'connected' | 'ended'isMuted,isVideoEnabled,isScreenSharing:booleanstartCall(targetId: string): Function to initiate a call.endCall(): Function to end the call.toggleMute(): Toggle audio.toggleVideo(): Toggle video.
Components
<VideoCall />: Renders local and remote video. Props:localStream,remoteStream,localVideoStyle,remoteVideoStyle.<AudioCall />: Renders remote audio (if no video is needed).<MuteButton />,<CameraFlipButton />,<ScreenShareButton />,<EndCallButton />: Helper buttons.
Production Setup
To use VoxLink in production, you must handle configuration for different environments and ensuring connectivity via TURN servers.
1. Environment Configuration
Use environment variables to separate your development and production signaling servers.
Example (.env):
REACT_APP_SIGNALING_SERVER=https://api.myapp.comExample (App.tsx):
const SERVER_URL = process.env.REACT_APP_SIGNALING_SERVER || 'http://localhost:3000';
const App = () => {
const { startCall } = useCall(SERVER_URL);
// ...
};2. ICE Servers (STUN/TURN)
For production, relying on public STUN servers is not enough because many users are behind symmetric NATs or firewalls. You need TURN servers.
Recommended Setup:
// Define your ICE servers (e.g., from Twilio, Xirsys, or your own coturn instance)
const iceServers = [
{ urls: 'stun:stun.l.google.com:19302' }, // Public STUN
{
urls: 'turn:your-turn-server.com:3478',
username: 'user',
credential: 'password'
}
];
const App = () => {
// Pass iceServers as the second argument
const { startCall } = useCall(SERVER_URL, iceServers);
// ...
};Note: Ensure
iceServersis stable (defined outside component or memoized) to avoid reconnects on re-renders.
Requirements
- Uses Socket.IO server for signaling.
- Requires a TURN server for production usage over the internet (default uses public STUN).
