我在使用 WebRTC 对等连接实现视频通话时遇到问题

问题描述 投票:0回答:1
import {
    mediaDevices,
    RTCPeerConnection,
    RTCView,
    RTCIceCandidate,
    RTCSessionDescription,
    MediaStream,
} from 'react-native-webrtc';

import styles from './callPageStyle';
import { useEffect, useState, useRef } from "react";

const CallPage = ({ route, navigation }) => {

// const navigation = useNavigation();
const userData = useSelector((state) => state.userData);
const dispatch = useDispatch();

const { callerId, calleeId, calleeName, isVideo, isCreator } = route.params;

const [localStream, setLocalStream] = useState(null);
const [remoteStream, setRemoteStream] = useState(null);
const [callStarted, setCallStarted] = useState(false);
const peerConnectionRef = useRef(null);
const remoteRTCMessage = useRef(null);

useEffect(() => {
    const recipientID = isCreator ? calleeId : callerId;
    webSocketService.registerSendCallMessageCallback(recipientID, onNewCall);
    webSocketService.registerAnswerCallMessageCallback(recipientID, onCallAnswered);
    webSocketService.registerICECandidateMessageCallback(recipientID, onICEcandidate);

    const initLocalStream = async () => {
        const stream = await mediaDevices.getUserMedia({ audio: true, video: true });
        setLocalStream(stream);
    };

    const delayProcessCall = setTimeout(() => {
        if (!isCreator) {
            startCall();
        } else {
            initLocalStream();
        }
    }, 2000);

    return () => {
        clearTimeout(delayProcessCall);

        if (localStream) {
            localStream.getTracks().forEach((track) => track.stop());
        }
    };
}, []);


const createPeerConnection = async () => {
    const configuration = {
      iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        { urls: 'stun:stun1.l.google.com:19302' },
        { urls: 'stun:stun2.l.google.com:19302' },
      ],
    };
    const peerConnection = new RTCPeerConnection(configuration);
  
    // Use a promise to wait for getUserMedia to complete
    const stream = await mediaDevices.getUserMedia({ audio: true, video: true });
    stream.getTracks().forEach((track) => peerConnection.addTrack(track, stream));
    setLocalStream(stream);
  
    return new Promise((resolve) => {
        peerConnection.onicecandidate = (event) => {
            if (event.candidate) {
            webSocketService.sendICECandidateToPeerServer(userData.id, isCreator ? calleeId : callerId, {
                calleeId: isCreator ? calleeId : callerId,
                rtcMessage: {
                label: event.candidate.sdpMLineIndex,
                id: event.candidate.sdpMid,
                candidate: event.candidate.candidate,
                },
            });
            } else {
                console.log("End of candidates.");
            }
        };
    
        peerConnection.ontrack = (event) => {
            setRemoteStream(event.streams[0]);
        };
    
        peerConnectionRef.current = peerConnection;
        resolve();
    });
};

const startCall = async () => {    
    try {
        console.log("=========sendNewCallToPeerServer===========");
        await createPeerConnection();

        const offer = await peerConnectionRef.current.createOffer();
        await peerConnectionRef.current.setLocalDescription(offer);

        webSocketService.sendNewCallToPeerServer(userData.id, isCreator ? calleeId : callerId, {
            calleeId: isCreator ? calleeId : callerId,
            rtcMessage: offer,
        });

        console.log("=========sendNewCallToPeerServer===========");
    } catch (error) {
      console.error('Error creating offer:', error);
    }
};

const handleAnswer = async () => {    
    try {
        const answer = await peerConnectionRef.current.createAnswer();
        await peerConnectionRef.current.setLocalDescription(answer);

        webSocketService.sendAnswerCallToPeerServer(userData.id, isCreator ? calleeId : callerId, {
            calleeId: isCreator ? calleeId : callerId,
            rtcMessage: answer,
        });

        setCallStarted(true);
    } catch (error) {
        console.error('Error creating answer:', error);
    }
};

const onNewCall = async (payload) => {
    console.log("On New Call !!!");
    const bigData = JSON.parse(payload.body);
    const data = JSON.parse(bigData.data);

    remoteRTCMessage.current = data.rtcMessage;

    await createPeerConnection();
    peerConnectionRef.current.setRemoteDescription(
        new RTCSessionDescription(remoteRTCMessage.current)
    );

    handleAnswer();
};

const onCallAnswered = (payload) => {
    console.log("onCallAnswered !!!");
    const bigData = JSON.parse(payload.body);
    const data = JSON.parse(bigData.data);
    
    remoteRTCMessage.current = data.rtcMessage;
    peerConnectionRef.current.setRemoteDescription(
        new RTCSessionDescription(remoteRTCMessage.current)
    );

    setCallStarted(true);
};

const onICEcandidate = (payload) => {
    console.log("onICEcandidate !!!");
    const bigData = JSON.parse(payload.body);
    const data = JSON.parse(bigData.data);

    let message = data.rtcMessage;

    if (peerConnectionRef.current) {
        peerConnectionRef.current
        .addIceCandidate(new RTCIceCandidate({candidate: message.candidate, sdpMLineIndex: message.label, sdpMid: message.id}))
        .then((data) => {
            console.log("SUCCESS");
        })
        .catch((err) => {
            console.log("Error", err);
        });
    }
};

这是我在react-native expo应用程序中实现视频通话功能的源代码。

我目前正在使用下面的react-native-webrtc库。

@config-plugins/react-native-webrtc": "^7.0.0

react-native-webrtc": "^111.0.3
,

我正在使用这样的Android模拟器:

  • API 级别 34
  • 图像:系统图像/android-34/google_apis/x86_x64

在对等点之间建立连接的所有逻辑都运行良好。但视频流有问题。 帮助我纠正源代码或提供任何建议。 谢谢。

javascript react-native expo webrtc rtcpeerconnection
1个回答
0
投票

我以前也遇到过这样的问题。 使用WebRTC流实现视频通话包含这样一个复杂的过程。 有更简单的方法来实现视频通话,而无需使用基本库。 我建议在 React Native 中使用“agora-rn-uikit”库。

更多详细说明在这里:

https://www.npmjs.com/package/agora-rn-uikit

安装命令:

npm i react-native-agora agora-react-native-rtm agora-rn-uikit

示例代码:

const connectionData = {
    appId: '<Agora App ID>',
    channel: 'test',
};
const rtcCallbacks = {
    EndCall: () => setVideoCall(false),
};

<AgoraUIKit connectionData={connectionData} rtcCallbacks={rtcCallbacks} />

使用方便,开发速度更快。

© www.soinside.com 2019 - 2024. All rights reserved.