기본 화상 통화 앱 반응

9838 단어 reactreactnative


필요한 것:
  • Twilio 계정
  • 서버측 구현(node.js)
  • 모듈을 사용한 클라이언트 측 구현 — react-native-twilio-video-webrtc

  • Twiilio 계정
    Twilio를 사용할 예정이므로 가입here하고 필수 키(API KEY SID, ACCOUNT SID, API KEY SECRET)를 검색해야 합니다.



    그런 다음 설정 => API 키로 이동합니다.

    새 API 키 추가를 클릭하고 유형으로 드롭다운을 선택하고 기본을 선택합니다.
    API 비밀은 한 번만 표시됩니다. 서버 측 구현을 위해 모든 키가 필요하므로 안전한 곳에 복사하여 붙여넣어야 합니다.



    서버 측 구현

    여기서 단계는 매우 간단합니다. 일반 노드 익스프레스를 구현하고 다음 경로를 추가합니다.

    import 'dotenv/config';
    import express from 'express';
    import twilio from 'twilio';
    
    const AccessToken = twilio.jwt.AccessToken;
    const VideoGrant = AccessToken.VideoGrant;
    const app = express();
    
    app.get('/getToken', (req, res) => {
    if (!req.query || !req.query.room || !req.query.username) {
     return res.status(400).send('username and room 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
     const grant = new VideoGrant();
    
      accessToken.identity = req.query.username;// Grant access to Video
      grant.room = req.query.room;
    
      accessToken.addGrant(grant); // Serialize the token as a JWT
      const jwt = accessToken.toJwt();
      return res.send(jwt);
      });
    


    이 끝점의 경우 쿼리 본문에서 사용자 이름을 문자열로, 방을 문자열로 가져옵니다. 방을 만들고 다른 참가자를 기다리는 방에 사용자를 추가합니다.

    클라이언트 측 구현

    이제 프로젝트에 twilio 비디오 webrtc 모듈을 추가할 수 있습니다.
    yarn add https://github.com/blackuy/react-native-twilio-video-webrtc
    그런 다음 Android 및 iOS 모두에 대한 간단한 설치 지침here을 따릅니다.

    import React, { useState, useRef } from "react";
    import {
     Alert,
     AppRegistry,
     StyleSheet,
     Text,
     TextInput,
     View,
     Button,
     PermissionsAndroid,
     Platform,
     TouchableOpacity,
    } from "react-native";
    
    import {
     TwilioVideoLocalView,
     TwilioVideoParticipantView,
     TwilioVideo,
    } from "react-native-twilio-video-webrtc";
    
    import styleSheet from "./styles";
    
    const styles = StyleSheet.create(styleSheet);
    
    const App = (props) => {
     const [isAudioEnabled, setIsAudioEnabled] = useState(true);
     const [isVideoEnabled, setIsVideoEnabled] = useState(true);
     const [status, setStatus] = useState("disconnected");
     const [participants, setParticipants] = useState(new Map());
     const [videoTracks, setVideoTracks] = useState(new Map());
     const [room, setRoom] = useState("");
     const [username, setUsername] = useState("");
     const twilioVideo = useRef(null);
    
     const fetchToken = async () => {
     try {
     const res = await fetch(
     `https://<your_base_url>/getToken?username=${username}&room=${room}`
          );
     if (!res.ok) {
     console.log("error", error);
     Alert.alert("API not available");
     return null;
          }
     const jwt = await res.text();
     return jwt;
        } catch (error) {
     console.log("error", error);
     Alert.alert("An Error occurred");
     return null;
        }
      };
    
     const _onConnectButtonPress = async () => {
     if (Platform.OS === "android") {
     await _requestAudioPermission();
     await _requestCameraPermission();
        }
     const token = await fetchToken();
     if (!token) {
     return;
        }
     twilioVideo.current.connect({
     accessToken: token,
     enableNetworkQualityReporting: true,
     dominantSpeakerEnabled: true,
        });
     setStatus("connecting");
      };
    
     const _onEndButtonPress = () => {
     twilioVideo.current.disconnect();
      };
    
     const _onMuteButtonPress = () => {
     twilioVideo.current
          .setLocalAudioEnabled(!isAudioEnabled)
          .then((isEnabled) => setIsAudioEnabled(isEnabled));
      };
    
     const _onFlipButtonPress = () => {
     twilioVideo.current.flipCamera();
      };
    
     const _onRoomDidConnect = () => {
     setStatus("connected");
      };
    
     const _onRoomDidDisconnect = ({ error }) => {
     console.log("ERROR: ", error);
    
     setStatus("disconnected");
      };
    
     const _onRoomDidFailToConnect = (error) => {
     console.log("ERROR: ", error);
    
     setStatus("disconnected");
      };
    
     const _onParticipantAddedVideoTrack = ({ participant, track }) => {
     console.log("onParticipantAddedVideoTrack: ", participant, track);
    
     setVideoTracks(
     new Map([
            ...videoTracks,
            [
     track.trackSid,
              { participantSid: participant.sid, videoTrackSid: track.trackSid },
            ],
          ])
        );
      };
    
     const _onParticipantRemovedVideoTrack = ({ participant, track }) => {
     console.log("onParticipantRemovedVideoTrack: ", participant, track);
    
     const videoTracks = new Map(videoTracks);
     videoTracks.delete(track.trackSid);
    
     setVideoTracks(videoTracks);
      };
    
     const _onNetworkLevelChanged = ({ participant, isLocalUser, quality }) => {
     console.log(
     "Participant",
     participant,
     "isLocalUser",
     isLocalUser,
     "quality",
     quality
        );
      };
    
     const _onDominantSpeakerDidChange = ({ roomName, roomSid, participant }) => {
     console.log(
     "onDominantSpeakerDidChange",
     `roomName: ${roomName}`,
     `roomSid: ${roomSid}`,
     "participant:",
     participant
        );
      };
    
     const _requestAudioPermission = () => {
     return PermissionsAndroid.request(
     PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
          {
     title: "Need permission to access microphone",
     message:
     "To run this demo we need permission to access your microphone",
     buttonNegative: "Cancel",
     buttonPositive: "OK",
          }
        );
      };
    
     const _requestCameraPermission = () => {
     return PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA, {
     title: "Need permission to access camera",
     message: "To run this demo we need permission to access your camera",
     buttonNegative: "Cancel",
     buttonPositive: "OK",
        });
      };
    
     return (
     <View style={styles.container}>
     {status === "disconnected" && (
     <View>
     <Text style={styles.welcome}>React Native Twilio Video</Text>
     <TextInput
     style={styles.input}
     autoCapitalize="none"
     value={username}
     onChangeText={(text) => setUsername(text)}
     />
     <TextInput
     style={styles.input}
     autoCapitalize="none"
     value={room}
     onChangeText={(text) => setRoom(text)}
     />
     <Button
     title="Connect"
     style={styles.button}
     onPress={_onConnectButtonPress}
     ></Button>
     </View>
          )}
    
     {(status === "connected" || status === "connecting") && (
     <View style={styles.callContainer}>
     {status === "connected" && (
     <View style={styles.remoteGrid}>
     {Array.from(videoTracks, ([trackSid, trackIdentifier]) => {
     return (
     <TwilioVideoParticipantView
     style={styles.remoteVideo}
     key={trackSid}
     trackIdentifier={trackIdentifier}
     />
                    );
                  })}
     </View>
              )}
     <View style={styles.optionsContainer}>
     <TouchableOpacity
     style={styles.optionButton}
     onPress={_onEndButtonPress}
     >
     <Text style={{ fontSize: 12 }}>End</Text>
     </TouchableOpacity>
     <TouchableOpacity
     style={styles.optionButton}
     onPress={_onMuteButtonPress}
     >
     <Text style={{ fontSize: 12 }}>
     {isAudioEnabled ? "Mute" : "Unmute"}
     </Text>
     </TouchableOpacity>
     <TouchableOpacity
     style={styles.optionButton}
     onPress={_onFlipButtonPress}
     >
     <Text style={{ fontSize: 12 }}>Flip</Text>
     </TouchableOpacity>
     <TwilioVideoLocalView enabled={true} style={styles.localVideo} />
     </View>
     </View>
          )}
    
     <TwilioVideo
     ref={twilioVideo}
     onRoomDidConnect={_onRoomDidConnect}
     onRoomDidDisconnect={_onRoomDidDisconnect}
     onRoomDidFailToConnect={_onRoomDidFailToConnect}
     onParticipantAddedVideoTrack={_onParticipantAddedVideoTrack}
     onParticipantRemovedVideoTrack={_onParticipantRemovedVideoTrack}
     onNetworkQualityLevelsChanged={_onNetworkLevelChanged}
     onDominantSpeakerDidChange={_onDominantSpeakerDidChange}
     />
     </View>
      );
    };
    
    export default App;
    


    위의 코드를 복사하여 ur react native 프로젝트에 붙여넣고 방과 사용자 이름을 입력하고 연결 버튼을 눌러 화상 통화를 시작하세요.
    오. 테스트할 장치가 두 개 이상 있는지 확인하고 실제로 작동하는지 확인하십시오.

    Twilio를 사용하여 반응 네이티브에서 기본 화상 통화를 구현하고 서버 측과 클라이언트 측을 모두 구현한 후 다음 단계는 고급 기능을 추가하고 다음과 같은 표준 통화 기능을 포함하는 WhatsApp 클론 구축과 같은 기술을 향상시키는 것입니다.
    다른 참가자 또는 여러 참가자 화상 통화방, 그룹 통화 벨 울림, 통화 중, 통화 거부 또는 응답되지 않은 통화와 같은 참가자 상태 관리 및 표시.

    이 모든 기능이 추가된 적절한 화상 통화 앱을 확인해야 합니다QuickComponent. 앞에서 언급한 React NativeWhatsApp Clone와 완전한 화상 통화 기능을 갖춘 Dating app , UberEats clone 등과 같은 더 많은 React Native 앱을 찾을 수 있습니다.

    좋은 웹페이지 즐겨찾기