logo

如何使用Video SDK构建React视频通话应用

109
2023年10月12日
本教程展示了如何使用React和Video SDK构建一个视频通话应用 —— 设置环境、集成视频通话以及实现会议控制功能。

你是否觉得现有的视频通话应用有所限制?如果是的话,为什么不自己制作一个视频通话应用,可以用于任何用途呢?借助Video SDK的帮助,很容易集成并构建自己的视频通话应用,具备聊天、投票、白板等功能。

Video SDK是一个平台,允许开发人员创建丰富的应用内体验,如嵌入实时视频、语音、实时录制、直播流和实时消息传递。Video SDK可在JavaScript、React.js、React-Native、iOS、Android和Flutter中无缝集成。Video SDK还提供预构建的SDK,可让您在短短10分钟内将实时通信集成到您的应用程序中。

在本教程中,您将探索Video SDK的群组通话功能。您将逐步了解如何使用React Video SDK集成视频通话。

本指南将帮助您在几分钟内运行Video SDK视频和音频通话。

让我们使用React.js和Video SDK创建一个视频通话应用。

先决条件

在继续之前,请确保您的开发环境满足以下要求:

  • Video SDK开发者帐户
  • 基本的React理解
  • React Video SDK
  • 在您的设备上安装了Node和NPM
  • 基本的Hooks理解(useState、useRef、useEffect)
  • React Context API(可选)

需要有Video SDK帐户来生成令牌。访问Video SDK仪表板生成令牌。

开始编码!

按照以下步骤创建必要的环境以向您的应用程序添加视频通话。

创建新的React应用

使用以下命令创建一个新的React应用

$ npx create-react-app videosdk-rtc-react-app

安装Video SDK

使用下面提到的npm命令安装Video SDK。在运行此命令之前,请确保您在React应用程序目录中。

$ npm install "@videosdk.live/react-sdk"

//对于参与者视频
$ npm install "react-player"

项目结构

在使用create-react-app创建应用程序后,您的项目结构应如下所示

root   
   ├── node_modules
   ├── public
   ├── src
   │    ├── api.js
   │    ├── App.js
   │    ├── App.css
   │    ├── index.js
   │    ├── index.js
   .    .

我们将使用功能组件来利用React的可重用组件架构。将为用户、视频和控件(麦克风、摄像头、离开)创建组件。

应用程序架构

该应用程序将包含一个MeetingView组件,其中包括ParticipantView,用于呈现参与者的名称、视频、音频等。我们还将有一个Controls组件,允许用户执行离开和切换媒体等操作。

我们将在两个文件上工作:

  • API.js:负责处理API调用,如生成唯一的meetingId和令牌
  • App.js:负责渲染MeetingView并加入会议。

构建React视频通话应用的五个步骤

步骤1:开始使用API.js

在继续之前,我们必须创建一个API请求来生成唯一的meetingId。您将需要一个身份验证令牌,您可以通过videosdk-rtc-api-server-examples或直接从Video SDK Dashboard for developers创建它。

//我们将使用此身份验证令牌来生成会议并连接到它
export const authToken = "<Generated-from-dashbaord>";
// 创建会议的API调用
export const createMeeting = async ({ token }) => {  const res = await fetch(`https://api.videosdk.live/v2/rooms`, {    method: "POST",    headers: {      authorization: `${authToken}`,      "Content-Type": "application/json",    },    body: JSON.stringify({}),  });  //从响应中解构roomId  const { roomId } = await res.json();  return roomId;
}

步骤2:使用所有组件的App.js框架

为了构建App.js的框架,我们将使用Video SDK Hooks和Context Providers。Video SDK提供MeetingProviderMeetingConsumeruseMeetinguseParticipant hooks。让我们了解每一个。

首先,我们将探索Context Provider和Consumer。当一些数据需要在不同嵌套级别的许多组件中访问时,主要使用Context。

  • MeetingProvider:它是一个Context Provider。它接受值配置和令牌作为props。Provider组件接受一个值prop,传递给此Provider的后代消费组件。一个Provider可以连接到多个消费者。Providers可以嵌套以在树的更深处覆盖值。
  • MeetingConsumer:它是Context Consumer。所有作为Provider后代的消费者将在Provider的值prop更改时重新渲染。
  • useMeeting:这是一个会议React hook API。它包括与会议相关的所有信息,如参与者、流等。
  • useParticipant:这是参与者hook API。useParticipant hook负责处理与一个特定参与者相关的所有事件和属性,如加入、离开、静音等。

Meeting Context有助于监听参与者加入会议或更改麦克风或摄像头等的所有更改。

让我们开始在App.js中更改几行代码。

import "./App.css";
import React, { useEffect, useRef, useState } from "react";
import {  MeetingProvider,  MeetingConsumer,  useMeeting,  useParticipant,
} from "@videosdk.live/react-sdk";
import { authToken, createMeeting } from "./API";

function JoinScreen() {  return null;
}

function VideoComponent(props) {  return null;
}

function Controls(props) {  return null;
}

function Container(props) {  return null;
}

function App() {  const [meetingId, setMeetingId] = useState(null);
  const getMeetingAndToken = async (id) => {    const meetingId =      id == null ? await createMeeting({ token: authToken }) : id;    setMeetingId(meetingId);  };
  return authToken && meetingId ? (    <MeetingProvider      config={{        meetingId,        micEnabled: true,        webcamEnabled: false,        name: "C.V. Raman",      }}      token={authToken}    >      <MeetingConsumer>        {() => <Container meetingId={meetingId} />}
      </MeetingConsumer>
    </MeetingProvider>
  ) : (    <JoinScreen getMeetingAndToken={getMeetingAndToken} />
  );
}

