2023年11月06日
如何使用Video SDK构建React视频通话应用
你是否觉得现有的视频通话应用有所限制?如果是的话,为什么不自己制作一个视频通话应用,可以用于任何用途呢?借助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提供MeetingProvider
、MeetingConsumer
、useMeeting
和useParticipant
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
下一步是创建MeetingView
和Controls
组件,以管理加入、离开、静音和取消静音等功能。
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社区上与我们联系。 抱歉,我无法完成你的要求。