如何在 next js 13 的客户端组件中处理 firebase 和 webrtc 任务

问题描述 投票:0回答:1

我创建了一个 next js 13 应用程序来与 webrtc 和 firestore 共享相机源。这是我的 page.tsx。我无法使这个服务端,因为我使用了反应挂钩,并且我无法将其移动到客户端,因为它包含 firestore 和服务器数据。

"use client";

import { useEffect, useRef, useState } from "react";
import { firestore } from "@/services/_configs/firestore";

export default function Page({ params }: { params: { userid: string } }) {

    const servers = {
        iceServers: [
            {
                urls: ['stun:stun1.l.google.com:19302',
                    'stun:stun2.l.google.com:19302']
            }
        ],
        iceCandidatePoolSize: 10,
    }

    const pc = new RTCPeerConnection(servers);

    const [viewerId, setViewerId] = useState('');

    const [localStream, setLocalStream] = useState<MediaStream | null>(null);
    const [remoteStream, setRemoteStream] = useState<MediaStream | null>(null);

    const localVideo = useRef<HTMLVideoElement | null>(null);
    const remoteVideo = useRef<HTMLVideoElement | null>(null);

    useEffect(() => {
        navigator.mediaDevices.getUserMedia({ video: true, audio: true })
            .then((currentStream) => {
                setLocalStream(currentStream);
            });
        setRemoteStream(new MediaStream());

        localStream?.getTracks().forEach((track) => {
            pc.addTrack(track, localStream);
        })

        pc.ontrack = event => {
            event.streams[0].getTracks().forEach((track) => {
                remoteStream?.addTrack(track);
            });
        }

        if (localVideo.current != null && remoteVideo.current != null) {
            localVideo.current.srcObject = localStream;
            remoteVideo.current.srcObject = remoteStream;
        }


    }, []);


    const requestLiveStream = async () => {

        const callDoc = firestore.collection('calls').doc();
        const offerCandidate = callDoc.collection('offerCandidates');
        const answerCandidate = callDoc.collection('answerCandidates');

        setViewerId(callDoc.id);

        pc.onicecandidate = event => {
            event.candidate && offerCandidate.add(event.candidate.toJSON());
        }

        const offerDescription = await pc.createOffer();
        await pc.setLocalDescription(offerDescription);

        const offer = {
            sdp: offerDescription.sdp,
            type: offerDescription.type,
        }

        await callDoc.set({ offer });

        callDoc.onSnapshot((snapshot) => {
            const data = snapshot.data();
            if (!pc.currentLocalDescription && data?.answer) {
                const answerDescription = new RTCSessionDescription(data.answer);
                pc.setRemoteDescription(answerDescription);
            }
        })

        answerCandidate.onSnapshot((snapshot) => {
            snapshot.docChanges().forEach((change) => {
                if (change.type === "added") {
                    const candidate = new RTCIceCandidate(change.doc.data());
                    pc.addIceCandidate(candidate);
                }
            })
        });
    }


    const startLiveStream = async () => {
        const callId = viewerId;
        const callDoc = firestore.collection('calls').doc(callId);
        const offerCandidate = callDoc.collection('offerCandidates');
        const answerCandidate = callDoc.collection('answerCandidates');

        pc.onicecandidate = event => {
            event.candidate && answerCandidate.add(event.candidate.toJSON());
        }

        const callData = (await callDoc.get()).data();

        const offerDescription = callData?.offer;
        await pc.setRemoteDescription(new RTCSessionDescription(offerDescription));

        const answerDescription = await pc.createAnswer();
        await pc.setLocalDescription(answerDescription);

        const answer = {
            sdp: answerDescription.sdp,
            type: answerDescription.type,
        }

        await callDoc.update({ answer });

        offerCandidate.onSnapshot((snapshot) => {
            snapshot.docChanges().forEach((change) => {
                console.log(change);
                if (change.type === "added") {
                    let data = change.doc.data();
                    pc.addIceCandidate(new RTCIceCandidate(data));
                }
            })
        });

    }



    return (
        <div>
            <h1>{viewerId}</h1>
            <input
                type="text"
                value={viewerId}
                onChange={(e) => setViewerId(e.target.value)}
            />
            <button onClick={requestLiveStream}>view live</button>

            <button onClick={startLiveStream}>Answer live</button>
            <video playsInline ref={remoteVideo} autoPlay />
            <br />
            <video playsInline ref={localVideo} autoPlay />
        </div>
    );
}

我收到此错误,我该如何解决。

Module not found: Can't resolve 'net'

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./node_modules/request/request.js

./node_modules/request/index.js

./node_modules/retry-request/index.js

./node_modules/google-gax/build/src/streamingCalls/streaming.js

./node_modules/google-gax/build/src/fallback.js

./node_modules/@google-cloud/firestore/build/src/index.js

./src/services/_configs/firestore.ts

./src/app/app/live/page.tsx

我尝试将 Firestore 代码与另一个代码分开,但我无法这样做,因为我在客户端有 Firestore 数据更改事件。

javascript google-cloud-firestore next.js webrtc
1个回答
0
投票

找到了此代码的解决方案。我正在使用

"@google-cloud/firestore": "^7.1.0"
包。所以它是服务器端包,无法发送到客户端。所以我所做的就是安装
"firebase": "^10.7.1"
包并执行请求。现在可以使用了。我正在使用 Next Js 13,如果您遇到这些错误,请不要安装 net 软件包。看看客户端是否使用了仅服务器包。
    

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