webrtc를 이용한 영상통화 앱

안녕하세요, 오늘 우리는 webRtc, firebase 및 react.js를 사용하여 화상 통화 앱을 만들고 있습니다.
여기에서 사용 가능한 코드를 테스트할 수도 있습니다 -> Github

1. 방 만들기 ->



먼저 firebase에 실시간 데이터베이스를 생성하고 firebase 데이터베이스에서 임의로 생성된 키인 urlparams를 사용하여 roomId를 생성합니다.

// reference of RD
let RD = firebase.database().ref();
// url params
const URLPARAMS = new URLSearchParams(window.location.search);
// get id from url
const roomId = URLPARAMS.get("id");

if (roomId) {
  // set room id as child
  RD = RD.child(roomId);
} else {
  // create id and set to roomid
  RD = RD.push();
  window.history.replaceState(null, "meet", "?id=" + RD.key);
}


2. 참가자 객체 생성 -



이제 오디오, 비디오 및 화면 공유 정보를 포함하는 roomId에 객체 참가자를 생성합니다. 다음과 같이 보일 것입니다 -

이 출력을 얻기 위해 다음과 같이 할 것입니다. userName을 문자열로 얻거나 동적으로 얻을 수도 있습니다.

const participantDb = RD.child("participant");
  useEffect(() => {
    //check for value if true
    connectedRef.on("value", (snap) => {
      if (snap.val()) {
        // create values to push
        const defaultPref = {
          audio: true,
          video: false,
          screen: false,
        };
        // push data to participant
        const pushedDataOfParticipant = participantDb.push({
          userName: 'tejendra',
          preference: defaultPref,
        });
        // remove user when he quit or close browser
        pushedDataOfParticipant.onDisconnect().remove();
      }
    });
  }, []);


3. 피어 연결 -



이제 webrtc의 가장 중요한 부분은 피어 투 피어 연결을 생성하여 실시간으로 통신할 수 있도록 하는 것입니다. 이를 위해 아래 이미지를 따라야 합니다.



신호를 위해 우리는 firebase를 사용하고 있습니다.
첫 번째 사용자는 다른 사람이 가입할 수 있도록 제안을 만들고 누군가가 가입하면 하나의 답변이 생성되고 신호를 사용하여 통신합니다.

나. 제안 만들기 -

export const createOffer = async (peerConnection, receiverId, createdID) => {
  const currentParticipantRef = participantRef.child(receiverId);
  peerConnection.onicecandidate = (event) => {
    event.candidate &&
      currentParticipantRef
        .child("offerCandidates")
        .push({ ...event.candidate.toJSON(), userId: createdID });
  };

  const offerDescription = await peerConnection.createOffer();
  await peerConnection.setLocalDescription(offerDescription);

  const offer = {
    sdp: offerDescription.sdp,
    type: offerDescription.type,
    userId: createdID,
  };

  await currentParticipantRef.child("offers").push().set({ offer });
};

export const initializeListensers = async (userId) => {
  const currentUserRef = participantRef.child(userId);

  currentUserRef.child("offers").on("child_added", async (snapshot) => {
    const data = snapshot.val();
    if (data?.offer) {
      const pc =
        store.getState().participants[data.offer.userId].peerConnection;
      await pc.setRemoteDescription(new RTCSessionDescription(data.offer));
      await createAnswer(data.offer.userId, userId);
    }
  });

  currentUserRef.child("offerCandidates").on("child_added", (snapshot) => {
    const data = snapshot.val();
    if (data.userId) {
      const pc = store.getState().participants[data.userId].peerConnection;
      pc.addIceCandidate(new RTCIceCandidate(data));
    }
  });

  currentUserRef.child("answers").on("child_added", (snapshot) => {
    const data = snapshot.val();
    if (data?.answer) {
      const pc =
        store.getState().participants[data.answer.userId].peerConnection;
      const answerDescription = new RTCSessionDescription(data.answer);
      pc.setRemoteDescription(answerDescription);
    }
  });

  currentUserRef.child("answerCandidates").on("child_added", (snapshot) => {
    const data = snapshot.val();
    if (data.userId) {
      const pc = store.getState().participants[data.userId].peerConnection;
      pc.addIceCandidate(new RTCIceCandidate(data));
    }
  });
};


ii. 답변 만들기 -

const createAnswer = async (otherUserId, userId) => {
  const pc = store.getState().participants[otherUserId].peerConnection;
  const participantRef1 = participantRef.child(otherUserId);
  pc.onicecandidate = (event) => {
    event.candidate &&
      participantRef1
        .child("answerCandidates")
        .push({ ...event.candidate.toJSON(), userId: userId });
  };

  const answerDescription = await pc.createAnswer();
  await pc.setLocalDescription(answerDescription);

  const answer = {
    type: answerDescription.type,
    sdp: answerDescription.sdp,
    userId: userId,
  };

  await participantRef1.child("answers").push().set({ answer });
};


이제 간단한 UI 구성 요소를 만들고 오디오, 비디오 및 화면 공유로 실시간 채팅을 시작할 수 있습니다.

좋은 웹페이지 즐겨찾기