You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+PeerJS 实现点对点通话自动接听功能的问题咨询

点对点通话自动接听实现方案

错误根因说明

你之前触发的Cannot read properties of undefined (reading 'renegotiate')报错,是因为逻辑位置放错了:
answerCall是被叫侧收到呼叫请求后执行的接听逻辑,你把它放到主叫侧的callUser函数末尾,此时主叫侧根本没有callerSignal、caller这些被叫侧才有的参数,调用peer.signal()时传了空值才会触发报错。

实现自动接听的修改步骤

1. 修改被叫侧呼叫请求监听逻辑

找到useEffect里的socket.on("callUser")监听回调,修改为收到呼叫后,确认媒体流已获取就直接调用answerCall,不需要等待用户点击按钮。

2. 修复原有代码的异步bug

你原来的callUser函数里axios.post请求后直接用randomId拿不到最新值,因为useState的更新是异步的,需要直接用请求返回的结果,避免呼叫请求发空ID。

完整修改后的代码片段

修改后的useEffect部分

useEffect(() => {
    navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((stream) => {
        setStream(stream)
        myVideo.current.srcObject = stream
    })

    socket.on("me", (id) => {
        setMe(id)
        axios.post("http://localhost:5000/ex", {
            displayName: firebase.auth().currentUser.displayName,
            me: id
        })
            .then(resp => console.log("Me =", resp.data))
    })

    socket.on("callUser", (data) => {
        setReceivingCall(true)
        setCaller(data.from)
        setName(data.name)
        setCallerSignal(data.signal)
        // 新增:确认媒体流已加载后自动接听
        if(stream) {
            answerCall()
        }
    })
}, [stream]) // 新增stream作为依赖,确保能拿到最新的流状态

修改后的callUser函数

const callUser = async (id) => {
    // 修复异步问题,直接用请求返回的id
    const resp = await axios.post("http://localhost:5000/ex2", {
        me
    })
    const targetId = resp.data
    setRandomId(targetId)

    const peer = new Peer({
        initiator: true,
        trickle: false,
        stream: stream
    })

    peer.on("signal", (data) => {
        socket.emit("callUser", {
            userToCall: targetId, // 直接用请求返回的结果,不用state里的randomId
            signalData: data,
            from: me,
            name: firebase.auth().currentUser.displayName
        })
    })

    peer.on("stream", (stream) => {
        userVideo.current.srcObject = stream
    })

    socket.on("callAccepted", (signal) => {
        setCallAccepted(true)
        peer.signal(signal)
    })

    connectionRef.current = peer
}

注意事项

  • 如果你需要保留手动接听的入口,只需要给自动接听的逻辑加开关控制即可,不需要删除原有Answer按钮。
  • 部分浏览器会要求音视频通话必须有用户交互触发,如果你碰到自动接听时媒体流加载失败,可以提前在页面加载后加一个简单的用户交互引导(比如进入页面前点击"进入"按钮),获取交互权限后就可以正常自动接听。

内容的提问来源于stack exchange,提问作者KylianMbappe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 15:36:01