Skip to content

Commit

Permalink
test pass candidate process
Browse files Browse the repository at this point in the history
  • Loading branch information
bin-r00t committed Jun 11, 2024
1 parent 8c4d0af commit bff5c45
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 125 deletions.
1 change: 1 addition & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function App() {
const remoteVideoRef = useRef(null);
// helper functions
const saveSocket = useCallback(function saveSocket(s) {
console.log('[App] save socket', s);
socket.current = s;
}, []);
// const loadLocalVideo = useCallback(function loadLocalVideo(stream) {})
Expand Down
75 changes: 75 additions & 0 deletions src/hooks/useMedia.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { useEffect, useState } from "react";
import { setPeerConnection, setStream, peerConnection } from "../utils/media";
import { useSelector } from "react-redux";

const configuration = {
iceServers: [
{
urls: [
"stun:stunserver.org",
"stun:stun.voiparound.com",
"stun:stun.voipbuster.com",
"stun:stun.voipstunt.com",
"stun:stun.voxgratia.org",
],
},
],
// sdpSemantics: "plan-b",
};

function useMedia(videoRef, socket) {
console.log("[useMedia] socket--", socket);
const { role } = useSelector((state) => state.media);

useEffect(() => {
const initPeerConnection = async () => {
if (peerConnection == null) {
console.log("create total new peer connection....");
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
// audio: true,
});

// save local stream
videoRef.current.srcObject = stream;
setStream(stream);

// create peer connection
const peerConnection = new RTCPeerConnection(configuration);
// add tracks
stream.getTracks().forEach((track) => {
peerConnection.addTrack(track, stream);
});

// save peer connection
setPeerConnection(peerConnection);
}

function onCandidate(event) {
if (event.candidate) {
console.log("iceCandidate", event.candidate);
// emit candidate
socket.current.emit(
`candidate::${role == "" ? "initiator" : role}`,
event.candidate
);
}
}
console.log("[useMedia] set onCandidate...");
peerConnection.onicecandidate = onCandidate;
// peerConnection.addEventListener("icecandidate", (event) => {
// if (event.candidate) {
// console.log("iceCandidate", event.candidate);
// // emit candidate
// socket.emit(
// `candidate::${role == "" ? "initiator" : role}`,
// event.candidate
// );
// }
// });
};
initPeerConnection();
}, [role, socket]);
}

export default useMedia;
21 changes: 10 additions & 11 deletions src/pages/Room/Layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ import { useEffect, useRef, useState, useContext } from "react";
import { Modal } from "../../components/Modal";
import VideoWrapper from "./VideoWrapper";
import VideoActions from "./Actions";
import { initSocket } from "../../utils/socket";
import { initSocket, registerMoreEvents } from "../../utils/socket";
import { GlobalContext } from "../../App";
import ParticipantsList from "./ParticipantsList";
// import { initWebRtc } from "../peer.tools";
// import { useDispatch, useSelector } from "react-redux";
// import { setPeerConnection } from "../../store/index";
import { useDispatch, useSelector } from "react-redux";

export default function Room() {
const dispatch = useDispatch();
const { socket, saveSocket } = useContext(GlobalContext);
const { roomId } = useParams();
const dialogRef = useRef();
Expand All @@ -24,13 +23,13 @@ export default function Room() {
if (username.value == "") {
dialogRef.current.open();
}
saveSocket(initSocket("https://10.168.1.141:8000", { token: roomId }));

// async function prepare() {
// const peerConnection = await initWebRtc();
// dispatch(setPeerConnection(peerConnection));
// }
// prepare();
const socket = initSocket(
"https://10.168.1.141:8000",
{ token: roomId },
dispatch
);
registerMoreEvents(socket);
saveSocket(socket);
}, []);

