Video Conferencing
Create multi-party video collaboration spaces with screen sharing, recording, and more.
Creating a Conference Room
Basic Room
const room = await userDialer.conference.create({
name: 'Web3 Team Standup',
maxParticipants: 10,
video: true,
audio: true
});
console.log('Room ID:', room.id);
console.log('Join URL:', room.url);With Options
const room = await userDialer.conference.create({
name: 'Product Demo',
maxParticipants: 50,
video: true,
audio: true,
settings: {
recordingEnabled: true,
screenShareEnabled: true,
chatEnabled: true, // Enable in-room messaging
waitingRoom: true,
muteOnJoin: false,
videoQuality: '1080p'
}
});Room Object
interface ConferenceRoom {
id: string;
name: string;
host: string; // Wallet address
participants: Participant[];
maxParticipants: number;
createdAt: Date;
url: string;
status: 'waiting' | 'active' | 'ended';
recording?: {
isRecording: boolean;
startedAt?: Date;
url?: string;
};
}Joining a Room
By Room ID
await userDialer.conference.join({
roomId: room.id,
video: true,
audio: true,
displayName: 'Alice.eth'
});By URL
await userDialer.conference.joinByUrl({
url: 'https://dial.wtf/rooms/abc123',
video: true,
audio: true
});Participants
Participant Object
interface Participant {
id: string;
walletAddress: string;
displayName: string;
isHost: boolean;
isMuted: boolean;
isVideoEnabled: boolean;
isScreenSharing: boolean;
joinedAt: Date;
}Get Participants
const participants = await userDialer.conference.getParticipants(roomId);
console.log(`${participants.length} participants in room`);Listen for Participant Events
userDialer.on('conference:participant:joined', (participant) => {
console.log(`${participant.displayName} joined`);
});
userDialer.on('conference:participant:left', (participant) => {
console.log(`${participant.displayName} left`);
});Media Controls
Audio Controls
// Mute yourself
await userDialer.conference.muteAudio(roomId);
// Unmute yourself
await userDialer.conference.unmuteAudio(roomId);
// Mute specific participant (host only)
await userDialer.conference.muteParticipant(roomId, participantId);
// Mute all participants (host only)
await userDialer.conference.muteAll(roomId);Video Controls
// Disable your video
await userDialer.conference.disableVideo(roomId);
// Enable your video
await userDialer.conference.enableVideo(roomId);
// Request participant to enable video
await userDialer.conference.requestVideo(roomId, participantId);Screen Sharing
Start Screen Share
const screenShare = await userDialer.conference.startScreenShare(roomId);
console.log('Screen share started');Stop Screen Share
await userDialer.conference.stopScreenShare(roomId);Listen for Screen Share
userDialer.on('conference:screenshare:started', ({ participantId }) => {
console.log(`${participantId} started screen sharing`);
});
userDialer.on('conference:screenshare:stopped', ({ participantId }) => {
console.log(`${participantId} stopped screen sharing`);
});Recording
Start Recording
const recording = await userDialer.conference.startRecording(roomId);
console.log('Recording started:', recording.id);Stop Recording
const recordedFile = await userDialer.conference.stopRecording(roomId);
console.log('Recording URL:', recordedFile.url);
console.log('Duration:', recordedFile.duration);Get Recordings
const recordings = await userDialer.conference.getRecordings(roomId);
recordings.forEach(rec => {
console.log(`Recording: ${rec.url}`);
console.log(`Duration: ${rec.duration}s`);
console.log(`Size: ${rec.size}MB`);
});In-Room Messaging
Party Line Messaging - Real-time ephemeral messaging within active video conference rooms.
In-room messaging is designed for party lines and video conferencing, providing real-time chat that exists only during the conference session. These messages are not persisted after the room ends.
Send Message
await userDialer.conference.sendMessage(roomId, {
content: 'Hello everyone!',
type: 'text'
});
// Send with mentions
await userDialer.conference.sendMessage(roomId, {
content: '@alice Great point!',
type: 'text',
mentions: ['0xAlice...']
});
// Share media in room
await userDialer.conference.sendMessage(roomId, {
type: 'image',
media: {
file: imageFile,
caption: 'Check this out'
}
});Receive Messages
userDialer.on('conference:message', ({ roomId, message, sender }) => {
console.log(`[${roomId}] ${sender.displayName}: ${message.content}`);
// Display with sender's profile
console.log('Avatar:', sender.avatar);
console.log('Wallet:', sender.walletAddress);
});Message Types
In-room messaging supports:
- Text messages - Plain text and formatted messages
- Emojis and reactions - React to messages and video
- Links - Share URLs with automatic preview
- Media - Share images and GIFs
- Mentions - Tag participants with @mentions
Note: In-room messages are ephemeral and only available during the active conference session. For persistent messaging, use Bucket Messaging or Matrix Messaging.
Layout Management
Set Layout
// Grid view (default)
await userDialer.conference.setLayout(roomId, 'grid');
// Speaker view (focus on active speaker)
await userDialer.conference.setLayout(roomId, 'speaker');
// Spotlight view (focus on specific participant)
await userDialer.conference.setLayout(roomId, 'spotlight', {
spotlightParticipantId: participantId
});Room Management
End Room (Host Only)
await userDialer.conference.end(roomId);Remove Participant (Host Only)
await userDialer.conference.removeParticipant(roomId, participantId);Transfer Host
await userDialer.conference.transferHost(roomId, newHostParticipantId);Advanced Features
Breakout Rooms
// Create breakout rooms
const breakoutRooms = await userDialer.conference.createBreakoutRooms(roomId, {
numberOfRooms: 3,
autoAssign: true // or manually assign participants
});
// Move participant to breakout room
await userDialer.conference.moveToBreakout(roomId, participantId, breakoutRooms[0].id);
// Close all breakout rooms
await userDialer.conference.closeBreakoutRooms(roomId);Polls
// Create poll
const poll = await userDialer.conference.createPoll(roomId, {
question: 'Should we launch next week?',
options: ['Yes', 'No', 'Need more time'],
duration: 60 // seconds
});
// Vote
await userDialer.conference.vote(roomId, poll.id, optionIndex);
// Get results
const results = await userDialer.conference.getPollResults(roomId, poll.id);Raise Hand
// Raise hand
await userDialer.conference.raiseHand(roomId);
// Lower hand
await userDialer.conference.lowerHand(roomId);
// Listen for raised hands
userDialer.on('conference:hand:raised', ({ participantId }) => {
console.log(`${participantId} raised their hand`);
});Complete Example: React Conference Component
import { useState, useEffect } from 'react';
import { DialClient, ConferenceRoom, Participant } from '@dial/sdk';
export function VideoConference({ dial, roomId }) {
const [room, setRoom] = useState<ConferenceRoom | null>(null);
const [participants, setParticipants] = useState<Participant[]>([]);
const [isMuted, setIsMuted] = useState(false);
const [isVideoEnabled, setIsVideoEnabled] = useState(true);
const [isScreenSharing, setIsScreenSharing] = useState(false);
useEffect(() => {
joinRoom();
setupEventListeners();
return () => {
leaveRoom();
};
}, [roomId]);
const joinRoom = async () => {
const joinedRoom = await userDialer.conference.join({
roomId,
video: true,
audio: true,
displayName: 'Alice.eth'
});
setRoom(joinedRoom);
setParticipants(joinedRoom.participants);
};
const setupEventListeners = () => {
userDialer.on('conference:participant:joined', (participant) => {
setParticipants(prev => [...prev, participant]);
});
userDialer.on('conference:participant:left', (participant) => {
setParticipants(prev =>
prev.filter(p => p.id !== participant.id)
);
});
};
const leaveRoom = async () => {
if (room) {
await userDialer.conference.leave(room.id);
}
};
const toggleMute = async () => {
if (isMuted) {
await userDialer.conference.unmuteAudio(roomId);
} else {
await userDialer.conference.muteAudio(roomId);
}
setIsMuted(!isMuted);
};
const toggleVideo = async () => {
if (isVideoEnabled) {
await userDialer.conference.disableVideo(roomId);
} else {
await userDialer.conference.enableVideo(roomId);
}
setIsVideoEnabled(!isVideoEnabled);
};
const toggleScreenShare = async () => {
if (isScreenSharing) {
await userDialer.conference.stopScreenShare(roomId);
} else {
await userDialer.conference.startScreenShare(roomId);
}
setIsScreenSharing(!isScreenSharing);
};
return (
<div className="conference">
<div className="participants-grid">
{participants.map(participant => (
<div key={participant.id} className="participant">
<video
ref={(el) => {
if (el) {
const stream = userDialer.conference.getParticipantStream(
roomId,
participant.id
);
el.srcObject = stream;
}
}}
autoPlay
playsInline
/>
<div className="participant-info">
<span>{participant.displayName}</span>
{participant.isMuted && <span>🔇</span>}
</div>
</div>
))}
</div>
<div className="controls">
<button onClick={toggleMute}>
{isMuted ? '🔇 Unmute' : '🔊 Mute'}
</button>
<button onClick={toggleVideo}>
{isVideoEnabled ? '📹 Disable Video' : '🚫 Enable Video'}
</button>
<button onClick={toggleScreenShare}>
{isScreenSharing ? '⏹️ Stop Share' : '🖥️ Share Screen'}
</button>
<button onClick={leaveRoom} className="danger">
📞 Leave
</button>
</div>
</div>
);
}Quality Settings
// Set video quality
await userDialer.conference.setVideoQuality(roomId, {
resolution: '720p', // '360p', '480p', '720p', '1080p'
frameRate: 30,
bitrate: 1500 // kbps
});
// Enable/disable adaptive quality
await userDialer.conference.setAdaptiveQuality(roomId, true);Analytics
// Get room statistics
const stats = await userDialer.conference.getStats(roomId);
console.log('Total duration:', stats.duration);
console.log('Peak participants:', stats.peakParticipants);
console.log('Total messages:', stats.messageCount);
console.log('Network quality:', stats.networkQuality);Next Steps
Last updated on