首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >灵丹妙药- MembraneWebRTC / React: MediaStreams在一个客户端为非空,而在另一个客户端为null &均未出现。

灵丹妙药- MembraneWebRTC / React: MediaStreams在一个客户端为非空,而在另一个客户端为null &均未出现。
EN

Stack Overflow用户
提问于 2022-08-24 00:40:38
回答 1查看 126关注 0票数 3

我正在扩展视频教程中使用的客户端,但是我无法让远程流出现在客户机上--要么流为null,要么流为非空&没有显示任何内容。

代码语言:javascript
复制
const useGala = roomId => {
    const { socket } = useContext(SocketContext);
    const permChannel = socket.channel(`room:${roomId}`);

    const [gala, setGala] = useState({
        channel: permChannel,
        localStream: null, 
        peers: [],
        streams: [],
        webrtcEngine: null,
        initialized: false,
    });

    const joinWebrtc = async (engine) => {
        engine.join({ displayName: "Will" });
    }

    const createLocalStream = async (engine) => {
        const localStream = await navigator.mediaDevices.getUserMedia(MEDIA_CONSTRAINTS);
        localStream.getTracks().forEach((track) => {
            engine.addTrack(track, localStream)
        });
        setGala(prev => ({ ...prev, localStream: localStream }));
    }

    const makeEngine = async () => {
        // Create the WebRTC engine
        const engine = new MembraneWebRTC({
            callbacks: {
                onSendMediaEvent: (mediaEvent) => {
                    console.log('gala:onSendMediaEvent: fired');
                    gala.channel.push("mediaEvent", { data: mediaEvent });
                },
                onConnectionError: () => {
                    console.log('on connection error triggered')
                },
                onJoinSuccess: (peerId, peersInRoom) => {
                    console.log("gala:onJoinSuccess: fired");
                    setGala(prev => ({ ...prev, peers: peersInRoom }));
                    createLocalStream(engine);
                },
                onJoinError: (metadata) => {
                    throw `Peer denied.`;
                },
                onTrackReady: ({ stream, peer, metadata }) => {
                    console.log("gala:onTrackReady: fired");
                    const inboundStream = { peerId: `${peer.id}`, stream: stream };
                    // This fires, but the `stream` object is either 
                    // 1. null if on the already joined client
                    // 2. non-null if on the newly joined client
                    setGala(prev => ({
                        ...prev,
                        streams: [...prev.streams, inboundStream]
                    }));
                },
                onTrackAdded: (ctx) => {
                    console.log("hook:onTrackAdded: fired");
                    console.log(ctx);
                },
                onTrackRemoved: (ctx) => { },
                onPeerJoined: (peer) => {
                    console.log("hook:onPeerJoined: fired");

                    setGala(prev => {
                        return {
                            ...prev,
                            peers: [...prev.peers, peer]
                        }
                    });
                },
                onPeerLeft: (peer) => {
                    console.log("hook:onPeerLeft: fired");

                    setGala(prev => {
                        const remainingPeers = prev.peers.filter((p) => p.id !== peer.id);
                        return {
                            ...prev,
                            peers: remainingPeers
                        }
                    });
                },
                onPeerUpdated: (ctx) => { },
            }
        });

        return engine;
    }

    const otherStuff = async (engine) => {
        if (gala.channel.state === 'joined' && !!engine) {
            // Setup a tracker for inbound media
            gala.channel.on("mediaEvent", (event) => {
                // For already-joined client, does not fire if new peer joins
                // For new peer, fires
                engine.receiveMediaEvent(event.data)
            });

            setGala(prev => ({
                ...prev,
                initialized: true,
                webrtcEngine: engine
            }))
        }
    }

    const doEverything = async () => {
        let engine;
        if (!gala.webrtcEngine) {
            engine = await makeEngine();
        }

        // Join the server with the new stream
        const phoenixChannelPushResult = async (push) => {
            return new Promise((resolve, reject) => {
                push
                    .receive("ok", (response) => resolve(response))
                    .receive("error", (response) => reject(response));
            });
        };

        if (gala.channel.state !== 'joining' && gala.channel.state !== 'joined' && (!!engine || gala.webrtcEngine)) {
            await phoenixChannelPushResult(gala.channel.join());
            if (engine) {
                await joinWebrtc(engine);
                return engine
            } else {
                return gala.webrtcEngine;
            }
        }

    }

    const all = useCallback(async () => {
        doEverything()
            .then(engine => otherStuff(engine));
    }, [gala.channel]);

    const doStuffWithChannel = useCallback(async () => {
        if (gala?.streams?.length > 0) {
            // Setup a tracker for inbound media
            // Set this up to see if it would fire, but nothing
            gala.channel.on("mediaEvent", (event) => {
                gala.webrtcEngine.receiveMediaEvent(event.data)
            });
        }
    }, [gala.streams, gala.channel]);

    useEffect(() => {
        if (!socket) return;
        all();
        doStuffWithChannel();
    }, [socket]);

    return gala;
}

我将获取所有gala.streams条目并将它们加载到MediaElement中。即使streams是非空的,也不会出现:

代码语言:javascript
复制
const MediaElement = ({ peerId, gala }) => {
    const audioRef = useRef();
    const videoRef = useRef();

    useEffect(() => {
        if (gala?.streams?.length > 0) {
            audioRef.current.srcObject = gala?.streams[gala?.streams?.length - 1]?.stream;
            videoRef.current.srcObject = gala?.streams[gala?.streams?.length - 1]?.stream;
        }
    }, [gala?.streams, gala.channel, gala.webrtcEngine]);

    return (
        <div className='col-span-full col-start-3 row-span-3' key={peerId}>
            <p className='text-white'>{peerId}</p>
            <audio id={`audio-${peerId}`} ref={audioRef} volume="true" autoPlay></audio>
            <video id={`video-${peerId}`} ref={videoRef} playsInline autoPlay></video>
        </div>
    );
}

export default MediaElement;

我相信这个错误与我如何管理webRtcEngine的状态有关,因为这是与普通的JavaScript示例的关键区别。

不过,我不知道怎么解决这个问题。我怎样才能让MediaStreams出现?

EN

回答 1

Stack Overflow用户

发布于 2022-08-31 13:33:59

我会写这个作为评论,但我没有足够的声誉。

乍一看,您的代码似乎没有问题。这可能是一个反应(某种种族条件)的问题,而不是membrane-webrtc

但是,有一个问题:为什么您只加载最后一个流?

代码语言:javascript
复制
    useEffect(() => {
            if (gala?.streams?.length > 0) {
                audioRef.current.srcObject = gala?.streams[gala?.streams?.length - 1]?.stream;
                videoRef.current.srcObject = gala?.streams[gala?.streams?.length - 1]?.stream;
            }
        }, [gala?.streams, gala.channel, gala.webrtcEngine]);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73466295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档