Agora视频呼叫Webrtc do react和laravel的展示

发布于 2025-01-22 15:28:01 字数 10818 浏览 0 评论 0原文

我正在研究React和Laravel项目,我想在视频通话中实施用户互相呼叫和联合的能力。我已经按照他们的文档指示实现了所有代码,并且我使用Laravel后端来生成令牌。显然,一切都起作用了,我没有任何错误。但是,我的相机打开了,但是在屏幕上没有显示本地流(视频)。我怀疑我的React代码有问题:

import React, { useEffect, useState, useRef } from "react";
import { connect } from "react-redux";
import Echo from "laravel-echo";
import axios from "axios";
import AgoraRTC from "agora-rtc-sdk";
import styles from "./css/settingspace.module.css";

const AGORA_ID = "my app id copyed from agora website";

const VideoCallPage = (props) => {
  const [agoraConnection, setAgoraConnection] = useState({
    callPlaced: false,
    mutedAudio: false,
    mutedVideo: false,
    userOnlineChannel: null,
    onlineUsers: [],
    incomingCall: false,
    incomingCaller: "",
    agoraChannel: null,
  });

  const client = useRef(null);
  const localStream = useRef(null);

  useEffect(() => {
    const initUserOnlineChannel = () => {
      console.log("Initiate User Online Channel");
      setAgoraConnection((prevAgoraConnection) => ({
        ...prevAgoraConnection,
        userOnlineChannel: window.Echo.join("agora-online-channel"),
      }));
      console.log("Initiate User Online Channel - Finished");
    };

    const initUserOnlineListeners = () => {
      console.log("Initiate User Online Listeners");
      agoraConnection.userOnlineChannel.here((users) => {
        setAgoraConnection((prevAgoraConnection) => ({
          ...prevAgoraConnection,
          onlineUsers: users,
        }));
      });
      agoraConnection.userOnlineChannel.joining((user) => {
        // check user availability
        const joiningUserIndex = agoraConnection.onlineUsers.findIndex(
          (data) => data.id === user.id
        );
        if (joiningUserIndex < 0) {
          setAgoraConnection((prevAgoraConnection) => ({
            ...prevAgoraConnection,
            onlineUsers: [...agoraConnection.onlineUsers, user],
          }));
        }
      });
      agoraConnection.userOnlineChannel.leaving((user) => {
        const leavingUserIndex = agoraConnection.onlineUsers.findIndex(
          (data) => data.id === user.id
        );
        setAgoraConnection((prevAgoraConnection) => ({
          ...prevAgoraConnection,
          onlineUsers: prevAgoraConnection.onlineUsers.splice(
            leavingUserIndex,
            1
          ),
        }));
      });
      // listen to incoming call
      agoraConnection.userOnlineChannel.listen("MakeAgoraCall", ({ data }) => {
        console.log("Incoming call");
        if (parseInt(data.userToCall) === parseInt(props.user.id)) {
          const callerIndex = agoraConnection.onlineUsers.findIndex(
            (user) => user.id === data.from
          );
          // the channel that was sent over to the user being called is what
          // the receiver will use to join the call when accepting the call.
          setAgoraConnection((prevAgoraConnection) => ({
            ...prevAgoraConnection,
            incomingCaller: agoraConnection.onlineUsers[callerIndex]["name"],
            incomingCall: true,
            agoraChannel: data.channelName,
          }));
        }
      });
    };

    initUserOnlineChannel();
    if (agoraConnection.userOnlineChannel) {
      initUserOnlineListeners();
    }
  }, [
    agoraConnection.onlineUsers,
    agoraConnection.userOnlineChannel,
    props.user.id,
  ]);

  const placeCall = async (id, calleeId) => {
    try {
      // channelName = the caller's and the callee's id. you can use anything. tho.
      const channelName = `${props.user.id}_${calleeId}`;
      const tokenRes = await generateToken(channelName);
      // Broadcasts a call event to the callee and also gets back the token
      await axios.post("api/agora/call-user", {
        user_to_call: id,
        channel_name: channelName,
      });
      initializeAgora();
      joinRoom(tokenRes.data, channelName);
    } catch (error) {
      console.log(error);
    }
  };

  const acceptCall = async () => {
    initializeAgora();
    const tokenRes = await generateToken(agoraConnection.agoraChannel);
    joinRoom(tokenRes.data, agoraConnection.agoraChannel);
    setAgoraConnection({
      ...agoraConnection,
      incomingCall: false,
      callPlaced: true,
    });
  };

  const declineCall = () => {
    // You can send a request to the caller to
    // alert them of rejected call
    setAgoraConnection({
      incomingCall: false,
    });
  };

  const generateToken = (channelName) => {
    return axios.post("api/agora/token", {
      channelName,
    });
  };

  const initializeAgora = () => {
    client.current = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
    client.current.init(
      AGORA_ID,
      () => {
        console.log("AgoraRTC client initialized");
      },
      (err) => {
        console.log("AgoraRTC client init failed", err);
      }
    );
  };

  const joinRoom = async (token, channel) => {
    client.current.join(
      token,
      channel,
      props.user.id,
      (uid) => {
        console.log("User " + uid + " join channel successfully");
        setAgoraConnection({ ...agoraConnection, callPlaced: true });
        createLocalStream();
        initializedAgoraListeners();
      },
      (err) => {
        console.log("Join channel failed", err);
      }
    );
  };

  const initializedAgoraListeners = () => {
    //   Register event listeners
    client.current.on("stream-published", function (evt) {
      console.log("Publish local stream successfully");
      console.log(evt);
    });
    //subscribe remote stream
    client.current.on("stream-added", ({ stream }) => {
      console.log("New stream added: " + stream.getId());
      client.current.subscribe(stream, function (err) {
        console.log("Subscribe stream failed", err);
      });
    });
    client.current.on("stream-subscribed", (evt) => {
      // Attach remote stream to the remote-video div
      evt.stream.play("remote-video");
      client.current.publish(evt.stream);
    });
    client.current.on("stream-removed", ({ stream }) => {
      console.log(String(stream.getId()));
      stream.close();
    });
    client.current.on("peer-online", (evt) => {
      console.log("peer-online", evt.uid);
    });
    client.current.on("peer-leave", (evt) => {
      var uid = evt.uid;
      var reason = evt.reason;
      console.log("remote user left ", uid, "reason: ", reason);
    });
    client.current.on("stream-unpublished", (evt) => {
      console.log(evt);
    });
  };

  const createLocalStream = () => {
    localStream.current = AgoraRTC.createStream({
      audio: true,
      video: true,
    });
    // Initialize the local stream
    localStream.current.init(
      () => {
        // Play the local stream
        localStream.current.play("me");
        console.log("Local stream played");
        // Publish the local stream
        client.current.publish(localStream.current, (err) => {
          console.log("publish local stream", err);
        });
      },
      (err) => {
        console.log(err);
      }
    );
  };

  const endCall = () => {
    localStream.current.close();
    client.current.leave(
      () => {
        console.log("Leave channel successfully");
        setAgoraConnection({
          ...agoraConnection,
          callPlaced: false,
        });
      },
      (err) => {
        console.log("Leave channel failed");
      }
    );
  };

  const handleAudioToggle = () => {
    if (agoraConnection.mutedAudio) {
      localStream.current.unmuteAudio();
      setAgoraConnection({
        ...agoraConnection,
        mutedAudio: false,
      });
    } else {
      localStream.current.muteAudio();
      setAgoraConnection({
        ...agoraConnection,
        mutedAudio: true,
      });
    }
  };

  const handleVideoToggle = () => {
    if (agoraConnection.mutedVideo) {
      localStream.current.unmuteVideo();
      setAgoraConnection({
        ...agoraConnection,
        mutedVideo: false,
      });
    } else {
      localStream.current.muteVideo();
      setAgoraConnection({
        ...agoraConnection,
        mutedVideo: true,
      });
    }
  };

  return (
    <div className="mt-5">
      <div>
        <button
          type="button"
          className="btn btn-primary"
          onClick={() => placeCall(4, 4)}
        >
          Call
        </button>
      </div>
      {agoraConnection.incomingCall && (
        <div className="row my-5">
          <div className="col-12">
            <p>
              Incoming Call From{" "}
              <strong>{agoraConnection.incomingCaller}</strong>
            </p>
            <div className="btn-group" role="group">
              <button
                type="button"
                className="btn btn-danger"
                data-dismiss="modal"
                onClick={() => declineCall()}
              >
                Decline
              </button>
              <button
                type="button"
                className="btn btn-success ml-5"
                onClick={() => acceptCall()}
              >
                Accept
              </button>
            </div>
          </div>
        </div>
      )}

      {agoraConnection.callPlaced && (
        <section id="video-container">
          <div id="me"></div>
          <div id="remote-video"></div>

          <div className="action-btns">
            <button
              type="button"
              className="btn btn-info"
              onClick={() => handleAudioToggle()}
            >
              {agoraConnection.mutedAudio ? "Unmute" : "Mute"}
            </button>
            <button
              type="button"
              className="btn btn-primary mx-4"
              onClick={() => handleVideoToggle()}
            >
              {agoraConnection.mutedVideo ? "ShowVideo" : "HideVideo"}
            </button>
            <button
              type="button"
              className="btn btn-danger"
              onClick={() => endCall()}
            >
              EndCall
            </button>
          </div>
        </section>
      )}
    </div>
  );
};

