Commencer with RealtimeKit
This Guide will walk you through integrating the Capacitor RealtimeKit plugin to Ajouter video conferencing powered by Cloudflare Calls to your Application.
Installation
Section titled “Installation”Installer the plugin using npm:
npm install @capgo/capacitor-realtimekitnpx cap syncDependencies
Section titled “Dependencies”This plugin uses the Cloudflare RealtimeKit SDK:
- iOS: RealtimeKitCoreiOS (automatically installed via Swift Package Manager)
- Android:
com.cloudflare.realtimekit:ui-androidversion0.2.2
Customizing Android RealtimeKit Version
Section titled “Customizing Android RealtimeKit Version”In your app’s build.gradle:
buildscript { ext { realtimekitUiVersion = '0.2.2' // or your desired version }}iOS Configuration
Section titled “iOS Configuration”Add the following to your app’s Info.plist:
<key>NSCameraUsageDescription</key><string>We need camera access for video calls</string>
<key>NSMicrophoneUsageDescription</key><string>We need microphone access for audio calls</string>
<key>NSPhotoLibraryUsageDescription</key><string>We need photo library access to share images</string>
<key>NSBluetoothPeripheralUsageDescription</key><string>We need Bluetooth access for audio routing</string>
<key>UIBackgroundModes</key><array> <string>audio</string> <string>voip</string> <string>fetch</string> <string>remote-notification</string></array>Android Configuration
Section titled “Android Configuration”Add the following permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-feature android:name="android.hardware.camera" android:required="false" /><uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />Basic Utilisation
Section titled “Basic Utilisation”Importer the Plugin
Section titled “Importer the Plugin”import { CapacitorRealtimekit } from '@capgo/capacitor-realtimekit';Initialiser the Plugin
Section titled “Initialiser the Plugin”async function initializeRealtimeKit() { try { await CapacitorRealtimekit.initialize(); console.log('RealtimeKit initialized'); } catch (error) { console.error('Failed to initialize RealtimeKit:', error); }}Démarrer a Meeting
Section titled “Démarrer a Meeting”async function startMeeting(meetingUrl: string) { try { await CapacitorRealtimekit.startMeeting({ url: meetingUrl }); console.log('Meeting started'); } catch (error) { console.error('Failed to start meeting:', error); }}Terminé Exemple
Section titled “Terminé Exemple”Here’s a comprehensive video conferencing service:
import { CapacitorRealtimekit } from '@capgo/capacitor-realtimekit';
export interface MeetingConfig { url: string; displayName?: string; audioEnabled?: boolean; videoEnabled?: boolean;}
export class VideoConferenceService { private isInitialized = false; private currentMeetingUrl: string | null = null;
async initialize(): Promise<boolean> { if (this.isInitialized) { console.log('RealtimeKit already initialized'); return true; }
try { await CapacitorRealtimekit.initialize(); this.isInitialized = true; console.log('RealtimeKit initialized successfully'); return true; } catch (error) { console.error('Failed to initialize RealtimeKit:', error); return false; } }
async startMeeting(config: MeetingConfig): Promise<void> { if (!this.isInitialized) { const initialized = await this.initialize(); if (!initialized) { throw new Error('Failed to initialize RealtimeKit'); } }
try { await CapacitorRealtimekit.startMeeting({ url: config.url });
this.currentMeetingUrl = config.url; console.log('Meeting started:', config.url); } catch (error) { console.error('Failed to start meeting:', error); throw error; } }
async joinMeeting(meetingUrl: string, displayName?: string): Promise<void> { const config: MeetingConfig = { url: meetingUrl, displayName: displayName };
await this.startMeeting(config); }
getCurrentMeetingUrl(): string | null { return this.currentMeetingUrl; }
isInMeeting(): boolean { return this.currentMeetingUrl !== null; }
async getPluginVersion(): Promise<string> { try { const result = await CapacitorRealtimekit.getPluginVersion(); return result.version; } catch (error) { console.error('Failed to get plugin version:', error); return 'unknown'; } }}
// Usageconst videoService = new VideoConferenceService();
// Initialize on app startawait videoService.initialize();
// Start a meetingawait videoService.startMeeting({ url: 'https://your-cloudflare-calls-url.com/meeting/123'});
// Join an existing meetingawait videoService.joinMeeting( 'https://your-cloudflare-calls-url.com/meeting/456', 'John Doe');Cloudflare Calls Configuration
Section titled “Cloudflare Calls Configuration”To use this plugin, you need to set up Cloudflare Calls:
1. Créer Cloudflare Compte
Section titled “1. Créer Cloudflare Compte”Sign up at Cloudflare if you don’t have an Compte.
2. Activer Calls API
Section titled “2. Activer Calls API”- Navigate to your Cloudflare Tableau de bord
- Go to Calls section
- Activer the Calls API
- Get your API credentials
3. Créer Meeting URLs
Section titled “3. Créer Meeting URLs”You need a backend service to Créer meeting URLs. Exemple using Cloudflare Workers:
// Cloudflare Worker exampleexport default { async fetch(request: Request): Promise<Response> { const { pathname } = new URL(request.url);
if (pathname === '/create-meeting') { const meetingId = generateMeetingId(); const meetingUrl = `https://your-app.calls.cloudflare.com/${meetingId}`;
return new Response(JSON.stringify({ meetingId, meetingUrl }), { headers: { 'Content-Type': 'application/json' } }); }
return new Response('Not found', { status: 404 }); }};
function generateMeetingId(): string { return Math.random().toString(36).substring(2, 15);}Advanced Utilisation
Section titled “Advanced Utilisation”Meeting with Custom Configuration
Section titled “Meeting with Custom Configuration”class MeetingManager { private videoService: VideoConferenceService;
constructor() { this.videoService = new VideoConferenceService(); }
async createAndJoinMeeting(userName: string): Promise<string> { // Initialize if needed await this.videoService.initialize();
// Call your backend to create a meeting const meetingUrl = await this.createMeetingOnBackend();
// Join the meeting await this.videoService.joinMeeting(meetingUrl, userName);
return meetingUrl; }
async createMeetingOnBackend(): Promise<string> { const response = await fetch('https://your-api.com/create-meeting', { method: 'POST', headers: { 'Content-Type': 'application/json' } });
const data = await response.json(); return data.meetingUrl; }
async shareMeetingLink(meetingUrl: string) { // Use Capacitor Share API if ('share' in navigator) { await (navigator as any).share({ title: 'Join my meeting', text: 'Join me for a video call', url: meetingUrl }); } }}Handling Permissions
Section titled “Handling Permissions”import { Capacitor } from '@capacitor/core';
async function checkAndRequestPermissions(): Promise<boolean> { if (Capacitor.getPlatform() === 'web') { // Request browser permissions try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
// Stop the stream, we just needed permission stream.getTracks().forEach(track => track.stop()); return true; } catch (error) { console.error('Permission denied:', error); return false; } }
// On native platforms, permissions are requested automatically return true;}
// Use before starting a meetingconst hasPermissions = await checkAndRequestPermissions();if (hasPermissions) { await videoService.startMeeting({ url: meetingUrl });}React Integration
Section titled “React Integration”import { useEffect, useState } from 'react';import { VideoConferenceService } from './VideoConferenceService';
function VideoCallComponent() { const [videoService] = useState(() => new VideoConferenceService()); const [isReady, setIsReady] = useState(false);
useEffect(() => { videoService.initialize().then(setIsReady); }, []);
const joinMeeting = async (meetingUrl: string) => { if (!isReady) { console.error('Video service not ready'); return; }
try { await videoService.joinMeeting(meetingUrl, 'User Name'); } catch (error) { console.error('Failed to join meeting:', error); } };
return ( <div> <button onClick={() => joinMeeting('https://your-meeting-url')} disabled={!isReady} > Join Meeting </button> </div> );}Vue Integration
Section titled “Vue Integration”import { ref, onMounted } from 'vue';import { VideoConferenceService } from './VideoConferenceService';
export default { setup() { const videoService = new VideoConferenceService(); const isReady = ref(false);
onMounted(async () => { isReady.value = await videoService.initialize(); });
const joinMeeting = async (meetingUrl: string) => { if (!isReady.value) { console.error('Video service not ready'); return; }
try { await videoService.joinMeeting(meetingUrl, 'User Name'); } catch (error) { console.error('Failed to join meeting:', error); } };
return { isReady, joinMeeting }; }};Best Practices
Section titled “Best Practices”- Initialiser Early: Initialiser RealtimeKit when your Application starts
- Handle Errors: Always wrap calls in try-catch blocks
- Request Permissions: Ensure camera/microphone permissions before starting
- Test Network: Vérifier internet connectivity before joining
- Background Audio: Configure background modes for iOS
- Utilisateur Experience: Show loading states during Initialisation
- Clean URLs: Valider meeting URLs before use
Problèmes courants
Section titled “Problèmes courants”Meeting Not Starting
Section titled “Meeting Not Starting”async function troubleshootMeeting(meetingUrl: string) { // Check initialization const version = await videoService.getPluginVersion(); console.log('Plugin version:', version);
// Verify URL format if (!meetingUrl.startsWith('https://')) { console.error('Invalid meeting URL, must use HTTPS'); return; }
// Try starting meeting try { await videoService.startMeeting({ url: meetingUrl }); } catch (error) { console.error('Meeting failed:', error); }}Permission Denied
Section titled “Permission Denied”On iOS, ensure Info.plist has all required Utilisation descriptions. On Android, verify AndroidManifest.xml permissions are present.
Audio Issues on iOS
Section titled “Audio Issues on iOS”Ensure background audio mode is configured in Info.plist:
<key>UIBackgroundModes</key><array> <string>audio</string> <string>voip</string></array>Suivant Steps
Section titled “Suivant Steps”- Explore the API Référence for Terminé method Documentation
- Read Cloudflare Calls Documentation
- Vérifier out the Exemple Application
- See the Tutoriel for Terminé implementation