iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0

在點對點連接前需要先收集 ICE 找到最適合的連線方式再交換 SPD 資訊,上篇先完成了 SDP 交換,接著這篇會完成 ICE 候選人的收集。

collectIceCandidates 處理 ICE

  • 建立負責收集 ICE 候選人的 function
  • 在 db 建立 host、guest 各自的 collection 並放入各自的 ICE 候選人,就像下圖👇👇👇, document 的同層級可以加入 collection
  • onicecandidateRTCIceCandidate 方法 toJSON() 將調用它的 轉換為 JSON,addDoc 加入
  • onicecandidateerror:處理收集到的每個候選人若有錯誤時觸發
  • 監聽 remote 當有 docChange 時,獲取的 ICE 候選者數據轉換為 RTCIceCandidate 對象,然後添加到 RTCPeerConnection 中

https://ithelp.ithome.com.tw/upload/images/20231004/201511248LZOP9tJ1y.png

async function collectIceCandidates(
  roomRef,
  peerConnection,
  localName,
  remoteName
) {
  // callerCandidates 存儲本地 ICE 候選者
  const candidatesCollection = collection(roomRef, localName);

  try {
    // 當收集到一個本地 ICE 候選者時,將觸發這個事件
    peerConnection.onicecandidate = async (event) => {
      // 如果事件中存在候選者,則將其轉換為 JSON 對象並添加到 candidatesCollection 中
      if (event.candidate) {
        console.log(event);
        await addDoc(candidatesCollection, event.candidate.toJSON());
      }
    };

    // 收集到一個本地 ICE 候選者時錯誤則觸發
    peerConnection.onicecandidateerror = (error) => {
      console.log("error", error);
    };

    // 監聽 calleeCandidates 裡的每個 doc
    const remoteCandidatesCollection = collection(roomRef, remoteName);
    onSnapshot(remoteCandidatesCollection, (snapshot) => {
      snapshot.docChanges().forEach(async (change) => {
        if (change.type === "added") {
          // 對於每個新增的遠程 ICE 候選者,將其轉換為 RTCIceCandidate
          const data = change.doc.data();
          await peerConnection.addIceCandidate(new RTCIceCandidate(data));
        }
      });
    });
  } catch (error) {
    console.error(error);
  }
async function createRoom() {
    // 創建一個新的 RTCPeerConnection
    if (!localStream.current) {
        alert('請先開啟視訊及麥克風');
        return;
    }
    const pc = new RTCPeerConnection(configuration);

    // 創建房間
    const roomRef = await addDoc(collection(db, "rooms"), {});
    const roomId = roomRef.id;
    window.alert(roomId);

    collectIceCandidates(roomRef, pc, "calleeCandidates", "callerCandidates")
		
		// 略...
}
async function joinRoom(roomId) {
    if (!localStream.current) {
        alert('請先開啟視訊及麥克風');
        return;
    }
 
	   // 取的輸入 id 的 room
    const roomRef = doc(db, "rooms", roomId);
    const roomSnapshot = await getDoc(roomRef);

    // 創建一個新的 RTCPeerConnection
    if (roomSnapshot.exists()) {
      const pc = new RTCPeerConnection(configuration);

      collectIceCandidates(roomRef, pc, "callerCandidates", "calleeCandidates")
			
			// 略...
		}
}

https://ithelp.ithome.com.tw/upload/images/20231004/20151124mEieLAJ00P.png

這篇完成了 ICE 候選人的新增與交換,從 Firebase db 可以看到 await addDoc(candidatesCollection, event.candidate.toJSON()),下篇就把我們交換後的資訊將遠端stream render 到畫面上。


上一篇
[Day21] 實作 - WebRTC SDP Offer 和 Answer 交換
下一篇
[Day23] 實作 - WebRTC 遠端視訊顯示
系列文
前端工程師30天 WebRTC + Firebase 視訊通話原理到實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言