实时视频通话能够拉近人与人之间的距离,为用户提供沉浸式的交流体验,帮助你的 app 提高用户黏性。
本文介绍如何通过少量代码集成声网视频 SDK ,在你的 app 里实现高质量、低延迟的视频通话功能。
下图展示在 app 中实现声网视频通话的基本工作流程:
实现视频通话的步骤如下:
1. 设置角色
将用户角色均设置为主播。
2. 加入频道
调用 joinChannel
创建并加入频道。在 App ID 一致的前提下,传入相同频道名的用户会进入同一个频道。
3、4. 在频道内发布和订阅音视频
加入频道后,两位主播可以发布音视频并互相订阅。
正式开始之前,请确保具备以下条件:
参考以下操作,在你的 app 中实现视频通话功能:
在本地文件夹中为 Electron 项目新建一个目录,并在项目根目录下创建以下文件:
package.json
: 用于安装和管理项目依赖项。index.html
:用于设计 app 的用户界面。main.js
:主进程文件。renderer.js
:渲染进程文件,用于实现与声网 Electron SDK 的交互。参考以下步骤,使用 npm 将声网 Electron SDK 集成到你的 Electron 项目:
在 package.json
文件中添加以下代码:
{
"name": "electron-demo-app",
"version": "0.1.0",
"author": "your name",
"description": "My Electron app",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"agora_electron": {
"platform": "darwin",
"prebuilt": true
},
"dependencies": { "agora-electron-sdk": "latest" },
"devDependencies": {"electron": "latest" }
}
{
"name": "electron-demo-app",
"version": "0.1.0",
"author": "your name",
"description": "My Electron app",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"agora_electron": {
"platform": "win32",
"prebuilt": true,
"arch": "ia32"
},
"dependencies": { "agora-electron-sdk": "latest" },
"devDependencies": {"electron": "latest" }
}
字段的具体含义如下:
agora-electron-sdk
:声网 Electron SDK 的版本号。设为 latest
表示获取最新版本的 SDK,其它版本可在 agora-electron-sdk 中查看。electron
:Electron 的版本号,支持 5.0.0 及以上版本(包括最新版本)。如果使用搭载 M1 芯片的 Mac 设备,Electron 的版本号需要设为 11.0.0 或以上。platform
:默认根据系统选择,macOS 为 darwin
,Windows 为 win32
。prebuilt
:默认设为 true
,防止出现 Electron 或 Node.js 版本与 SDK 不兼容的问题。arch
:默认根据系统选择。在终端中进入项目根目录,运行如下命令安装依赖项:
npm install
npm install -D --arch=ia32 electron
npm install
npm install -D --arch=ia32 electron
安装 32 位的 Electron,然后运行 npm install
。否则会收到报错:Not a valid win32 application
。node_modules
文件夹,建议先删除该文件夹,再运行 npm install
,以免出现报错。本节介绍如何使用声网 SDK 在你的 app 中实现视频通话功能。
将以下代码复制到 index.html
文件,创建一个只包含本地视频窗口和远端视频窗口的用户界面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Electron Quickstart</title>
</head>
<body>
<h1>Electron Quickstart</h1>
<!--在界面中添加本地视频窗口 -->
<div
id="join-channel-local-video"
style="width: 300px; height: 300px; float: left"
></div>
<!--在界面中添加远端视频窗口 -->
<div
id="join-channel-remote-video"
style="width: 300px; height: 300px; float: left"
></div>
</body>
<script src="./renderer.js"></script>
</html>
将以下代码复制到 main.js
文件,实现基本的 Electron 项目主进程:
const { app, BrowserWindow } = require("electron");
const path = require("path");
// 如果使用 Electron 9.x 及以上版本,需要将 allowRendererProcessReuse 设为 false
app.allowRendererProcessReuse = false;
function createWindow() {
// 创建浏览器窗口
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// preload: path.join(__dirname, "renderer.js"),
// 将 nodeIntegration 设置 true 以及 contextIsolation 设为 false
nodeIntegration: true,
contextIsolation: false,
},
});
// 加载 index.html 文件的内容
mainWindow.loadFile("./index.html");
// 开启开发者工具
mainWindow.webContents.openDevTools();
}
// 管理 Electron 应用的浏览器窗口
app.whenReady().then(() => {
createWindow();
// 如果当前没有窗口打开,则新建一个窗口(适用于 macOS)
app.on("activate", function () {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
// 如果所有窗口都已关闭,则退出 Electron 应用(适用于 Windows)
app.on("window-all-closed", function () {
if (process.platform !== "darwin") app.quit();
});
macOS 自 v10.14 起,使用摄像头和麦克风前需要检查并获取设备的使用权限。你需要在主进程中调用 Electron 原生的 askForMediaAccess
方法,来向用户请求摄像头和麦克风权限。在 main.js
文件中添加如下代码:
// 检查并获取设备权限
async function checkAndApplyDeviceAccessPrivilege() {
// 检查并获取摄像头权限
const cameraPrivilege = systemPreferences.getMediaAccessStatus('camera');
console.log(`Camera privilege before applying: ${cameraPrivilege}`);
if (cameraPrivilege !== 'granted') {
await systemPreferences.askForMediaAccess('camera');
console.log('Requested camera access from user');
}
// 检查并获取麦克风权限
const micPrivilege = systemPreferences.getMediaAccessStatus('microphone');
console.log(`Microphone privilege before applying: ${micPrivilege}`);
if (micPrivilege !== 'granted') {
await systemPreferences.askForMediaAccess('microphone');
console.log('Requested microphone access from user');
}
}
checkAndApplyDeviceAccessPrivilege();
视频通话的 API 调用时序见下图:
将以下代码复制到 renderer.js
文件,实现以上 API 的调用逻辑:
const {
createAgoraRtcEngine,
VideoMirrorModeType,
VideoSourceType,
RenderModeType,
ChannelProfileType,
ClientRoleType,
} = require("agora-electron-sdk");
let rtcEngine;
let localVideoContainer;
let remoteVideoContainer;
let isJoined = false;
// 填入你的临时 Token
let token = "Your token";
// 用户 id,并确保其在频道内的唯一性
let uid = 123;
const EventHandles = {
// 监听本地用户加入频道事件
onJoinChannelSuccess: ({ channelId, localUid }, elapsed) => {
console.log('成功加入频道:' + channelId);
isJoined = true;
// 本地用户加入频道后,设置本地视频窗口
rtcEngine.setupLocalVideo({
sourceType: VideoSourceType.VideoSourceCameraPrimary,
view: localVideoContainer,
mirrorMode: VideoMirrorModeType.VideoMirrorModeDisabled,
renderMode: RenderModeType.RenderModeFit,
});
},
onLeaveChannel: ({ channelId, localUid }, stats) => {
console.log('成功退出频道:' + channelId);
isJoined = false;
},
// 监听远端用户加入频道事件
onUserJoined: ({ channelId, localUid }, remoteUid, elapsed) => {
console.log('远端用户 ' + remoteUid + ' 已加入');
// 远端用户加入频道后,设置远端视频窗口
rtcEngine.setupRemoteVideoEx(
{
sourceType: VideoSourceType.VideoSourceRemote,
uid: remoteUid,
view: remoteVideoContainer,
mirrorMode: VideoMirrorModeType.VideoMirrorModeDisabled,
renderMode: RenderModeType.RenderModeFit,
},
{ channelId },
);
},
};
window.onload = () => {
const os = require("os");
const path = require("path");
// 填入你的 App ID
const APPID = "Your App ID";
// 填入生成 Token 时使用的频道名
const channel = "Your channel";
localVideoContainer = document.getElementById("join-channel-local-video");
remoteVideoContainer = document.getElementById("join-channel-remote-video");
const sdkLogPath = path.resolve(os.homedir(), "./test.log");
// 创建 RtcEngine 实例
rtcEngine = createAgoraRtcEngine();
// 初始化 RtcEngine 实例
rtcEngine.initialize({
appId: APPID,
logConfig: { filePath: sdkLogPath }
});
// 注册事件回调
rtcEngine.registerEventHandler(EventHandles);
// 设置频道场景为直播场景
rtcEngine.setChannelProfile(ChannelProfileType.ChannelProfileLiveBroadcasting);
// 设置用户角色,主播设为 ClientRoleBroadcaster,观众设为 ClientRoleAudience
rtcEngine.setClientRole(ClientRoleType.ClientRoleBroadcaster);
// 视频默认禁用,你需要调用 enableVideo 启用视频流
rtcEngine.enableVideo();
// 开启摄像头预览
rtcEngine.startPreview();
// 使用临时 Token 加入频道
rtcEngine.joinChannel(token, channel, uid, {});
};
参考以下步骤测试你的 Electron 项目:
在 renderer.js
文件中,将 "Your App ID"、"Your token"、“Your channel” 分别替换为你的 App ID、临时 Token 和频道名,详见开始使用声网平台。
在终端中进入项目根目录,运行以下命令:
npm start
项目成功运行后,你会看到一个自动弹出的窗口,在窗口中看到本地的视频画面。
邀请一位朋友克隆 https://github.com/AgoraIO/API-Examples-Web 到本地,在浏览器中打开 Demo/index.html 文件,并输入相同的 App ID、频道名称和临时 Token。
你的朋友成功加入后,你们可以听见、看见对方。
在测试或生产环境中,为确保通信安全,声网推荐使用 token 服务器来生成 token,详见使用 Token 鉴权。
本节提供了额外的信息供参考。
声网在 Github 上提供一个开源项目的 API 示例项目 Electron API Example 供你参考。
除了使用 npm 集成以外,你也可以进入 Electron-SDK 手动编译最新的 SDK,集成到应用中。