学习如何通过逐步教程创建强大的直播流应用程序。探索React和视频SDK的无缝集成,构建交互式直播流体验。跟随我们的指导,从设置环境到实现实时聊天、直播视频流和交互式参与工具等关键功能的开发过程。释放React和视频SDK的潜力,创建一个吸引观众的迷人直播流应用程序。立即开始,将您的直播流应用程序开发技能提升到新的水平!
在当今数字时代,直播流已成为分享内容和实时吸引观众的日益流行媒介。随着YouTube、Twitch和Facebook Live等平台的兴起,企业和个人都在探索利用直播视频的力量与目标观众建立联系。如果您希望使用React和视频SDK构建交互式直播流应用程序,那么您来对地方了。在本文中,我们将指导您创建一款尖端的直播流应用程序,帮助您在竞争中脱颖而出。
React已成为最广泛使用的JavaScript框架之一,用于构建用户界面。其基于组件的架构、虚拟DOM和高效渲染使其成为开发人员的热门选择。当与视频SDK结合使用时,视频SDK是一个强大的工具包,为开发人员提供了集成实时视频流到其应用程序所需的工具和功能,React在直播流领域变得更加强大。
用于构建交互式直播流应用程序的工具
- VideoSDK.Live的React SDK
- VideoSDK.Live的HLS组合
- VideoSDK.Live的HLS流
使用视频SDK构建React交互式直播流应用程序的四个步骤
步骤1:了解您的直播流应用程序功能和项目结构
我将为两种类型的用户创建此应用程序,即“演讲者”和“观众”。
- 演讲者将拥有所有媒体控件,即他们可以切换他们的网络摄像头和麦克风,与观众分享信息。演讲者还可以启动HLS流,以便观众消费内容。
- 观众将没有任何媒体控件,他们只能观看由演讲者启动的VideoSDK HLS流。
开始编写代码之前的先决条件:
- VideoSDK账户。如果没有,请注册
- 用于React的编码环境
- 对React的良好理解
在设置好编码环境后,我们现在可以开始编写我们的代码,首先我将使用create-react-app创建一个新的React应用程序,同时安装一些有用的依赖项。
npx create-react-app videosdk-interactive-live-streaming-app
cd videosdk-interactive-live-streaming-app
npm install @videosdk.live/react-sdk react-player hls.js
项目结构
我将创建三个屏幕:
- 欢迎屏幕
- 演讲者屏幕
- 观众屏幕
以下是我们应用程序的文件夹结构。
root/
├──node_modules/
├──public/
├──src/
├────screens/
├───────WelcomeScreenContainer.js
├───────speakerScreen/
├──────────MediaControlsContainer.js
├──────────ParticipantsGridContainer.js
├──────────SingleParticipantContainer.js
├──────────SpeakerScreenContainer.js
├──────ViewerScreenContainer.js
├────api.js
├────App.js
├────index.js
应用程序容器
我将准备一个基本的App.js,这个文件将包含所有屏幕,并根据appData状态的变化有条件地渲染它们。
/src/App.js
import React, { useState } from "react";
import SpeakerScreenContainer from "./screens/speakerScreen/SpeakerScreenContainer";
import ViewerScreenContainer from "./screens/ViewerScreenContainer";
import WelcomeScreenContainer from "./screens/WelcomeScreenContainer";
const App = () => {
const [appData, setAppData] = useState({ meetingId: null, mode: null });
return appData.meetingId ? (
appData.mode === "CONFERENCE" ? (
<SpeakerScreenContainer meetingId={appData.meetingId} />
) : (
<ViewerScreenContainer meetingId={appData.meetingId} />
)
) : (
<WelcomeScreenContainer setAppData={setAppData} />
);
};
export default App;
步骤2:您的React直播流应用程序的欢迎屏幕
创建一个新的会议将需要一个API调用,因此我们将为此编写一些代码。
在生产中,可以从用户仪表板获取临时的授权令牌,但我们建议使用您的服务器生成的授权令牌。
遵循此指南从用户仪表板获取临时授权令牌。
/src/api.js
export const authToken = "temporary-generated-auth-token-goes-here";
export const createNewRoom = async () => {
const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
method: "POST",
headers: {
authorization: `${authToken}`,
"Content-Type": "application/json",
},
});
const { roomId } = await res.json();
return roomId;
};
WelcomeScreenContainer将用于由演讲者创建新会议。它还将允许输入已创建的meetingId以加入现有会话。
src/screens/WelcomeScreenContainer.js
import React, { useState } from "react";
import { createNewRoom } from "../api";
const WelcomeScreenContainer = ({ setAppData }) => {
const [meetingId, setMeetingId] = useState("");
const createClick = async () => {
const meetingId = await createNewRoom();
setAppData({ mode: "CONFERENCE", meetingId });
};
const hostClick = () => setAppData({ mode: "CONFERENCE", meetingId });
const viewerClick = () => setAppData({ mode: "VIEWER", meetingId });
return (
<div>
<button onClick={createClick}>Create new Meeting</button>
<p>{"\n\nor\n\n"}</p>
<input
placeholder="Enter meetingId"
onChange={(e) => setMeetingId(e.target.value)}
value={meetingId}
/>
<p>{"\n\n"}</p>
<button onClick={hostClick}>Join As Host</button>
<button onClick={viewerClick}>Join As Viewer</button>
</div>
);
};
export default WelcomeScreenContainer;
步骤3:演讲者屏幕
这个屏幕将包含所有的媒体控件和参与者网格。首先,我将为即将加入的参与者创建一个名称输入框。
src/screens/speakerScreen/SpeakerScreenContainer.js
import { MeetingProvider } from "@videosdk.live/react-sdk";
import React from "react";
import MediaControlsContainer from "./MediaControlsContainer";
import ParticipantsGridContainer from "./ParticipantsGridContainer";
import { authToken } from "../../api";
const SpeakerScreenContainer = ({ meetingId }) => {
return (
<MeetingProvider
token={authToken}
config={{
meetingId,
name: "C.V. Raman",
micEnabled: true,
webcamEnabled: true,
}}
joinWithoutUserInteraction
>
<MediaControlsContainer meetingId={meetingId} />
<ParticipantsGridContainer />
</MeetingProvider>
);
};
export default SpeakerScreenContainer;
MediaControls
这个容器将用于切换麦克风和网络摄像头。此外,我们将添加一些代码来启动HLS流。
import { useMeeting, Constants } from "@videosdk.live/react-sdk";
import React, { useMemo } from "react";
const MediaControlsContainer = () => {
const { toggleMic, toggleWebcam, startHls, stopHls, hlsState, meetingId } =
useMeeting();
const { isHlsStarted, isHlsStopped, isHlsPlayable } = useMemo(
() => ({
isHlsStarted: hlsState === Constants.hlsEvents.HLS_STARTED,
isHlsStopped: hlsState === Constants.hlsEvents.HLS_STOPPED,
isHlsPlayable: hlsState === Constants.hlsEvents.HLS_PLAYABLE,
}),
[hlsState]
);
const _handleToggleHls = () => {
if (isHlsStarted) {
stopHls();
} else if (isHlsStopped) {
startHls({ quality: "high" });
}
};
return (
<div>
<p>MeetingId: {meetingId}</p>
<p>HLS state: {hlsState}</p>
{isHlsPlayable && <p>Viewers will now be able to watch the stream.</p>}
<button onClick={toggleMic}>Toggle Mic</button>
<button onClick={toggleWebcam}>Toggle Webcam</button>
<button onClick={_handleToggleHls}>
{isHlsStarted ? "Stop Hls" : "Start Hls"}
</button>
</div>
);
};
export default MediaControlsContainer;
ParticipantGridContainer
这将从useMeeting钩子获取所有已加入的参与者,并将它们单独渲染。在这里,我们将使用SingleParticipantContainer来渲染单个参与者的网络摄像头流。
src/screens/speakerScreen/ParticipantsGridContainer.js
import { useMeeting } from "@videosdk.live/react-sdk";
import React, { useMemo } from "react";
import SingleParticipantContainer from "./SingleParticipantContainer";
const ParticipantsGridContainer = () => {
const { participants } = useMeeting();
const participantIds = useMemo(
() => [...participants.keys()],
[participants]
);
return (
<div>
{participantIds.map((participantId) => (
<SingleParticipantContainer
{...{ participantId, key: participantId }}
/>
))}
</div>
);
};
export default ParticipantsGridContainer;
SingleParticipantContainer
这个容器将从props获取participantId,并从useParticipant钩子获取网络摄像头流和其他信息。它将渲染提供的参与者ID的音频和视频流。
src/screens/speakerScreen/SingleParticipantContainer.js
import { useParticipant } from "@videosdk.live/react-sdk";
import React, { useEffect, useMemo, useRef } from "react";
import ReactPlayer from "react-player";
const SingleParticipantContainer = ({ participantId }) => {
const { micOn, micStream, isLocal, displayName, webcamStream, webcamOn } =
useParticipant(participantId);
const audioPlayer = useRef();
const videoStream = useMemo(() => {
if (webcamOn && webcamStream) {
const mediaStream = new MediaStream();
mediaStream.addTrack(webcamStream.track);
return mediaStream;
}
}, [webcamStream, webcamOn]);
useEffect(() => {
if (!isLocal && audioPlayer.current && micOn && micStream) {
const mediaStream = new MediaStream();
mediaStream.addTrack(micStream.track);
audioPlayer.current.srcObject = mediaStream;
audioPlayer.current.play().catch((err) => {
if (
err.message ===
"play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD"
) {
console.error("audio" + err.message);
}
});
} else {
audioPlayer.current.srcObject = null;
}
}, [micStream, micOn, isLocal, participantId]);
return (
<div style={{ height: 200, width: 360, position: "relative" }}>
<audio autoPlay playsInline controls={false} ref={audioPlayer} />
<div
style={{ position: "absolute", background: "#ffffffb3", padding: 8 }}
>
<p>Name: {displayName}</p>
<p>Webcam: {webcamOn ? "on" : "off"}</p>
<p>Mic: {micOn ? "on" : "off"}</p>
</div>
{webcamOn && (
<ReactPlayer
playsinline // very very imp prop
pip={false}
light={false}
controls={false}
muted={true}
playing={true}
url={videoStream}
height={"100%"}
width={"100%"}
onError={(err) => {
console.log(err, "participant video error");
}}
/>
)}
</div>
);
};
export default SingleParticipantContainer;
我们的演讲者屏幕已经完成,现在我们可以开始编写ViewerScreenContainer。
步骤 4:观众屏幕
观众屏幕将用于观众参与者,当演讲者开始直播时,他们将观看HLS流。\ 与演讲者屏幕一样,这个屏幕也将有初始化过程。\ src/screens/ViewerScreenContainer.js
import {
MeetingConsumer,
Constants,
MeetingProvider,
useMeeting,
} from "@videosdk.live/react-sdk";
import React, { useEffect, useMemo, useRef } from "react";
import Hls from "hls.js";
import { authToken } from "../api";
const HLSPlayer = () => {
const { hlsUrls, hlsState } = useMeeting();
const playerRef = useRef(null);
const hlsPlaybackHlsUrl = useMemo(() => hlsUrls.playbackHlsUrl, [hlsUrls]);
useEffect(() => {
if (Hls.isSupported()) {
const hls = new Hls({
capLevelToPlayerSize: true,
maxLoadingDelay: 4,
minAutoBitrate: 0,
autoStartLoad: true,
defaultAudioCodec: "mp4a.40.2",
});
let player = document.querySelector("#hlsPlayer");
hls.loadSource(hlsPlaybackHlsUrl);
hls.attachMedia(player);
} else {
if (typeof playerRef.current?.play === "function") {
playerRef.current.src = hlsPlaybackHlsUrl;
playerRef.current.play();
}
}
}, [hlsPlaybackHlsUrl, hlsState]);
return (
<video
ref={playerRef}
id="hlsPlayer"
autoPlay
controls
style={{ width: "70%", height: "70%" }}
playsInline
playing
onError={(err) => console.log(err, "hls video error")}
></video>
);
};
const ViewerScreenContainer = ({ meetingId }) => {
return (
<MeetingProvider
token={authToken}
config={{ meetingId, name: "C.V. Raman", mode: "VIEWER" }}
joinWithoutUserInteraction
>
<MeetingConsumer>
{({ hlsState }) =>
hlsState === Constants.hlsEvents.HLS_PLAYABLE ? (
<HLSPlayer />
) : (
<p>Waiting for host to start stream...</p>
)
}
</MeetingConsumer>
</MeetingProvider>
);
};
export default ViewerScreenContainer;
我们的观众屏幕已经完成,现在我们可以测试我们的应用。\ npm run start
交互式直播应用的输出
此应用的源代码可在此GithubRepo中找到。
接下来做什么?
这只是使用Video SDK构建交互式直播应用的一个非常基本的示例,您可以按照自己的方式进行自定义。
- 添加更多的CSS使UI更具交互性
- 使用PubSub添加聊天功能
- 实现Change Mode,通过这个功能,我们可以将任何参与者从观众切换到演讲者,反之亦然。
- 您还可以参考我们使用VideoSDK的React包构建的预构建应用。这是Github Repo。
更多React资源
- React视频通话快速入门文档
- React交互式直播快速入门文档
- 使用React Hooks构建视频聊天应用
- 代码示例
结论
通过这样,我们成功地使用Video SDK构建了React交互式直播应用。如果您想要添加聊天消息和屏幕共享等功能,您可以随时参考文档。
本文暂时没有评论,来添加一个吧(●'◡'●)