前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >视频通话进阶:React Hooks和屏幕共享,让你在虚拟世界中畅享面对面的交流

视频通话进阶:React Hooks和屏幕共享,让你在虚拟世界中畅享面对面的交流

原创
作者头像
zayyo
发布2023-10-14 20:00:15
2380
发布2023-10-14 20:00:15
举报
文章被收录于专栏:zayyo前端zayyo前端

这篇文章是关于什么的?

您撰写本文是为了深入研究使用 React 构建具有屏幕共享功能的视频会议应用程序的复杂性。您的目标是强调这项技术的复杂性和变革潜力。

我为什么创建这篇文章?

我写这篇文章是为了讨论使用 React 创建一个具有屏幕共享功能的复杂视频会议应用程序。我探索了技术、代码和用户界面如何结合起来超越常规的沟通。此外,我还讨论了此类应??用程序如何改变现代科技时代的人类互动。

视频 SDK - 适合每个开发人员的实时视频基础设施

Video SDK是一个强大的实时视频平台,具有实时视频会议、聊天、屏幕共享等功能。它提供适用于各种平台的 SDK,使开发人员能够创建可定制的视频体验,并支持JavaScript、React、React Native、Flutter、Android Native、iOS Native等流行编程语言。此外,它采用即用即付的定价模式,适合各种规模的企业。https://www.videosdk.live/

适合每个开发者的实时视频基础设施<br><br>
适合每个开发者的实时视频基础设施<br><br>

我们为您提供什么?

Video SDK RTC React JS SDK 提供了一系列令人印象深刻的功能,每个功能都旨在增强您的虚拟通信和协作体验:

  • 免费使用:您每月可免费使用 10,000 分钟。
  • 轻松设置:它是低代码和无服务器的,因此易于使用。
  • 全多媒体:享受实时音频、视频和数据流。
  • 高质量屏幕共享:以高清和全高清共享您的屏幕。
  • 可定制的 UI:根据需要个性化界面。
  • 丰富聊天:在聊天中与富媒体进行交流。
  • 社交媒体集成:与 Facebook 和 Youtube 等平台连接(RTMP 输出支持)。
  • 智能扬声器开关:自动扬声器管理。
  • 云录制:在云端录制会议。

如果您在任何时候遇到困难或需要帮助来理解概念,您可以将您的查询放入我们的Discord 频道

构建一个具有屏幕共享和 React 的视频聊天应用程序

先决条件

  • 首先,您需要一个视频 SDK 帐户还没有吗?没有汗!只需标记我们的视频 SDK 仪表板指南即可。
  • 接下来,确保您掌握了React 的基础知识。伙计们,我们在这里谈论的是 React 101
  • 当然,这场秀的明星是我们的 React Video SDK包管理器。你会希望它出现在你的武器库中。
  • 不要忘记在您的设备上安装 Node 和 NPM。他们是您这段旅程中值得信赖的伙伴。
  • 现在,我们来谈谈 Hooks - 熟悉useStateuseRefuseEffect。它们是你的秘密武器。
  • 如果您雄心勃勃,可以深入研究 React Context API。它是可选的,但它可以为您的应用程序增添一些额外的魅力。

让我们开始吧

您可以使用反应脚本生成项目模板或任何其他反应样板。

代码语言:javascript
复制
Create new project using create-react-app

安装依赖项

代码语言:javascript
复制
##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"

项目结构

代码语言:javascript
复制
.
├── node_modules
├── public
├── .env
├── src
│ └── api.js
│ └── App.js
│ └── index.css
│ └── index.jsx
├── package.json
...
.

当然,我们将利用功能组件的力量来利用 React 出色的可重用组件设置。这是我们菜单上的内容:

  • 用户组件:这些将处理与用户相关的功能。
  • 视频组件:这些组件将处理与视频相关的所有内容。
  • 控制组件:这些是真正的 MVP,涵盖麦克风、摄像头和最重要的退出功能,确保您的视频体验顺利进行。

让我们开始吧,让奇迹发生吧!

应用架构:

我们的应用程序的结构如下:

  • MeetingView 组件:这是我们应用程序的主要中心。在其中,您将找到ParticipantView。我们将在此视图中显示重要的参与者信息,例如他们的姓名、视频流、音频状态等。
  • 控制组件:将其视为命令中心。这是用户控制应用程序的地方。在这里,他们可以执行离开会议和切换媒体设置等操作。
1
1

我们将其分为两个关键文件:

API.js:此文件处理 API 任务,例如创建唯一的会议 ID 和令牌。

App.js:这就是奇迹发生的地方。它呈现 MeetingView 并让您进入会议。这是您视频冒险的前门。

有了这两个文件,我们就可以开始了!

让我们深入了解 API.js

在我们进行下一步之前,我们的首要任务是在API.js中编写 API 请求。此请求是您生成独一无二的会议 ID 的金票。但是等一下,有一个问题 - 您需要一个身份验证令牌。

您可以通过两种方式获取此令牌:使用videosdk-rtc-api-server-examples快速启动它,或者直接转到开发人员的“<Generate-from-dashbaord>

2
2

src/API.js

代码语言:javascript
复制
//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 线框

在 App.js 线框中,我们将利用视频 SDK 挂钩和上下文提供程序。这是快速细分:

  1. MeetingProvider:与不同嵌套级别的多个组件共享数据的上下文提供程序。
  2. MeetingConsumer:监听 Provider 数据变化的 Context Consumer。
  3. u* seMeeting *:处理与会议相关的所有事务的挂钩,例如加入、离开以及调整麦克风和网络摄像头设置。
  4. useParticipant:此钩子专注于单个参与者,管理他们的姓名、网络摄像头流、麦克风流等。会议上下文密切关注会议中的所有更改。让我们深入研究并调整 App.js 以实现这一目标!?

src/App.js

代码语言:javascript
复制
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

代码语言:javascript
复制
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>
  );
}

实施参与者视图和控制

让我们卷起袖子开始实现ParticipantViewControls。这些组件对于有效管理参与者交互至关重要。

ParticipantView:该组件将显示各个参与者的视图,显示他们的视频、音频和其他相关信息。

控件:控制面板允许您执行将参与者的麦克风静音/取消静音以及切换摄像头等操作。

有了这些组件,您就可以完全控制参与者的体验。是时候潜水了!?

  • 转发麦克风和摄像头的引用:我们将使用 ReactuseRef来引用音频和视频组件以进行参与者控制。
  • useParticipant Hook:此挂钩使用特定参与者的 ID 管理其属性和事件。
  • MediaStream API:我们使用 MediaStream 来处理音频和视频播放。

src/App.js

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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} />
  );
}

运行应用程序

现在您已经实现了所有组件,您可以使用以下命令运行应用程序:

代码语言:javascript
复制
npm start

这将启动开发服务器,您可以在网络浏览器中访问视频会议应用程序。

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这篇文章是关于什么的?
  • 我为什么创建这篇文章?
  • 视频 SDK - 适合每个开发人员的实时视频基础设施
  • 我们为您提供什么?
  • 构建一个具有屏幕共享和 React 的视频聊天应用程序
  • 先决条件
  • 让我们开始吧
  • 安装依赖项
  • 项目结构
  • 应用架构:
  • 让我们深入了解 API.js
  • 构建 App.js 线框
  • 让我们开始实施加入屏幕吧!
  • 实施参与者视图和控制
    • 功能控制
    • 创建会议视图
    • 运行应用程序
    相关产品与服务
    多因子身份认证
    多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
    http://www.vxiaotou.com