Azure 通信服务 (ACS) 参与者未显示

时间:2021-02-11 06:23:12

标签: reactjs azure azure-communication-services

我遇到了 azure 通信服务远程参与者无法加入的问题...

道歉:复制整个文件以防止混淆

这是我的代码

import React,{createContext, useCallback, useContext, useEffect, useState} from 'react';
import {CallClient, LocalVideoStream} from "@azure/communication-calling";
import { AzureCommunicationUserCredential } from "@azure/communication-common";
import { SessionContext } from './sessionContext';

export const CallingContext = createContext();

const CallingContextProvider = (props) => {
  const {sessionID,currentUser,info,groupID} = useContext(SessionContext)
  const joinAutomaticallyStorage = window.localStorage.getItem("joinAutomatically")
  const [joinAutomatically, setJoinAutomatically] = useState(false);
  const [cameraList, setCameraList] = useState([]);
  const [micList, setMicList] = useState([]);
  const [speakerList, setSpeakerList] = useState([]);
  const [currentCamera, setCurrentCamera] = useState('');
  const [currentMic, setCurrentMic] = useState('');
  const [cameraEnabled, setCameraEnabled] = useState(true);
  const [micEnabled, setMicEnabled] = useState(false);
  const [loadingDevices, setLoadingDevices] = useState(true);
  const [permissionsError, setPermissionsError] = useState(false);
  const [callState, setCallState] = useState('');
  const [callAgent, setCallAgent] = useState();
  const [deviceManager, setDeviceManager] = useState();
  const [localVideoStreams, setLocalVideoStreams] = useState([]);
  const [remoteParticipants, setRemoteParticipants] = useState([]);
  const [call, setCall] = useState();

  const toggleVideo = async() => {
    if (!cameraEnabled && call) {
      const lvs = new LocalVideoStream(currentCamera);
      await call.startVideo(lvs);
      setCameraEnabled(true);
    } else if (cameraEnabled && call) {
      try {
        await call.stopVideo(call.localVideoStreams[0]);
        setCameraEnabled(false);
      } catch (error) {
        console.log(error);
      }
    }
  };

  const toggleMicrophone = async ()=> {
    try {
      if (micEnabled && call) {
        await call.mute();
        setMicEnabled(!micEnabled);
      } else if (!micEnabled && call) {
        await call.unmute();
        setMicEnabled(!micEnabled);
      } else {
        setMicEnabled(!micEnabled);
      }
    } catch (error) {
      console.log(error);
    }
  };

  const joinCall = () => {
    if(callAgent){
      try {
        const call = callAgent.join({groupID},
          {
            videoOptions: {localVideoStreams: cameraEnabled ? [new LocalVideoStream(currentCamera)]: [],},
            audioOptions: {muted: !micEnabled}
          }
        );
        call.on("localVideoStreamsUpdated", localVideoStreamsUpdated);
        call.on('remoteParticipantsUpdated', remoteParticipantsUpdated);
        setCall(call)

        //SAVING TO LOCAL STORAGE CAUSES CRASHING (NEEDS FIXING)

        return window.localStorage.setItem("joinAutomatically",joinAutomatically)
      } catch (error) {
        console.log(error);
        return
      }
    }
    return
  }
  const localVideoStreamsUpdated = useCallback((streams) => {
    console.log(streams);
    setLocalVideoStreams(streams.added);
  },[])

  const remoteParticipantsUpdated = useCallback((incomingRemoteParticipants) => {
    console.log("incomingRemoteParticipants");
    for (const participant of incomingRemoteParticipants.added) {
      participant.on("videoStreamsUpdated", (event) => {
        console.log("videoStreamsUpdate", event);
      });

      participant.on("displayNameChanged", () => {
        console.log("displayNameChanged",participant);
        setRemoteParticipants((remoteParticipants) => {
          const index = remoteParticipants.indexOf(participant);
          return [
            ...remoteParticipants.slice(0, index),
            participant,
           ...remoteParticipants.slice(index + 1)
          ]
        });
      });

      participant.on("participantStateChanged", () => {
        switch (participant.state) {
          case "Connected":
            setRemoteParticipants((remoteParticipants) => [...remoteParticipants,participant]);
            break;
          case "Disconnected":
            setRemoteParticipants((remoteParticipants) => {
              const index = remoteParticipants.indexOf(participant);
              return remoteParticipants.slice(0, index).concat(remoteParticipants.slice(index + 1));
            });
            break;
          default:
            break;
        }
      });

      participant.on("isSpeakingChanged", () => {
        console.log("isSpeakingChanged",participant);
        setRemoteParticipants((remoteParticipants) => {
          const index = remoteParticipants.indexOf(participant);
          return [
            ...remoteParticipants.slice(0, index),
            participant,
           ...remoteParticipants.slice(index + 1)
          ]
        });
      });

      participant.on("isMutedChanged", () => {
        console.log("isMutedChanged",participant);
        setRemoteParticipants((remoteParticipants) => {
          const index = remoteParticipants.indexOf(participant);
          return [
            ...remoteParticipants.slice(0, index),
            participant,
           ...remoteParticipants.slice(index + 1)
          ]
        });
      });
    }
  },[]);
  useEffect(()=>{
    if(info.isVideo){
      setCameraEnabled(true)
    }else{
      setCameraEnabled(false)
    }
  },[info.isVideo])

  useEffect(() => {
    (async()=>{
      let callAgent
      let deviceManager;
      try {
        const tokenCredential = new AzureCommunicationUserCredential(currentUser.token);
        const callClient = new CallClient();
        callAgent = await callClient.createCallAgent(tokenCredential,{displayName:currentUser.username});
        deviceManager = await callClient.getDeviceManager();
        const result = await deviceManager.askDevicePermission(true, true);
        if(!result.audio && !result.video){
          setPermissionsError(true)
          return
        }
        const mics = deviceManager.getMicrophoneList()
        const cams = deviceManager.getCameraList()
        if(!mics.length || !cams.length){
          setPermissionsError(true)
          return
        }
        const speakers = deviceManager.getSpeakerList()
        setSpeakerList(speakers)
        setMicList(mics);
        setCurrentMic(mics[0])
        setCameraList(cams);
        setCurrentCamera(cams[0])
        deviceManager.setMicrophone(mics[0])
        setDeviceManager(deviceManager);
        setLoadingDevices(false)
        setCallAgent(callAgent);
        if(joinAutomaticallyStorage === "true"){
          const call = callAgent.join({groupID},
            {
              videoOptions: {localVideoStreams: cameraEnabled ? [new LocalVideoStream(cams[0])]: [],},
              audioOptions: {muted: !micEnabled}
            }
          );
          call.on("localVideoStreamsUpdated", localVideoStreamsUpdated);
          call.on('remoteParticipantsUpdated', remoteParticipantsUpdated);
          setCall(call)
        }
      } catch {
        if (callAgent) {
          callAgent.dispose();
        }
      }
    })()
    const cleanup=()=>{
      if (callAgent) {
        callAgent.dispose();
        return
      }
    }
    window.addEventListener('beforeunload', cleanup);
    return()=>{
      window.removeEventListener('beforeunload', cleanup);
      cleanup()
    }
    // eslint-disable-next-line
  }, [currentUser.token,currentUser.username,info.isVideo,callAgent,joinAutomaticallyStorage,groupID]);

  useEffect(() => {
    if(cameraEnabled){
      setCurrentCamera(cameraList[0])
    } 
    if(micEnabled){
      setCurrentMic(micList[0])
    }
  }, [micEnabled,cameraEnabled,cameraList,micList]);

  useEffect(()=>{
    if(!callAgent) return;

    callAgent.on('callsUpdated', (e => {
      e.added.forEach(addedCall => {
        addedCall.on('callStateChanged', () => {setCallState(addedCall.state)});
      });
      e.removed.forEach(removedCall => {
        console.log(removedCall);
      });
    }));

    return()=> {
      if (callAgent) {
        callAgent.off('callsUpdated',()=>{})
        callAgent.dispose();
        return
      }
    }
  },[callAgent])

  useEffect(()=>{
    if(!call) return;
    return ()=>{
      call.off('callStateChanged', () => {setCallState(call.state)});
      call.off("localVideoStreamsUpdated", localVideoStreamsUpdated);
      call.off('remoteParticipantsUpdated', remoteParticipantsUpdated);
    }
  },[call,remoteParticipantsUpdated,localVideoStreamsUpdated])

  return (
    <CallingContext.Provider value={{
      sessionID,cameraList,micList,callAgent,isVideo:info.isVideo,
      deviceManager,speakerList,setCurrentCamera,setCurrentMic,cameraEnabled,
      setCameraEnabled,micEnabled, setMicEnabled,currentCamera,currentMic,loadingDevices,permissionsError,
      joinCall,callState,joinAutomatically, setJoinAutomatically,
      username:currentUser.username,
      toggleVideo,toggleMicrophone,
      localVideoStreams,remoteParticipants
    }}>
      {props.children}
    </CallingContext.Provider>
  );
};

export default CallingContextProvider;


本地视频流正常。在 remoteParticipantsUpdated 上根本不触发。我认为是代码的排列方式导致的,但没有得到写入顺序。

这是一个 Context Provider 环绕调用页面并保存重要状态

0 个答案:

没有答案