Video & Audio Rendering
Learn how to render video and audio streams in your application UI across all platforms
Overview
BaxCloud provides native video and audio rendering components across all platforms. The SDK handles participant management, track control, and provides easy-to-use rendering components for displaying video and audio in your application UI.
Important
Video Tracks
Render camera and screen share video streams with hardware acceleration
Audio Tracks
Audio plays automatically, with controls for muting and volume
Multi-Participant
Render multiple participants in grid, gallery, or custom layouts
Video Rendering
Render video streams across all platforms
BaxCloud provides native video rendering components across all platforms. Each platform has optimized components for high-performance video display with built-in participant management.
React applications use BaxCloud's React components for rendering. These provide high-performance video rendering with built-in optimizations and hooks for participant management.
Basic Video Rendering
1import { BaxCloudVideoRenderer, BaxCloudAudioRenderer, useBaxCloudParticipants } from '@baxcloud/react-sdk';
2
3function VideoCall() {
4 const participants = useBaxCloudParticipants();
5
6 return (
7 <div className="video-grid">
8 {participants.map(participant => (
9 <div key={participant.userId} className="video-tile">
10 {participant.cameraEnabled && (
11 <BaxCloudVideoRenderer
12 userId={participant.userId}
13 mirror={participant.isLocal}
14 style={{ width: '100%', height: '100%' }}
15 />
16 )}
17 {participant.microphoneEnabled && (
18 <BaxCloudAudioRenderer userId={participant.userId} />
19 )}
20
21 {/* Participant info */}
22 <div className="participant-info">
23 <span>{participant.name} {participant.isLocal && '(You)'}</span>
24 {participant.isSpeaking && <span className="speaking-indicator">🎤</span>}
25 </div>
26 </div>
27 ))}
28 </div>
29 );
30}Complete Multi-Participant Example
1import { useEffect, useState } from 'react';
2import {
3 BaxCloudVideoRenderer,
4 BaxCloudAudioRenderer,
5 useBaxCloudParticipants,
6 BaxCloudClient
7} from '@baxcloud/react-sdk';
8
9function VideoConference() {
10 const [client] = useState(() => new BaxCloudClient({
11 projectId: 'your-project-id',
12 apiKey: 'your-api-key',
13 }));
14
15 const participants = useBaxCloudParticipants();
16
17 useEffect(() => {
18 const connectToRoom = async () => {
19 await client.connect({
20 roomName: 'my-conference',
21 participant: {
22 userId: 'user-123',
23 name: 'John Doe',
24 isHost: true,
25 },
26 liveType: 'video_conference',
27 });
28
29 // Enable camera and microphone
30 await client.enableCamera();
31 await client.enableMicrophone();
32 };
33
34 connectToRoom();
35
36 return () => {
37 client.disconnect();
38 };
39 }, [client]);
40
41 const renderParticipant = (participant) => {
42 return (
43 <div
44 key={participant.userId}
45 className={`participant-tile ${participant.isLocal ? 'local' : 'remote'}`}
46 style={{
47 position: 'relative',
48 backgroundColor: '#1a1a1a',
49 borderRadius: '8px',
50 overflow: 'hidden',
51 aspectRatio: '16/9',
52 }}
53 >
54 {/* Video */}
55 {participant.cameraEnabled ? (
56 <BaxCloudVideoRenderer
57 userId={participant.userId}
58 mirror={participant.isLocal}
59 style={{
60 width: '100%',
61 height: '100%',
62 objectFit: 'cover'
63 }}
64 />
65 ) : (
66 // No video placeholder
67 <div style={{
68 position: 'absolute',
69 inset: 0,
70 display: 'flex',
71 alignItems: 'center',
72 justifyContent: 'center',
73 background: '#2a2a2a',
74 }}>
75 <div style={{
76 width: '80px',
77 height: '80px',
78 borderRadius: '50%',
79 background: '#3a3a3a',
80 display: 'flex',
81 alignItems: 'center',
82 justifyContent: 'center',
83 fontSize: '32px',
84 color: '#888',
85 }}>
86 {participant.name.charAt(0).toUpperCase()}
87 </div>
88 </div>
89 )}
90
91 {/* Audio */}
92 {participant.microphoneEnabled && (
93 <BaxCloudAudioRenderer userId={participant.userId} />
94 )}
95
96 {/* Participant info overlay */}
97 <div
98 style={{
99 position: 'absolute',
100 bottom: 0,
101 left: 0,
102 right: 0,
103 padding: '8px',
104 background: 'linear-gradient(transparent, rgba(0,0,0,0.7))',
105 }}
106 >
107 <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
108 <span style={{ color: 'white', fontSize: '14px', fontWeight: 500 }}>
109 {participant.name}
110 {participant.isLocal && ' (You)'}
111 </span>
112 {!participant.microphoneEnabled && (
113 <span style={{ color: '#ef4444' }}>🔇</span>
114 )}
115 {participant.isSpeaking && (
116 <span style={{ color: '#10b981' }}>🎤</span>
117 )}
118 </div>
119 </div>
120 </div>
121 );
122 };
123
124 return (
125 <div style={{ padding: '20px', height: '100vh', display: 'flex', flexDirection: 'column' }}>
126 <h1 style={{ marginBottom: '20px' }}>Video Conference</h1>
127
128 <div style={{
129 display: 'grid',
130 gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
131 gap: '16px',
132 flex: 1,
133 }}>
134 {participants.map((participant) => renderParticipant(participant))}
135 </div>
136
137 {/* Controls */}
138 <div style={{
139 marginTop: '20px',
140 display: 'flex',
141 gap: '12px',
142 justifyContent: 'center',
143 }}>
144 <button onClick={() => client.toggleCamera()}>
145 Toggle Camera
146 </button>
147 <button onClick={() => client.toggleMicrophone()}>
148 Toggle Mic
149 </button>
150 <button onClick={() => client.switchCamera()}>
151 Switch Camera
152 </button>
153 <button onClick={() => client.disconnect()}>
154 Leave
155 </button>
156 </div>
157 </div>
158 );
159}useBaxCloudParticipants() hook provides real-time participant data with state properties like cameraEnabled, microphoneEnabled, andisSpeaking. Use these to conditionally render video and show participant status.Audio Rendering
Audio tracks play automatically in all platforms. However, you can control muting, volume levels, and audio output device selection.
Audio Controls
1// Mute/unmute local microphone
2await client.muteMicrophone();
3await client.unmuteMicrophone();
4
5// Toggle microphone
6await client.toggleMicrophone();
7
8// Audio plays automatically through BaxCloudAudioRenderer
9// Volume control handled by system audio settingsmicrophoneEnabled and isSpeaking for UI updates.Best Practices
1. Always Clean Up Video Tracks on Unmount
Failing to properly clean up video renderers can cause memory leaks and prevent the camera from being released.
1useEffect(() => {
2 // Component mounted
3 return () => {
4 // Component unmounting - disconnect
5 client?.disconnect();
6 };
7}, [client]);2. Use Participant State Properties
BaxCloud provides participant state properties for reactive UI updates.
1// React example with participant state
2const participants = useBaxCloudParticipants();
3
4{participants.map(participant => (
5 <div key={participant.userId}>
6 {participant.cameraEnabled && (
7 <BaxCloudVideoRenderer userId={participant.userId} />
8 )}
9 {!participant.microphoneEnabled && <MutedIcon />}
10 {participant.isSpeaking && <SpeakingIndicator />}
11 </div>
12))}3. Optimize Video Display
Use appropriate object-fit values to prevent letterboxing and ensure video fills containers properly.
1// React: objectFit: 'cover'
2// React Native: use aspectRatio and flex
3// Flutter: fit: BoxFit.cover
4// iOS: mirror parameter on VideoView
5// Android: VideoView handles scaling automatically
6
7// This prevents letterboxing and ensures video fills the container4. Use Aspect Ratio to Prevent Stretching
Maintain proper aspect ratios (16:9 for landscape, 9:16 for portrait) to prevent distortion.
1// CSS (React)
2.video-container {
3 aspect-ratio: 16 / 9;
4 width: 100%;
5}
6
7// React Native
8aspectRatio: 16 / 9
9
10// Flutter
11aspectRatio: 16 / 95. Handle Screen Rotation (Mobile)
On mobile devices, properly handle orientation changes to reflow your video grid.
1// React Native
2import { Dimensions } from 'react-native';
3
4const [orientation, setOrientation] = useState('portrait');
5
6useEffect(() => {
7 const subscription = Dimensions.addEventListener('change', ({ window }) => {
8 setOrientation(window.width > window.height ? 'landscape' : 'portrait');
9 });
10 return () => subscription?.remove();
11}, []);
12
13// Adjust grid columns based on orientation
14const columns = orientation === 'landscape' ? 3 : 2;