function handleSetName() {
Expand Down
41 changes: 8 additions & 33 deletions src/pages/Room/VideoWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,45 +22,20 @@ import {
ArrowDownTrayIcon,
} from "@heroicons/react/24/solid";
//
import { useEffect, useRef, useState } from "react";
import { initWebRtc } from "../peer.tools";
import { useDispatch, useSelector } from "react-redux";
import { handleStartNegotiation } from "../../utils/socket";
import { useContext } from "react";
import { GlobalContext } from "../../App";
import useMedia from "../../hooks/useMedia";

export default function Room({}) {
export default function VideoWrapper({}) {
const { localVideoRef, remoteVideoRef, socket } = useContext(GlobalContext);
const localStream = useRef();
const remoteStream = useRef();

useEffect(() => {
setTimeout(() => {
console.log("localVideoRef", localVideoRef.current);
console.log("remoteVideoRef", remoteVideoRef.current);
}, 2000);
async function prepare() {
// peerConnection cannot be saved to redux store
// dispatch(setPeerConnection(peerConnection)); is NOT allowed
const peerConnection = await initWebRtc({
ref: localVideoRef,
stream: null,
});
console.log("socket", socket);
// TODO:此处而言, negotiation::start 注册太晚了... 在 socket.js 中注册又太早
socket.current.on("negotiation::start", () => {
console.log("start negotiation");
});

console.log("peerConnection -->", peerConnection);
}
prepare();
}, []);
// 初始化 peer connection
console.log('[VideoWrapper] ', socket);
useMedia(localVideoRef, socket);

function togglePlay() {
selfVideoRef.current.paused
? selfVideoRef.current.play()
: selfVideoRef.current.pause();
localVideoRef.current.paused
? localVideoRef.current.play()
: localVideoRef.current.pause();
}
return (
<section className="main-area flex-1 flex justify-center items-center gap-10">
Expand Down
59 changes: 33 additions & 26 deletions src/pages/peer.tools.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,7 @@
function sendOfferToPeer(socket, offer) {
console.log("Sending offer to peer");
socket.emit("offer", { offer });
}

function sendAnswerToPeer(socket, answer) {
console.log("Sending answer to peer");
socket.emit("answer", { answer });
}

function sendIceCandidateToPeer(socket, iceCandidate) {
console.log("Sending ICE candidate to peer");
socket.emit("ice-candidate", { iceCandidate });
}

function receiveOffer(socket, offer, peerConnection) {
console.log("Receiving offer from peer");
peerConnection.setRemoteDescription(offer);
}
import { setPeerConnection } from "../utils/media";

function receiveAnswer(socket, answer, peerConnection) {
console.log("Receiving answer from peer");
peerConnection.setRemoteDescription(answer);
}

export async function initWebRtc(selfVideo) {
export async function initWebRtc(selfVideo, socket) {
console.log("init webrtc ", selfVideo);
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
// audio: true,
Expand All @@ -49,9 +27,38 @@ export async function initWebRtc(selfVideo) {
peerConnection.addEventListener("icecandidate", (event) => {
if (event.candidate) {
console.log("iceCandidate", event.candidate);
// inject
socket.emit("candidate::initiator", event.candidate);
}
});
setPeerConnection(peerConnection);
// const offer = await peerConnection.createOffer();
// peerConnection.setLocalDescription(offer);
return peerConnection;

// return peerConnection;
}

// function sendOfferToPeer(socket, offer) {
// console.log("Sending offer to peer");
// socket.emit("offer", { offer });
// }

// function sendAnswerToPeer(socket, answer) {
// console.log("Sending answer to peer");
// socket.emit("answer", { answer });
// }

// function sendIceCandidateToPeer(socket, iceCandidate) {
// console.log("Sending ICE candidate to peer");
// socket.emit("ice-candidate", { iceCandidate });
// }

// function receiveOffer(socket, offer, peerConnection) {
// console.log("Receiving offer from peer");
// peerConnection.setRemoteDescription(offer);
// }

// function receiveAnswer(socket, answer, peerConnection) {
// console.log("Receiving answer from peer");
// peerConnection.setRemoteDescription(answer);
// }
41 changes: 0 additions & 41 deletions src/pages/useMedia.js

This file was deleted.

22 changes: 20 additions & 2 deletions src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { configureStore, createSlice } from "@reduxjs/toolkit";
import { createOffer } from '../utils/media'

// media 相关 API
// getSenders()
// replaceTrack()
// getTracks()
// setSinkId() - change audio output
// getCapabilities()
// pc.addIceCandidate()

// Keywords:
// Switching cameras in WebRTC
Expand All @@ -18,7 +21,8 @@ const mediaSlice = createSlice({
videoDeviceId: "default", // 当前选中的视频设备id
audioInputDeviceId: "default", // 当前选中的音频输入设备id
audioOutputDeviceId: "default", // 当前选中的音频输出设备id

role: "", // 当前角色,用于区分 offer/answer
offer: null,
// 用于获取媒体流的约束条件,会随着选择而更新, replaceTrack()
// 更换tracks的时候,是需要重新negotiation的, 也就是需要重新 createOffer
constraints: {
Expand Down Expand Up @@ -56,6 +60,13 @@ const mediaSlice = createSlice({
break;
}
},
setRole(state, action) {
state.role = action.payload;
},
setOffer(state, action) {
state.offer = action.payload;
state.role = 'initiator'; // <=== 这里设置角色
},
},
});

Expand All @@ -65,6 +76,13 @@ const store = configureStore({
},
});

export function setOfferCreator() {
return async (dispatch) => {
const offer = await createOffer();
dispatch(mediaSlice.actions.setOffer(offer));
};
}

export default store;
export const { setLocalStream, addRemoteStream, setDevice } =
export const { setLocalStream, addRemoteStream, setDevice, setRole, setOffer } =
mediaSlice.actions;
14 changes: 13 additions & 1 deletion src/utils/media.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// variables - those variables cannot be put into redux
// let remoteStream = null;
let peerConnection = null;
export let peerConnection = null;
let localStream = null;
let remoteStreams = [];

Expand Down Expand Up @@ -33,5 +33,17 @@ export function setStream(source, stream) {
}

export function setPeerConnection(pc) {
console.log("setPeerConnection", pc);
peerConnection = pc;
}

export async function createOffer() {
if (peerConnection) {
const offer = await peerConnection.createOffer();
peerConnection.setLocalDescription(offer);
console.log("setLocalDescription", offer);
return offer;
}
console.log("peerConnection is NULL");
return null;
}
Loading

0 comments on commit bff5c45

Please sign in to comment.