const mapStateToProps = (state) => {
  return {
    user: state.auth,
  };
};

export default connect(mapStateToProps)(VideoCallPage);

在我打个电话后,我说我的网络相机启动了应显示我本地流的位置,但没有实际流:

我真的没有其他想法如何解决此问题。

I am working on react and laravel project and I want to implement the ability of to users to call each other and joint in a video call. I have implemented all of the code as instructed in their documentation and I have used Laravel back-end to generate the token. Apparently everything works and I get no errors. However, my camera opens but no local stream (video) is displayed on the screen. I suspect is something wrong with my react code:

import React, { useEffect, useState, useRef } from "react";
import { connect } from "react-redux";
import Echo from "laravel-echo";
import axios from "axios";
import AgoraRTC from "agora-rtc-sdk";
import styles from "./css/settingspace.module.css";

const AGORA_ID = "my app id copyed from agora website";

const VideoCallPage = (props) => {
  const [agoraConnection, setAgoraConnection] = useState({
    callPlaced: false,
    mutedAudio: false,
    mutedVideo: false,
    userOnlineChannel: null,
    onlineUsers: [],
    incomingCall: false,
    incomingCaller: "",
    agoraChannel: null,
  });

  const client = useRef(null);
  const localStream = useRef(null);

  useEffect(() => {
    const initUserOnlineChannel = () => {
      console.log("Initiate User Online Channel");
      setAgoraConnection((prevAgoraConnection) => ({
        ...prevAgoraConnection,
        userOnlineChannel: window.Echo.join("agora-online-channel"),
      }));
      console.log("Initiate User Online Channel - Finished");
    };

    const initUserOnlineListeners = () => {
      console.log("Initiate User Online Listeners");
      agoraConnection.userOnlineChannel.here((users) => {
        setAgoraConnection((prevAgoraConnection) => ({
          ...prevAgoraConnection,
          onlineUsers: users,
        }));
      });
      agoraConnection.userOnlineChannel.joining((user) => {
        // check user availability
        const joiningUserIndex = agoraConnection.onlineUsers.findIndex(
          (data) => data.id === user.id
        );
        if (joiningUserIndex < 0) {
          setAgoraConnection((prevAgoraConnection) => ({
            ...prevAgoraConnection,
            onlineUsers: [...agoraConnection.onlineUsers, user],
          }));
        }
      });
      agoraConnection.userOnlineChannel.leaving((user) => {
        const leavingUserIndex = agoraConnection.onlineUsers.findIndex(
          (data) => data.id === user.id
        );
        setAgoraConnection((prevAgoraConnection) => ({
          ...prevAgoraConnection,
          onlineUsers: prevAgoraConnection.onlineUsers.splice(
            leavingUserIndex,
            1
          ),
        }));
      });
      // listen to incoming call
      agoraConnection.userOnlineChannel.listen("MakeAgoraCall", ({ data }) => {
        console.log("Incoming call");
        if (parseInt(data.userToCall) === parseInt(props.user.id)) {
          const callerIndex = agoraConnection.onlineUsers.findIndex(
            (user) => user.id === data.from
          );
          // the channel that was sent over to the user being called is what
          // the receiver will use to join the call when accepting the call.
          setAgoraConnection((prevAgoraConnection) => ({
            ...prevAgoraConnection,
            incomingCaller: agoraConnection.onlineUsers[callerIndex]["name"],
            incomingCall: true,
            agoraChannel: data.channelName,
          }));
        }
      });
    };

    initUserOnlineChannel();
    if (agoraConnection.userOnlineChannel) {
      initUserOnlineListeners();
    }
  }, [
    agoraConnection.onlineUsers,
    agoraConnection.userOnlineChannel,
    props.user.id,
  ]);

  const placeCall = async (id, calleeId) => {
    try {
      // channelName = the caller's and the callee's id. you can use anything. tho.
      const channelName = `${props.user.id}_${calleeId}`;
      const tokenRes = await generateToken(channelName);
      // Broadcasts a call event to the callee and also gets back the token
      await axios.post("api/agora/call-user", {
        user_to_call: id,
        channel_name: channelName,
      });
      initializeAgora();
      joinRoom(tokenRes.data, channelName);
    } catch (error) {
      console.log(error);
    }
  };

  const acceptCall = async () => {
    initializeAgora();
    const tokenRes = await generateToken(agoraConnection.agoraChannel);
    joinRoom(tokenRes.data, agoraConnection.agoraChannel);
    setAgoraConnection({
      ...agoraConnection,
      incomingCall: false,
      callPlaced: true,
    });
  };

  const declineCall = () => {
    // You can send a request to the caller to
    // alert them of rejected call
    setAgoraConnection({
      incomingCall: false,
    });
  };

  const generateToken = (channelName) => {
    return axios.post("api/agora/token", {
      channelName,
    });
  };

  const initializeAgora = () => {
    client.current = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
    client.current.init(
      AGORA_ID,
      () => {
        console.log("AgoraRTC client initialized");
      },
      (err) => {
        console.log("AgoraRTC client init failed", err);
      }
    );
  };

  const joinRoom = async (token, channel) => {
    client.current.join(
      token,
      channel,
      props.user.id,
      (uid) => {
        console.log("User " + uid + " join channel successfully");
        setAgoraConnection({ ...agoraConnection, callPlaced: true });
        createLocalStream();
        initializedAgoraListeners();
      },
      (err) => {
        console.log("Join channel failed", err);
      }
    );
  };

  const initializedAgoraListeners = () => {
    //   Register event listeners
    client.current.on("stream-published", function (evt) {
      console.log("Publish local stream successfully");
      console.log(evt);
    });
    //subscribe remote stream
    client.current.on("stream-added", ({ stream }) => {
      console.log("New stream added: " + stream.getId());
      client.current.subscribe(stream, function (err) {
        console.log("Subscribe stream failed", err);
      });
    });
    client.current.on("stream-subscribed", (evt) => {
      // Attach remote stream to the remote-video div
      evt.stream.play("remote-video");
      client.current.publish(evt.stream);
    });
    client.current.on("stream-removed", ({ stream }) => {
      console.log(String(stream.getId()));
      stream.close();
    });
    client.current.on("peer-online", (evt) => {
      console.log("peer-online", evt.uid);
    });
    client.current.on("peer-leave", (evt) => {
      var uid = evt.uid;
      var reason = evt.reason;
      console.log("remote user left ", uid, "reason: ", reason);
    });
    client.current.on("stream-unpublished", (evt) => {
      console.log(evt);
    });
  };

  const createLocalStream = () => {
    localStream.current = AgoraRTC.createStream({
      audio: true,
      video: true,
    });
    // Initialize the local stream
    localStream.current.init(
      () => {
        // Play the local stream
        localStream.current.play("me");
        console.log("Local stream played");
        // Publish the local stream
        client.current.publish(localStream.current, (err) => {
          console.log("publish local stream", err);
        });
      },
      (err) => {
        console.log(err);
      }
    );
  };

  const endCall = () => {
    localStream.current.close();
    client.current.leave(
      () => {
        console.log("Leave channel successfully");
        setAgoraConnection({
          ...agoraConnection,
          callPlaced: false,
        });
      },
      (err) => {
        console.log("Leave channel failed");
      }
    );
  };

  const handleAudioToggle = () => {
    if (agoraConnection.mutedAudio) {
      localStream.current.unmuteAudio();
      setAgoraConnection({
        ...agoraConnection,
        mutedAudio: false,
      });
    } else {
      localStream.current.muteAudio();
      setAgoraConnection({
        ...agoraConnection,
        mutedAudio: true,
      });
    }
  };

  const handleVideoToggle = () => {
    if (agoraConnection.mutedVideo) {
      localStream.current.unmuteVideo();
      setAgoraConnection({
        ...agoraConnection,
        mutedVideo: false,
      });
    } else {
      localStream.current.muteVideo();
      setAgoraConnection({
        ...agoraConnection,
        mutedVideo: true,
      });
    }
  };

  return (
    <div className="mt-5">
      <div>
        <button
          type="button"
          className="btn btn-primary"
          onClick={() => placeCall(4, 4)}
        >
          Call
        </button>
      </div>
      {agoraConnection.incomingCall && (
        <div className="row my-5">
          <div className="col-12">
            <p>
              Incoming Call From{" "}
              <strong>{agoraConnection.incomingCaller}</strong>
            </p>
            <div className="btn-group" role="group">
              <button
                type="button"
                className="btn btn-danger"
                data-dismiss="modal"
                onClick={() => declineCall()}
              >
                Decline
              </button>
              <button
                type="button"
                className="btn btn-success ml-5"
                onClick={() => acceptCall()}
              >
                Accept
              </button>
            </div>
          </div>
        </div>
      )}

      {agoraConnection.callPlaced && (
        <section id="video-container">
          <div id="me"></div>
          <div id="remote-video"></div>

          <div className="action-btns">
            <button
              type="button"
              className="btn btn-info"
              onClick={() => handleAudioToggle()}
            >
              {agoraConnection.mutedAudio ? "Unmute" : "Mute"}
            </button>
            <button
              type="button"
              className="btn btn-primary mx-4"
              onClick={() => handleVideoToggle()}
            >
              {agoraConnection.mutedVideo ? "ShowVideo" : "HideVideo"}
            </button>
            <button
              type="button"
              className="btn btn-danger"
              onClick={() => endCall()}
            >
              EndCall
            </button>
          </div>
        </section>
      )}
    </div>
  );
};

const mapStateToProps = (state) => {
  return {
    user: state.auth,
  };
};

export default connect(mapStateToProps)(VideoCallPage);

After I place a call like I said my web camera starts the place where my local stream should be displayed is shown but without the actual stream:
enter image description here

I really have no other ideas how to fix this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫烠⑼条掵仅有一顆心 2025-01-29 15:28:01

在大多数情况下,AgorARTC在两个Divs中插入HTML视频元素(第一div是TrackID,第二个DIV是视频元素包装器),您需要为此元素进行样式,因为它们具有宽度0px&amp; Heigth 0px,检查检查员,您还可以使用从Agora-RTC导入的Agoravideoplayer组件,也需要样式

in the most cases AgoraRTC insert the html video element inside two divs (first div is the trackid, second div is the video element wrapper), you need to style this elements cu'z they have width 0px & heigth 0px, check in the inspector, you can also use the AgoraVideoPlayer component imported from agora-rtc and need style this too

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文