与 PeerJS 反应自动应答对等呼叫

Posted

技术标签:

【中文标题】与 PeerJS 反应自动应答对等呼叫【英文标题】:React with PeerJS Automatically Answering a Peer Call 【发布时间】:2021-12-10 08:37:37 【问题描述】:

我正在尝试构建一个用户呼叫用户然后其他用户自动接受呼叫的应用程序。

目前我将它作为一个按钮说“接听”(接到电话时),然后用户单击此按钮将开始视频通话,但我该如何让它自动回答而无需用户点击这个按钮?

export default function Board() 
    const [me, setMe] = useState("")
    const [stream, setStream] = useState()
    const [receivingCall, setReceivingCall] = useState(false)
    const [caller, setCaller] = useState("")
    const [callerSignal, setCallerSignal] = useState()
    const [callAccepted, setCallAccepted] = useState(false)
    const [idToCall, setIdToCall] = useState("")
    const [callEnded, setCallEnded] = useState(false)
    const [name, setName] = useState("")
    const [randomId, setRandomId] = useState(null)

    const myVideo = useRef()
    const userVideo = useRef()
    const connectionRef = useRef()

    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)
        )
    , [])

    const getRandomId = () => 
    

    const callUser = async (id) => 

        axios.post("http://localhost:5000/ex2", 
            me
        ).then(resp => 
            setRandomId(resp.data)
        )

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

        peer.on("signal", (data) => 
            socket.emit("callUser", 
                userToCall: 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
    

    const changeCall = () => 

    

    const answerCall = () => 
        setCallAccepted(true)
        const peer = new Peer(
            initiator: false,
            trickle: false,
            stream: stream
        )
        peer.on("signal", (data) => 
            socket.emit("answerCall",  signal: data, to: caller )
        )
        peer.on("stream", (stream) => 
            userVideo.current.srcObject = stream
        )

        peer.signal(callerSignal)
        connectionRef.current = peer
    

    const leaveCall = () => 
        setCallEnded(true)
        connectionRef.current.destroy()
    

    const videoDimensions = 
        objectFit: "cover"
    

    return (
        <div className="">
            <div className="video-container">
                <div className="video">
                    stream && <video playsInline muted ref=myVideo autoPlay style=videoDimensions />
                </div>
                <div className="video">
                    callAccepted && !callEnded ?
                        <video playsInline muted ref=userVideo autoPlay style=videoDimensions /> :
                        null
                </div>
            </div>
            <div className="myId">
                <input placeholder="name" onChange=(e) => setName(e.target.value)></input>

                <p>me</p>

                <input placeholder="to call" onChange=(e) => setIdToCall(e.target.value)></input>

                <div className="call-button">
                    callAccepted && !callEnded ? (
                        <button onClick=leaveCall>
                            End Call
                        </button>
                    ) : (
                        <button color="primary" aria-label="call" onClick=() => callUser(idToCall)>
                            call
                        </button>
                    )
                    idToCall
                </div>
            </div>
            <div>
                receivingCall && !callAccepted ? (
                    <div className="caller">
                        <h1 >name is calling...</h1>
                        <button id="answerButton" variant="contained" color="primary" onClick=answerCall>
                            Answer
                        </button>
                    </div>
                ) : null
            </div>


        </div>
    )

我尝试将“answerCall”函数放在“callUser”正文的末尾,但它给出了以下错误:

Unhandled Rejection (TypeError): Cannot read properties of undefined (reading 'renegotiate')

我只是想给一个用户打电话,然后其他用户自动接听,而无需他们手动点击“接听”按钮。

【问题讨论】:

【参考方案1】:

您是否查看过名为 Livekit.io 的开源项目?

它自称为“一个开源项目,可通过 WebRTC 提供可扩展的多用户会议。它旨在为您提供在应用程序中构建实时音频和/或视频体验所需的一切。”

他们的文档在这里:https://docs.livekit.io/

【讨论】:

以上是关于与 PeerJS 反应自动应答对等呼叫的主要内容,如果未能解决你的问题,请参考以下文章

如何在PeerJS中的呼叫者和接收者之间发送数据?

peerjs 在 loaclhost 上工作,但不在 heroku 上?

呼叫中心如何实现智能化办公?

在 React Native 中使用 Peerjs 进行多个视频通话(n 个用户)

人机协同与AI能力训练

托管和部署 peerjs 服务器