您撰写本文是为了深入研究使用 React 构建具有屏幕共享功能的视频会议应用程序的复杂性。您的目标是强调这项技术的复杂性和变革潜力。
我写这篇文章是为了讨论使用 React 创建一个具有屏幕共享功能的复杂视频会议应用程序。我探索了技术、代码和用户界面如何结合起来超越常规的沟通。此外,我还讨论了此类应用程序如何改变现代科技时代的人类互动。
Video SDK是一个强大的实时视频平台,具有实时视频会议、聊天、屏幕共享等功能。它提供适用于各种平台的 SDK,使开发人员能够创建可定制的视频体验,并支持JavaScript、React、React Native、Flutter、Android Native、iOS Native等流行编程语言。此外,它采用即用即付的定价模式,适合各种规模的企业。https://www.videosdk.live/
Video SDK RTC React JS SDK 提供了一系列令人印象深刻的功能,每个功能都旨在增强您的虚拟通信和协作体验:
如果您在任何时候遇到困难或需要帮助来理解概念,您可以将您的查询放入我们的Discord 频道。
useState
、useRef
和useEffect
。它们是你的秘密武器。您可以使用反应脚本生成项目模板或任何其他反应样板。
Create new project using create-react-app
##npm
$ npm install "@videosdk.live/react-sdk"
//For the Participants Video
$ npm install "react-player"
or
##yarn
$ yarn add "@videosdk.live/react-sdk"
//For the Participants Video
$ yarn add "react-player"
.
├── node_modules
├── public
├── .env
├── src
│ └── api.js
│ └── App.js
│ └── index.css
│ └── index.jsx
├── package.json
...
.
当然,我们将利用功能组件的力量来利用 React 出色的可重用组件设置。这是我们菜单上的内容:
让我们开始吧,让奇迹发生吧!
我们的应用程序的结构如下:
我们将其分为两个关键文件:
API.js:此文件处理 API 任务,例如创建唯一的会议 ID 和令牌。
App.js:这就是奇迹发生的地方。它呈现 MeetingView 并让您进入会议。这是您视频冒险的前门。
有了这两个文件,我们就可以开始了!
在我们进行下一步之前,我们的首要任务是在API.js中编写 API 请求。此请求是您生成独一无二的会议 ID 的金票。但是等一下,有一个问题 - 您需要一个身份验证令牌。
您可以通过两种方式获取此令牌:使用videosdk-rtc-api-server-examples快速启动它,或者直接转到开发人员的“<Generate-from-dashbaord> ”。
src/API.js
//Auth token we will use to generate a meeting and connect to it
export const authToken = "<Generated-from-dashbaord>";
// API call to create meeting
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({}),
});
//Destructuring the roomId from the response
const { roomId } = await res.json();
return roomId;
};
不是📝 需要有一个 VideoSDK 帐户才能生成令牌。访问VideoSDK仪表板以生成令牌。
在 App.js 线框中,我们将利用视频 SDK 挂钩和上下文提供程序。这是快速细分:
src/App.js
import "./App.css";
import React, { useEffect, useMemo, useRef, useState } from "react";
import {
MeetingProvider,
MeetingConsumer,
useMeeting,
useParticipant,
} from "@videosdk.live/react-sdk";
import { authToken, createMeeting } from "./API";
import ReactPlayer from "react-player";
function JoinScreen({ getMeetingAndToken }) {
return null;
}
function ParticipantView(props) {
return null;
}
function Controls(props) {
return null;
}
function MeetingView(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);
};
const onMeetingLeave = () => {
setMeetingId(null);
};
return authToken && meetingId ? (
<MeetingProvider
config={{
meetingId,
micEnabled: true,
webcamEnabled: true,
name: "C.V. Raman",
}}
token={authToken}
>
<MeetingConsumer>
{() => (
<MeetingView meetingId={meetingId} onMeetingLeave={onMeetingLeave} />
)}
</MeetingConsumer>
</MeetingProvider>
) : (
<JoinScreen getMeetingAndToken={getMeetingAndToken} />
);
}
export default App;
在加入屏幕中,我们通过两个基本功能使事情变得简单:
创建新会议:此选项允许用户从头开始开始新的会议。
加入会议:在这里,用户可以使用会议 ID 跳入现有会议。
我们这里的明星是 JoinScreen 组件。这是动作发生的地方。是时候让这个屏幕焕然一新了!🚀
src/App.js
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>
);
}
让我们卷起袖子开始实现ParticipantView和Controls。这些组件对于有效管理参与者交互至关重要。
ParticipantView:该组件将显示各个参与者的视图,显示他们的视频、音频和其他相关信息。
控件:控制面板允许您执行将参与者的麦克风静音/取消静音以及切换摄像头等操作。
有了这些组件,您就可以完全控制参与者的体验。是时候潜水了!🚀
useRef
来引用音频和视频组件以进行参与者控制。src/App.js
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]);
// webcamStream.pause()
// micStream.pause()
// webcamStream.resume()
// micStream.resume()
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 key={props.participantId}>
<p>
Participant: {displayName} | Webcam: {webcamOn ? "ON" : "OFF"} | Mic:{" "}
{micOn ? "ON" : "OFF"}
</p>
<audio ref={micRef} autoPlay muted={isLocal} />
<button onClick={() => webcamStream.pause()}>Pause</button>
<button onClick={() => webcamStream.resume()}>Resume</button>
{webcamOn && (
<ReactPlayer
//
playsinline // very very imp prop
pip={false}
light={false}
controls={false}
muted={true}
playing={true}
//
url={videoStream}
//
height={"200px"}
width={"300px"}
onError={(err) => {
console.log(err, "participant video error");
}}
/>
)}
</div>
);
}
src/App.js
function Controls() {
const { leave, toggleMic, toggleWebcam, toggleScreenShare } = useMeeting();
return (
<div>
<button onClick={() => leave()}>Leave</button>
<button onClick={() => toggleMic()}>toggleMic</button>
<button onClick={() => toggleWebcam()}>toggleWebcam</button>
<button onClick={() => toggleScreenShare()}>screen share</button>
</div>
);
}
const PresenterView = ({ presenterId }) => {
const { screenShareStream, screenShareOn } = useParticipant(presenterId);
//Creating a media stream from the screen share stream
const mediaStream = useMemo(() => {
if (screenShareOn && screenShareStream) {
const mediaStream = new MediaStream();
mediaStream.addTrack(screenShareStream.track);
return mediaStream;
}
}, [screenShareStream, screenShareOn]);
return (
<>
<ReactPlayer
//
playsinline // very very imp prop
playIcon={<></>}
//
pip={false}
light={false}
controls={false}
muted={true}
playing={true}
//
url={mediaStream} // passing mediastream here
//
height={"100%"}
width={"100%"}
onError={(err) => {
console.log(err, "presenter video error");
}}
/>
</>
);
};
让我们专注于实现该MeetingView
组件。该组件是应用程序的核心,负责显示会议界面,包括参与者视频、音频和其他重要信息。
使用 MeetingView 后,您将拥有一个用于所有会议相关活动的中心枢纽。让我们开始工作吧!🚀
src/App.js
function MeetingView(props) {
const [joined, setJoined] = useState(null);
const { join, presenterId } = useMeeting();
const { 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}
/>
))}
{presenterId && <PresenterView presenterId={presenterId} />}
</div>
) : joined && joined == "JOINING" ? (
<p>Joining the meeting...</p>
) : (
<button onClick={joinMeeting}>Join</button>
)}
</div>
);
}
function App() {
const [meetingId, setMeetingId] = useState(null);
const getMeetingAndToken = async (id) => {
const meetingId =
id == null ? await createMeeting({ token: authToken }) : id;
setMeetingId(meetingId);
};
const onMeetingLeave = () => {
setMeetingId(null);
};
return authToken && meetingId ? (
<MeetingProvider
config={{
meetingId,
micEnabled: true,
webcamEnabled: true,
name: "C.V. Raman",
}}
token={authToken}
>
<MeetingConsumer>
{() => (
<MeetingView meetingId={meetingId} onMeetingLeave={onMeetingLeave} />
)}
</MeetingConsumer>
</MeetingProvider>
) : (
<JoinScreen getMeetingAndToken={getMeetingAndToken} />
);
}
现在您已经实现了所有组件,您可以使用以下命令运行应用程序:
npm start
这将启动开发服务器,您可以在网络浏览器中访问视频会议应用程序。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。