VOIP/Video Consultations
VoipConfig Object
interface VoipConfig {
id?: number;
consultation_id?: number;
api_key?: string;
call_id?: string;
token?: string;
created_at?: string;
updated_at?: string;
}
For
VOIPconsultation the config data will be invoipConfigand forVIDEOwill be invideoConfig, but they share the same data structure so we use one interface for both:VoipConfig.
VOIP and Video consultations are rendered and handled the same way.
The difference is to enable the video on Video consultations and disable it for VOIP consultations.
On web, video/VOIP calling is powered by @opentok/client (OpenTok.js) instead of native OpenTok, but the component names and props are unchanged from the React Native SDK.
VOIP/Video Components
These are the components available to handle these consultations:
TBIPublisher
TBISession
TBISubscriber
TBISubscriberView
VOIP/Video Example
Check the below code example of using our ready-to-use components to handle VOIP/Video consultations:
import React, { useState } from 'react';
import {
TBIPublisher,
TBISession,
TBISubscriber,
TBISubscriberView,
} from 'react-web-altibbi';
const Video = ({ data, voip }: { data: any; voip: boolean }) => {
const [audio, setAudio] = useState<boolean>(true);
const [video, setVideo] = useState<boolean>(!voip);
const [camera, setCamera] = useState<'front' | 'back'>('front');
const toggleVideo = () => setVideo((prev) => !prev);
const toggleAudio = () => setAudio((prev) => !prev);
const switchCamera = () =>
setCamera((prev) => (prev === 'front' ? 'back' : 'front'));
const renderSubscribers = (subscriberIds: string[]) => {
if (subscriberIds && subscriberIds.length > 0) {
return subscriberIds.map((streamId) => (
<TBISubscriberView
key={streamId}
streamId={streamId}
style={{ width: '100%', height: '100%' }}
/>
));
}
};
return (
<TBISession
apiKey={data.api_key}
sessionId={data.call_id}
token={data.token}
eventHandlers={{
sessionDisconnected: (event) => {},
streamDestroyed: (event) => {},
error: (event) => {},
}}
>
<TBISubscriber
eventHandlers={{
error: (event) => {},
}}
>
{renderSubscribers}
</TBISubscriber>
<TBIPublisher
style={{
position: 'absolute',
width: 100,
height: 100,
top: 0,
margin: 5,
right: 0,
}}
properties={{
cameraPosition: camera,
publishVideo: video,
publishAudio: audio,
enableDtx: true,
}}
eventHandlers={{
streamDestroyed: (event) => {},
error: (event) => {},
}}
/>
<div
style={{
display: 'flex',
flexDirection: 'row',
padding: 8,
position: 'absolute',
backgroundColor: 'white',
bottom: 0,
left: 0,
right: 0,
justifyContent: 'center',
}}
>
<span
style={{
fontSize: 20,
marginRight: 10,
color: video ? 'blue' : 'red',
cursor: 'pointer',
}}
onClick={toggleVideo}
>
{`Video ${video ? 'On' : 'Off'}`}
</span>
<span
style={{
fontSize: 20,
marginRight: 10,
color: audio ? 'blue' : 'red',
cursor: 'pointer',
}}
onClick={toggleAudio}
>
{`Audio ${audio ? 'On' : 'Off'}`}
</span>
<span
style={{ fontSize: 20, marginRight: 10, cursor: 'pointer' }}
onClick={switchCamera}
>
camera ({camera})
</span>
</div>
</TBISession>
);
};
export default Video;
The browser will prompt the user for camera/microphone permission the first time
TBIPublisherinitializes — make sure your app is served over HTTPS (orlocalhost) sincegetUserMediarequires a secure context.