React+WebRTC+Firebase视频通话ontrack事件未触发求助
React+WebRTC+Firebase视频通话无法触发ontrack接收远程流问题
我正在使用React、WebRTC和Firebase开发视频通话应用,已成功建立本地与远程连接,但无法接收远程MediaStream,ontrack函数始终未触发,不知道原因。
完整代码如下:
import logo from './logo.svg'; import { useEffect, useRef } from 'react'; import './App.css'; import { useState } from 'react'; import { initializeApp } from 'firebase/app' import { addDoc, collection, doc, getDoc, getFirestore, onSnapshot, setDoc, updateDoc } from 'firebase/firestore' function App() { const myVideoRef = useRef(null) const yourVideoRef = useRef(null) const [cameras, setcameras] = useState() const [myCallId, setmyCallId] = useState() const [callId, setcallId] = useState() const [roomId ,setroomId] = useState() const servers = { iceServers: [ { urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'], }, ], iceCandidatePoolSize: 10, } const pc = new RTCPeerConnection(servers) const firebaseConfig = { // 我的配置信息 } const app = initializeApp(firebaseConfig) const db = getFirestore(app) async function getConnectedDevices(type){ const devices = await navigator.mediaDevices.enumerateDevices() return devices.filter(device => device.kind === type) } async function openCamera(cameraId){ const constraints = { 'audio': {'echoCancellation': true}, 'video': { 'deviceId': cameraId, } } navigator.mediaDevices.getUserMedia(constraints) .then((stream) => { stream.getTracks().forEach((track) => { pc.addTrack(track,stream) }) myVideoRef.current.srcObject = stream }) // 这段代码始终不触发 let remoteStream = new MediaStream() pc.ontrack = (event) => { event.streams[0].getTracks().forEach((track) => { remoteStream.addTrack(track) }) } yourVideoRef.current.srcObject = remoteStream } async function call(){ const callDoc = doc(collection(db,"calls")) const offerCandidates = collection(callDoc,"offerCandidates") const answerCandidates = collection(callDoc,"answerCandidates") setmyCallId(callDoc.id) pc.onicecandidate = (event) => { console.log(event.candidate) event.candidate && addDoc(offerCandidates,event.candidate.toJSON()) } const offerDescription = await pc.createOffer() await pc.setLocalDescription(offerDescription) const offer = { sdp: offerDescription.sdp, type: offerDescription.type } await setDoc(callDoc, { offer } ) onSnapshot(callDoc, snapshot => { const data = snapshot.data() if(!pc.currentRemoteDescription && data?.answer){ const answerDescription = new RTCSessionDescription(data.answer) pc.setRemoteDescription(answerDescription) } }) onSnapshot(answerCandidates, snapshot => { snapshot.docChanges().forEach((change) => { if(change.type === 'added'){ console.log(change.doc.data()) const candidate = new RTCIceCandidate(change.doc.data()) pc.addIceCandidate(candidate) console.log(yourVideoRef.current.srcObject) console.log(myVideoRef.current.srcObject) } }) }) } async function answer(){ const callDoc = doc(collection(db,"calls"),callId) const offerCandidates = collection(callDoc,"offerCandidates") const answerCandidates = collection(callDoc,"answerCandidates") pc.onicecandidate = (event) => { event.candidate && addDoc(answerCandidates,event.candidate.toJSON()) } const callData = (await getDoc(callDoc)).data() console.log(callData) const offerDescription = callData.offer await pc.setRemoteDescription(new RTCSessionDescription(offerDescription)) const answerDescription = await pc.createAnswer() await pc.setLocalDescription(answerDescription) const answer = { type: answerDescription.type, sdp: answerDescription.sdp, } await updateDoc(callDoc, {answer}) onSnapshot(offerCandidates, snapshot => { snapshot.docChanges().forEach((change) => { console.log(change) if(change.type === 'added'){ let data = change.doc.data() pc.addIceCandidate(new RTCIceCandidate(data)) } }) }) } useEffect(() => { async function fetch(){ const cameras = await getConnectedDevices('videoinput') setcameras(cameras) } fetch() },[]) return ( <div className="App"> <div className='flex flex-row'> {cameras && cameras.map( camera => <h2 className='m-3' key={camera.deviceId} onClick={() => openCamera(camera.deviceId)} >{camera.label}</h2>)} </div> <div className='flex flex-row'> <video className='w-1/2' ref={myVideoRef} autoPlay /> <video className='w-1/2' ref={yourVideoRef} autoPlay /> </div> <button onClick={call} className='bg-gray-200'>发起通话</button> <div className='flex flex-row'> <input onChange={(e) => setcallId(e.target.value)} className='border-[4px] border-black' placeholder="输入通话ID" /> <button onClick={answer} className='bg-gray-200'>接听通话</button> </div> <h2>我的通话ID:{myCallId}</h2> </div> ); } export default App;
我尝试过将ontrack函数放在useEffect、全局作用域、setRemoteDescription之前,但它仍然无法触发,相关代码片段:
let remoteStream = new MediaStream() pc.ontrack = (event) => { event.streams[0].getTracks().forEach((track) => { remoteStream.addTrack(track) }) } yourVideoRef.current.srcObject = remoteStream
内容的提问来源于stack exchange,提问作者computer
相关产品推荐
相关产品推荐