export default App;

步骤3:实现加入屏幕

加入屏幕将作为一个介质,用于安排新会议或加入现有会议。

function JoinScreen({ getMeetingAndToken }) {  const [meetingId, setMeetingId] = useState(null);  const onClick = async () => {    await getMeetingAndToken(meetingId);  };  return (    <div>      <input        type="text"        placeholder="Enter Meeting Id"        onChange={(e) => {          setMeetingId(e.target.value);        }}      />
      <button onClick={onClick}>Join</button>
      {" or "}      <button onClick={onClick}>Create Meeting</button>
    </div>
  );
}

步骤4:实现Container和Controls

下一步是创建MeetingViewControls组件,以管理加入、离开、静音和取消静音等功能。

function MeetingView(props) {  const [joined, setJoined] = useState(null);  //获取用于加入会议的方法。  //我们还将获取参与者列表,以显示所有参与者  const { join, participants } = useMeeting({    //当会议成功加入时的回调    onMeetingJoined: () => {      setJoined("JOINED");    },    //当会议离开时的回调    onMeetingLeft: () => {      props.onMeetingLeave();    },  });  const joinMeeting = () => {    setJoined("JOINING");    join();  };
  return (    <div className="container">      <h3>Meeting Id: {props.meetingId}</h3>
      {joined && joined == "JOINED" ? (        <div>          <Controls />          //用于呈现会议中的所有参与者          {[...participants.keys()].map((participantId) => (            <ParticipantView              participantId={participantId}              key={participantId}            />
          ))}        </div>
      ) : joined && joined == "JOINING" ? (        <p>Joining the meeting...</p>
      ) : (        <button onClick={joinMeeting}>Join</button>
      )}    </div>
  );
}

除此之外,需要一个Control组件来处理用户操作。

function Controls() {  const { leave, toggleMic, toggleWebcam } = useMeeting();  return (    <div>      <button onClick={leave}>Leave</button>
      <button onClick={toggleMic}>toggleMic</button>
      <button onClick={toggleWebcam}>toggleWebcam</button>
    </div>
  );
}

步骤5:实现Participant View

在实现视频组件之前,我们需要了解一些概念。

1. 用于麦克风和摄像头的Ref转发

Ref转发是一种自动将ref通过组件传递给其子组件的技术。我们将使用Refs将音频和视频轨道与组件连接起来。

const webcamRef = useRef(null);
const micRef = useRef(null);

2. useParticipant Hook

useParticipant hook负责处理加入会议的一个特定参与者的所有属性和事件。它将参与者作为参数。

const { webcamStream, micStream, webcamOn, micOn } = useParticipant(  props.participantId
);

3. MediaStream API

MediaStream对于将MediaTrack添加到音频/视频标签以播放音频或视频非常有用。

const webcamRef = useRef(null);
const mediaStream = new MediaStream();
mediaStream.addTrack(webcamStream.track);

webcamRef.current.srcObject = mediaStream;
webcamRef.current  .play()  .catch((error) => console.error("videoElem.current.play() failed", error));

现在,让我们使用所有这些API来创建ParticipantView

function ParticipantView(props) {  const micRef = useRef(null);  const { webcamStream, micStream, webcamOn, micOn, isLocal, displayName } =    useParticipant(props.participantId);
  const videoStream = useMemo(() => {    if (webcamOn && webcamStream) {      const mediaStream = new MediaStream();      mediaStream.addTrack(webcamStream.track);      return mediaStream;    }  }, [webcamStream, webcamOn]);
  useEffect(() => {    if (micRef.current) {      if (micOn && micStream) {        const mediaStream = new MediaStream();        mediaStream.addTrack(micStream.track);
        micRef.current.srcObject = mediaStream;        micRef.current          .play()          .catch((error) =>            console.error("videoElem.current.play() failed", error)          );      } else {        micRef.current.srcObject = null;      }    }  }, [micStream, micOn]);
  return (    <div>      <p>        Participant: {displayName} | Webcam: {webcamOn ? "ON" : "OFF"} | Mic:{" "}        {micOn ? "ON" : "OFF"}      </p>
      <audio ref={micRef} autoPlay playsInline muted={isLocal} />
      {webcamOn && (        <ReactPlayer          //          playsinline // very very imp prop          pip={false}          light={false}          controls={false}          muted={true}          playing={true}          //          url={videoStream}          //          height={"300px"}          width={"300px"}          onError={(err) => {            console.log(err, "participant video error");          }}        />
      )}    </div>
  );
}

我们已经成功使用React.js和Video SDK实现了一个定制的视频通话应用。

结论

我们已成功使用React.js完成了视频通话应用。如果您希望添加诸如聊天消息、屏幕共享、投票等功能,您可以随时查看我们的文档。如果您在实施过程中遇到任何困难,可以查看我们在GitHub上的示例,或在我们的Discord社区上与我们联系。 抱歉,我无法完成你的要求。

本文链接:https://www.iokks.com/art/27db64988f2c
本博客所有文章除特别声明外,均采用CC BY 4.0 CN协议 许可协议。转载请注明出处!