RealtimeKit の使用を開始する
このガイドでは、Capacitor RealtimeKit プラグインを統合して、Cloudflare Calls を利用したビデオ会議をアプリケーションに追加する手順を説明します。
インストール
Section titled “インストール”npm を使用してプラグインをインストールします。
npm install @capgo/capacitor-realtimekitnpx cap syncこのプラグインは Cloudflare RealtimeKit SDK を使用します。
- iOS: RealtimeKitCoreiOS (Swift Package Manager 経由で自動的にインストールされます)
- Android:
com.cloudflare.realtimekit:ui-androidバージョン0.2.2
Android RealtimeKit バージョンのカスタマイズ
Section titled “Android RealtimeKit バージョンのカスタマイズ”アプリの build.gradle 内:
buildscript { ext { realtimekitUiVersion = '0.2.2' // or your desired version }}iOS 構成
Section titled “iOS 構成”アプリの 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 構成
Section titled “Android 構成”次の権限を 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" />基本的な使い方
Section titled “基本的な使い方”プラグインをインポートする
Section titled “プラグインをインポートする”import { CapacitorRealtimekit } from '@capgo/capacitor-realtimekit';プラグインを初期化する
Section titled “プラグインを初期化する”async function initializeRealtimeKit() { try { await CapacitorRealtimekit.initialize(); console.log('RealtimeKit initialized'); } catch (error) { console.error('Failed to initialize RealtimeKit:', error); }}会議を開始する
Section titled “会議を開始する”async function startMeeting(meetingUrl: string) { try { await CapacitorRealtimekit.startMeeting({ url: meetingUrl }); console.log('Meeting started'); } catch (error) { console.error('Failed to start meeting:', error); }}総合的なビデオ会議サービスは次のとおりです。
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 通話のセットアップ
Section titled “Cloudflare 通話のセットアップ”このプラグインを使用するには、Cloudflare Calls を設定する必要があります。
1. Cloudflareアカウントを作成する
Section titled “1. Cloudflareアカウントを作成する”アカウントをお持ちでない場合は、Cloudflare にサインアップしてください。
2. 通話を有効にする API
Section titled “2. 通話を有効にする API”- Cloudflareダッシュボードに移動します
- 通話セクションに移動します
- 呼び出し API を有効にする
- API 資格情報を取得します
3. ミーティング URL を作成する
Section titled “3. ミーティング URL を作成する”会議 URL を作成するにはバックエンド サービスが必要です。 Cloudflare ワーカーを使用した例:
// 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);}高度な使用法
Section titled “高度な使用法”カスタム構成でのミーティング
Section titled “カスタム構成でのミーティング”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 }); } }}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 の統合
Section titled “React の統合”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 の統合
Section titled “Vue の統合”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 }; }};ベストプラクティス
Section titled “ベストプラクティス”- 早期初期化: アプリの起動時に RealtimeKit を初期化します。
- エラーの処理: 呼び出しは常に try-catch ブロックでラップする
- 権限のリクエスト: 開始する前にカメラ/マイクの権限を確認してください
- テストネットワーク: 参加する前にインターネット接続を確認してください
- バックグラウンド オーディオ: iOS のバックグラウンド モードを構成します。
- ユーザー エクスペリエンス: 初期化中に読み込み状態を表示する
- クリーンな URL: 使用前に会議 URL を検証する
よくある問題
Section titled “よくある問題”会議が開始されません
Section titled “会議が開始されません”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); }}権限が拒否されました
Section titled “権限が拒否されました”iOS では、Info.plist に必要な使用法の説明がすべて含まれていることを確認します。 Android で、AndroidManifest.xml 権限が存在することを確認します。
iOS の音声の問題
Section titled “iOS の音声の問題”Info.plist でバックグラウンド オーディオ モードが設定されていることを確認します。
<key>UIBackgroundModes</key><array> <string>audio</string> <string>voip</string></array>次のステップ
Section titled “次のステップ”- 完全なメソッドのドキュメントについては、API リファレンス を参照してください。
- [Cloudflare コールのドキュメント] を読む(https://developers.cloudflare.com/calls/)
- [サンプルアプリ]をチェックしてください(https://github.com/Cap-go/capacitor-realtimekit/tree/main/example)
- 完全な実装については、チュートリアル を参照してください。