RealTimeX
Sign inStart for free
RealTimeXWeb Package
IntroductionPrerequisitesInstallationProject setupQuick start
Package structureConfigurationComponentsHooksAPI integrationSocket events
OverviewReplace entire UIReplace componentsStyle with classNamesThemes & localePhone & video callingIn-call control barFeatures
Unread badgeRich-text messagesPins, stars & datesMessage threadsMentionsCanvas & draftsNotificationsAdmin permissionsServer refusalsSession & token refresh
Host app integrationTroubleshootingFAQVersion historyBest practicesSupport & contact
Web packageCustomization

Phone & video calling

A complete audio/video calling system built on VideoSDK - ready with zero extra props.

Overview

Call buttons appear in the chat header for DMs and groups. The package ships a complete, ready-to-use calling system built on VideoSDK - it works the moment your backend's calling routes are live (the /calls/* REST and call_* socket contract). No VideoSDK API keys are ever in the frontend; your backend signs short-lived join tokens.

What “built-in” gets you

Pressing the phone/video button calls the package's own useCallStore().startCall(…) - no features.onPhoneCall needed. You get:

  • Ringing UI on both sides (IncomingCallDialog), busy detection, and missed / declined / cancelled call messages in the chat timeline.
  • A full in-call surface (CallOverlay): mic, camera, leave, screen share, pin a tile, grid/speaker layout for groups, emoji reactions, raise hand, in-call chat and a participants panel.
  • One presenter at a time. While someone shares, others see Ask to share your screen; the presenter gets a toast with Stop sharing. The host gets Take over screen share instead.
  • Cloud recording - host-only start/stop, a live “● REC” badge for everyone and a download link once processed. Gated by callRecordingEnabled. It follows the call's live mode, so an audio call switched to video records as video.
  • Transcripts - when the backend produces one, the recording gets a transcript (status in the Recordings drawer and preview). Gated by callTranscriptionEnabled; there's no separate start button.
  • Join an ongoing call - a banner with Join in the chat header while a group call runs, and live calls in the Calls drawer (GET /calls/active, POST /calls/:callId/join).
  • Calls & Recordings drawers - history and recordings per chat, from the header options menu (CallsDrawer / RecordingsDrawer slots).
  • Collaborative whiteboard - a shared drawing board; “Share PDF to chat” uploads its export as an attachment. Gated by whiteboardEnabled.
  • The call pops into its own browser window when possible (falls back to the panel if the popup is blocked), so it keeps running while the user browses elsewhere.

Restyle, hide or replace any in-call control with features.callControls - see In-call control bar.

Requirement: @videosdk.live/react-sdk

Calling needs @videosdk.live/react-sdk pinned to ^0.13.3. It's already bundled, so npm/yarn hosts need nothing extra. pnpm + Vite hosts list "@realtimexsco/live-chat > @videosdk.live/react-sdk" in optimizeDeps.include (see Project setup).

Warning

Never let a lockfile pull @videosdk.live/react-sdk@latest / 1.x - see Troubleshooting.

Option A - Use your own call SDK

Providing onPhoneCall / onVideoCall fully replacesthe built-in VideoSDK flow - it doesn't run alongside it. Omit both to keep the built-in system.

tsx
1features={{2  showPhoneCall: true,3  showVideoCall: true,4  onPhoneCall: ({ activeChannel, conversationId }) => {5    yourVoiceSDK.start(activeChannel.id, conversationId);6  },7  onVideoCall: ({ activeChannel, conversationId }) => {8    yourVideoSDK.start(activeChannel.id, conversationId);9  },10}}

Option B - Replace the call button group

tsx
1components={{2  HeaderCallActions: ({ onPhoneCall, onVideoCall, activeChannel }) => (3    <div className="flex gap-2">4      <button type="button" onClick={onPhoneCall}>Call {activeChannel.name}</button>5      <button type="button" onClick={onVideoCall}>Video</button>6    </div>7  ),8}}

Warning

Don't import HeaderCallActions from the package inside your own custom one - that causes infinite recursion. Render your own buttons.

Option C - Replace individual buttons

tsx
1components={{2  PhoneCallButton: ({ onPhoneCall, className }) => (3    <button type="button" className={className} onClick={onPhoneCall}>📞</button>4  ),5  VideoCallButton: ({ onVideoCall, className }) => (6    <button type="button" className={className} onClick={onVideoCall}>📹</button>7  ),8}}

Custom buttons should respect the admin's settings - useAdminFeatureGate("videoCall").

Hide calls

tsx
features={{ showPhoneCall: false, showVideoCall: false }}

To hide the in-call UI or ringing dialog, pass CallOverlay: () => null or IncomingCallDialog: () => null in components.

Calling exports

ExportKindPurpose
CallOverlayComponentFull-screen in-call UI - auto-mounted
IncomingCallDialogComponentRinging UI for callees - auto-mounted
useCallStoreHookCalling state machine - uiStatus, startCall, acceptCall, endCall, recording/reactions state
CallStateTypeFull shape returned by useCallStore
apiCreateCallRoom, apiFetchJoinToken, apiFetchCallHistory, apiFetchCallDetailFunctionsREST building blocks for your own call-history UI
CALL_MODES, CALL_STATUSConstants"audio" | "video" and the call lifecycle statuses
apiStartRecording, apiStopRecording, apiGetRecordingStatus, apiGetCallRecordings, apiGetConversationRecordingsFunctionsCloud recording REST building blocks
CallTranscriptReadyPayload, CallTranscriptFailedPayload, TranscriptStatusTypesTranscript socket payloads and status
UseMeetingRecordingResultTypeRecording hook result - for your own record button
tsx
1import { useCallStore, CALL_STATUS } from "@realtimexsco/live-chat";2 3const uiStatus = useCallStore((s) => s.uiStatus);4const isRecording = useCallStore((s) => s.recordingStatus === "recording");
PreviousThemes & localeNextIn-call control bar

On this page

OverviewWhat “built-in” gets youRequirement: @videosdk.live/react-sdkOption A - Use your own call SDKOption B - Replace the call button groupOption C - Replace individual buttonsHide callsCalling exports
Back to top