React Native アプリにビデオ通話を追加する方法
COVID-19 パンデミックの間、ビデオ通話は不可欠な日常活動になりました。チャット アプリ、音声通話、ビデオ通話などの機能を使用することで、友人や家族とのつながりを保つことができました。
それでは、ビデオ通話を可能にする独自の React Native アプリを作成しましょう。
このチュートリアルでは、Twilio プログラム可能なビデオ通話 API を使用して、React Native アプリにビデオ通話機能を実装する方法を学習します。
プロセスは非常に簡単です。ビデオ会議室を作成し、他のユーザーをその会議室に招待するだけです。これを行うには、カメラとマイクにアクセスする必要があります。そのため、テスト目的で実際のスマートフォン デバイスを使用する必要があります。
Twilio API にアクセスするために使用するメイン パッケージは、react-native-twilio-video-webrtc パッケージです。
要件
- Twilio アカウント
- テスト用に最低 2 台の iOS または Android デバイス
- React ネイティブ環境のセットアップ
始めましょう!
Twilio API キーを取得する方法
Twilio API キーを取得するには、Twilio アカウントが必要です。そのためには、この URL にアクセスしてください。アカウントを設定したら、以下のスクリーンショットで示されている場所に移動する必要があります:
アクセス トークンのフェッチを処理するようにサーバーをセットアップする方法
アクセス トークンを取得するには、新しいノード サーバー プロジェクトを作成する必要があります。そのためには、次のコマンドを実行して必要なパッケージをインストールする必要があります:
yarn add dotenv express ngrok nodemon twilio
次に、以下のコード スニペットに示すように、環境変数ファイル (.env) に Twilio 資格情報を追加する必要があります。
PORT=3000
ACCOUNT_SID=AC5ceb0847c50c91b143ce07
API_KEY_SID=SKa173c10de99a26fd86969b
API_KEY_SECRET=Czv7IjNIZJis8s7jb5FePi
次に、API エンドポイントを作成する必要があります。まず、必要なパッケージをインポートし、オブジェクト インスタンスを作成して、以下のコード スニペットの指示に従ってアクセス トークンを取得する必要があります。
import 'dotenv/config';
import express from 'express';
import twilio from 'twilio';
import ngrok from 'ngrok';
const AccessToken = twilio.jwt.AccessToken;
const VideoGrant = AccessToken.VideoGrant;
const app = express();
ここでは、アクセス トークンを取得するための API エンドポイントを作成します。 Express インスタンスが提供する get メソッドを使用して、アクセス トークンで応答するエンドポイント関数を作成する必要があります。
関数内で、Twillio 資格情報を使用して新しいインスタンスを作成する必要があります。次に、モバイル デバイスの登録画面から受け取ったユーザー名を ID 属性として追加する必要があります。
最後に、ユーザーがビデオを使用できるようにアクセスを許可し、JWT トークンをデバイスに戻します。以下のスニペットでこれらすべてを行うコードを次に示します:
app.get('/getToken', (req, res) => {
if (!req.query || !req.query.userName) {
return res.status(400).send('Username parameter is required');
}
const accessToken = new AccessToken(
process.env.ACCOUNT_SID,
process.env.API_KEY_SID,
process.env.API_KEY_SECRET,
);
// Set the Identity of this token
accessToken.identity = req.query.userName;
// Grant access to Video
var grant = new VideoGrant();
accessToken.addGrant(grant);
// Serialize the token as a JWT
var jwt = accessToken.toJwt();
return res.send(jwt);
});
また、作成したエンドポイント API をイースト アクセス用にインターネットに公開します。そのために、次のコード スニペットのコードを使用できます:
app.listen(process.env.PORT, () =>
console.log(`Server listening on port ${process.env.PORT}!`),
);
ngrok.connect(process.env.PORT).then((url) => {
console.log(`Server forwarded to public url ${url}`);
});
最後に、以下のスクリーンショットに示すようにサーバーを実行する必要があります:
これで、アクセス トークンを返す API エンドポイントが正常に作成されました。
React Native プロジェクトの設定方法
React Native プロジェクトでは、パッケージを手動で設定するだけでなく、Android と iOS の両方のプラットフォームでカメラとマイクにアクセスするためのアクセス許可を構成する必要があります。
ただし、最初に必要なパッケージをインストールする必要があります。これは react-navigation
です。 と react-native-twilio-video-webrtc
、プロジェクト ターミナルで次のコマンドを実行します:
yarn add @react-navigation/native @react-navigation/stack react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view react-native-dotenv react-native-permissions <https://github.com/blackuy/react-native-twilio-video-webrtc>
iOS のセットアップ
iOS の場合、パッケージを手動でセットアップする必要があります。まず、Podfile で IOS ターゲットを 11 に増やす必要があります . Twilio のネイティブ ビデオ SDK は iOS 11.0 以降のみをサポートしているため、これが必要です。
platform :ios, '11.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
Podfile では、以下のコード スニペットの指示に従って、アクセス許可要求をセットアップする必要があります。
permissions_path = '../node_modules/react-native-permissions/ios'
pod 'Permission-Camera', :path => "#{permissions_path}/Camera.podspec"
pod 'Permission-Microphone', :path => "#{permissions_path}/Microphone.podspec"
次に、info.plist を開いて、以下のコード スニペットの指示に従って、カメラとマイクへのアクセス許可を要求するコードを追加する必要があります。
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSCameraUsageDescription</key>
<string>We require your permission to access the camera while in a video call</string>
<key>NSMicrophoneUsageDescription</key>
<string>We require your permission to access the microphone while in a video call</string>
これで iOS のセットアップは完了です。
Android のセットアップ
何よりもまず、次のコード行を ./android/settings.gradle に追加する必要があります ファイル:
project(':react-native-twilio-video-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-twilio-video-webrtc/android')
また、パッケージ実装コードを ./android/app/build.gradle に追加する必要があります ファイル:
implementation project(':react-native-twilio-video-webrtc')
最後に、これを MainApplication.java にインポートする必要があります ファイルも:
import com.twiliorn.library.TwilioPackage;
次に、次のコードを使用してパッケージをアクティブ化する必要があります:
@Override
protected List getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List packages = new PackageList(this).getPackages();
// add the following code
packages.add(new TwilioPackage());
return packages;
}
Register Room 画面の作成方法
ここでは、React Native アプリのビデオ通話でルームに登録できるようにする「Register Room」という画面を作成します。
まず、以下のコード スニペットに示すように、必要なパッケージをインポートする必要があります。
import React, {useState, useRef, useEffect, useContext} from 'react';
import {
StyleSheet,
View,
Text,
StatusBar,
TouchableOpacity,
TextInput,
Alert,
KeyboardAvoidingView,
Platform,
ScrollView,
Dimensions,
} from 'react-native';
import {
TwilioVideoLocalView,
TwilioVideoParticipantView,
TwilioVideo,
} from 'react-native-twilio-video-webrtc';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
- react-navigation:登録画面とビデオ通話画面のナビゲーションを処理します。
- react-native:このパッケージにより、カメラとマイクへのアクセス許可を処理できます。
- react-native-twilio-video-webrtc:これにより、Twilio のビデオ通話プログラム可能な API にアクセスできます。
インスタンスと変数を初期化する方法
まず、react-navigation のインスタンスを作成します。次に、以下のコード スニペットに示すように、状態とコンテキスト変数を初期化して、状態を配布します。
const Stack = createStackNavigator();
const initialState = {
isAudioEnabled: true,
status: 'disconnected',
participants: new Map(),
videoTracks: new Map(),
userName: '',
roomName: '',
token: '',
};
const AppContext = React.createContext(initialState);
const dimensions = Dimensions.get('window');
ブートストラップ ナビゲーション
App.js で ファイルを使用して、ナビゲーション コンテナー スタックを作成します。 Stack
の使用 以下のコード スニペットで指示されているように、コンテキストを使用してすべての画面に状態を配布します。
export default () => {
const [props, setProps] = useState(initialState);
return (
<>
<StatusBar barStyle="dark-content" />
<AppContext.Provider value={{props, setProps}}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Video Call" component={VideoCallScreen} />
</Stack.Navigator>
</NavigationContainer>
</AppContext.Provider>
</>
);
};
登録画面の作り方
登録画面には、ユーザーの資格情報を取得し、ユーザーがビデオ コール ルームに参加できるようにするためのモーダル ダイアログが表示されます。
まず、コンテキストから register.js に小道具を取得する必要があります 以下のコード スニペットに示すようなファイル:
import React, {useState, useRef, useEffect, useContext} from 'react';
import {
checkMultiple,
request,
requestMultiple,
PERMISSIONS,
RESULTS,
} from 'react-native-permissions';
const RegisterScreen = ({navigation}) => {
const {props, setProps} = useContext(AppContext);
次に、カメラとマイクのアクセス許可を処理する関数を作成する必要があります。関数のコードは、以下のコード スニペットで提供されます:
const _checkPermissions = (callback) => {
const iosPermissions = [PERMISSIONS.IOS.CAMERA, PERMISSIONS.IOS.MICROPHONE];
const androidPermissions = [
PERMISSIONS.ANDROID.CAMERA,
PERMISSIONS.ANDROID.RECORD_AUDIO,
];
checkMultiple(
Platform.OS === 'ios' ? iosPermissions : androidPermissions,
).then((statuses) => {
const [CAMERA, AUDIO] =
Platform.OS === 'ios' ? iosPermissions : androidPermissions;
if (
statuses[CAMERA] === RESULTS.UNAVAILABLE ||
statuses[AUDIO] === RESULTS.UNAVAILABLE
) {
Alert.alert(
'Error',
'Hardware to support video calls is not available',
);
} else if (
statuses[CAMERA] === RESULTS.BLOCKED ||
statuses[AUDIO] === RESULTS.BLOCKED
) {
Alert.alert(
'Error',
'Permission to access hardware was blocked, please grant manually',
);
} else {
if (
statuses[CAMERA] === RESULTS.DENIED &&
statuses[AUDIO] === RESULTS.DENIED
) {
requestMultiple(
Platform.OS === 'ios' ? iosPermissions : androidPermissions,
).then((newStatuses) => {
if (
newStatuses[CAMERA] === RESULTS.GRANTED &&
newStatuses[AUDIO] === RESULTS.GRANTED
) {
callback && callback();
} else {
Alert.alert('Error', 'One of the permissions was not granted');
}
});
} else if (
statuses[CAMERA] === RESULTS.DENIED ||
statuses[AUDIO] === RESULTS.DENIED
) {
request(statuses[CAMERA] === RESULTS.DENIED ? CAMERA : AUDIO).then(
(result) => {
if (result === RESULTS.GRANTED) {
callback && callback();
} else {
Alert.alert('Error', 'Permission not granted');
}
},
);
} else if (
statuses[CAMERA] === RESULTS.GRANTED ||
statuses[AUDIO] === RESULTS.GRANTED
) {
callback && callback();
}
}
});
};
次に、アプリが起動するたびに、この権限チェック関数を呼び出す必要があります。そのためには、useEffect
内で関数を呼び出す必要があります。 以下のコード スニペットの指示に従ってフックします:
useEffect(() => {
_checkPermissions();
}, []);
最後に、部屋名とユーザー名を受け入れる 2 つの入力を持つ単純なフォームを作成する必要があります。次に、入力をサーバーに送信して、Twilio API に登録する必要があります。このコードは、以下のコード スニペットで提供されます:
return (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.container}>
<ScrollView contentContainerStyle={styles.container}>
<View style={styles.form}>
<View style={styles.formGroup}>
<Text style={styles.text}>User Name</Text>
<TextInput
style={styles.textInput}
autoCapitalize="none"
value={props.userName}
onChangeText={(text) => setProps({...props, userName: text})}
/>
</View>
<View style={styles.formGroup}>
<Text style={styles.text}>Room Name</Text>
<TextInput
style={styles.textInput}
autoCapitalize="none"
value={props.roomName}
onChangeText={(text) => setProps({...props, roomName: text})}
/>
</View>
<View style={styles.formGroup}>
<TouchableOpacity
disabled={false}
style={styles.button}
onPress={() => {
_checkPermissions(() => {
fetch(`https://ae7a722dc260.ngrok.io/getToken?userName=${props.userName}`)
.then((response) => {
if (response.ok) {
response.text().then((jwt) => {
setProps({...props, token: jwt});
navigation.navigate('Video Call');
return true;
});
} else {
response.text().then((error) => {
Alert.alert(error);
});
}
})
.catch((error) => {
console.log('error', error);
Alert.alert('API not available');
});
});
}}>
<Text style={styles.buttonText}>Connect to Video Call</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
</KeyboardAvoidingView>
);
以下のエミュレータのスクリーンショットに示すような結果が得られます:
ここで、サーバー上で実行されている Twilio API に登録するためにルーム名とユーザー名を入力できるモーダル フォームを含む [ルームの登録] 画面に注目してください。
ビデオ通話画面の作成方法
ビデオ通話画面には 2 つのウィンドウがあります。1 つは自分のカメラのビューを表示し、もう 1 つは受信者のカメラのビューを表示します。
まず、状態を受け入れるためにコンテキストを初期化する必要があります。次に、useRef
を使用して参照変数を作成します。 以下のコード スニペットで指示されているように、状態にアクセスするためのフック:
const VideoCallScreen = ({navigation}) => {
const twilioVideo = useRef(null);
const {props, setProps} = useContext(AppContext);
次に、connect
を使用して接続を初期化する必要があります twilioVideo
のメソッド 以下のコード スニペットで指示されているように、ルーム名とアクセス トークンを提供します。
useEffect(() => {
twilioVideo.current.connect({
roomName: props.roomName,
accessToken: props.token,
});
setProps({...props, status: 'connecting'});
return () => {
_onEndButtonPress();
};
}, []);
次に、ビデオ通話画面の本体テンプレートを作成する必要があります。ここでは、接続が確立され、条件付きレンダリングを使用してストリーミングされている場合にのみ、参加者のカメラ ビューを表示します。この全体的なコードは、以下のコード スニペットで提供されます:
{(props.status === 'connected' || props.status === 'connecting') && (
<View style={styles.callWrapper}>
{props.status === 'connected' && (
<View style={styles.grid}>
{Array.from(props.videoTracks, ([trackSid, trackIdentifier]) => (
<TwilioVideoParticipantView
style={styles.remoteVideo}
key={trackSid}
trackIdentifier={trackIdentifier}
/>
))}
</View>
)}
</View>
)}
次に、通話の終了、ミュート、前面カメラと背面カメラの切り替えなど、ビデオ内機能を制御する関数を作成する必要があります。必要な機能のコーディング実装は、以下のコード スニペットで提供されます:
const _onEndButtonPress = () => {
twilioVideo.current.disconnect();
setProps(initialState);
};
const _onMuteButtonPress = () => {
twilioVideo.current
.setLocalAudioEnabled(!props.isAudioEnabled)
.then((isEnabled) => setProps({...props, isAudioEnabled: isEnabled}));
};
const _onFlipButtonPress = () => {
twilioVideo.current.flipCamera();
};
ここでは、 disconnect
を使用しました 、 setLocalAudioEnabled
と flipCamera
twilioVideo
が提供するメソッド 必要なビデオ内機能をトリガーするインスタンス。
ここで、関数をトリガーするためにいくつかのボタンをレンダリングする必要があります。そのためには、次のコード スニペットのコードを使用する必要があります:
<View style={styles.optionsContainer}>
<TouchableOpacity style={styles.button} onPress={_onEndButtonPress}>
<Text style={styles.buttonText}>End</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={_onMuteButtonPress}>
<Text style={styles.buttonText}>
{props.isAudioEnabled ? 'Mute' : 'Unmute'}
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={_onFlipButtonPress}>
<Text style={styles.buttonText}>Flip</Text>
</TouchableOpacity>
</View>
最後のステップは TwilioVideo
を追加することです すべてのビデオ通話イベントを処理および監視するように構成されたコンポーネント。全体的に構成された TwilioVideo
コンポーネントは、以下のコード スニペットで提供されます:
<TwilioVideo
ref={twilioVideo}
onRoomDidConnect={() => {
setProps({...props, status: 'connected'});
}}
onRoomDidDisconnect={() => {
setProps({...props, status: 'disconnected'});
navigation.goBack();
}}
onRoomDidFailToConnect={(error) => {
Alert.alert('Error', error.error);
setProps({...props, status: 'disconnected'});
navigation.goBack();
}}
onParticipantAddedVideoTrack={({participant, track}) => {
if (track.enabled) {
setProps({
...props,
videoTracks: new Map([
...props.videoTracks,
[
track.trackSid,
{
participantSid: participant.sid,
videoTrackSid: track.trackSid,
},
],
]),
});
}
}}
onParticipantRemovedVideoTrack={({track}) => {
const videoTracks = props.videoTracks;
videoTracks.delete(track.trackSid);
setProps({...props, videoTracks});
}}
/>
ルーム内のユーザー間で適切な接続を確立できた場合、次の結果が得られます:
上のスクリーンショットは、部屋にいる 2 人の参加者間のビデオ通話を示しています。
これにより、React Native アプリにビデオ通話機能を正常に実装できました。
結論
このチュートリアルは、React Native アプリでビデオ通話をセットアップする方法について、初心者レベルの学習リソースを提供することを目的としています。これは、Twilio のプログラム可能なビデオ通話 API を使用して行いました。
React Native の部分だけでなく、別のノード サーバー プロジェクトでの全体的な API 実装についても説明しました。
次のステップは、匿名通話や複数参加者のビデオ通話ルームの開始などの高度な機能を追加することです。
機能のインスピレーションと適切なビデオ通話アプリについては、強力な機能を備えたビデオ チャット アプリの状態を提供する instamobile.io をご覧ください。
また会いましょう、ハッピー コーディング!
-
React Native で動画を背景として使用する方法
この投稿では、backgroundVideo を作成します。 React Nativeで。 React Native を使い始めたばかりの方は、私の記事 What you need to know to build mobile apps with React Native をチェックしてください。 デモ:Peleton ホーム画面 バックグラウンド ビデオは、アプリの UI に素晴らしい効果を追加できます。ここで行うように、たとえば広告を表示したり、ユーザーにメッセージを送信したりする場合にも役立ちます。 いくつかの基本的な要件が必要になります。開始するには、react-native 環
-
iOS 11の写真アプリで人を追加または削除する方法
iOS 10 Apple は、顔を認識し、それらを利用して人々の顔を含む写真を整理する革新的な機能を導入しました。そのため、愛する人の写真をすべて見なければならないたびに、すべての写真をめくる代わりに、その人の写真のサムネイルをクリックするだけで済みました。しかし、iOS 11 では多くの変更や修正が行われ、その中にはコンフォート ゾーンから抜け出すようなものもありました。そのようなものの 1 つは、iOS 11 での変更は、人物の写真を含むサムネイルを追加するオプションに直接アクセスできないことです。そこで、iOS 11 を実行している iPhone の写真アプリから人物を追加または削除する