本文将介绍如何在 Electron 环境下,快速接入实时音视频 SDK,实现一个基本的音视频通话。
环境准备
Windows 7+,推荐 Windows 10/11。
MacOS 10.13+。
Node.js 16.20.2 或更高稳定版。
接入指引
步骤1. 导入 SDK
1. 在命令行窗口中执行如下命令,安装 Electron,建议版本号 >= 4.0.0。
npm install electron@24.8.8 --save-dev
注意:
Mac 平台下,Electron 从 25.0.0 版本开始,ElectronSDK 的事件通知会失效,请使用 Electron 25.0.0 以下的版本。
2. 在您的 Electron 项目中使用 npm 命令安装 SDK 包:
npm install trtc-electron-sdk@latest --save
说明:
步骤2. 配置工程
1. 为了正确打包运行 Electron 版本的 TRTC SDK(也就是
trtc_electron_sdk.node
文件),您还需要执行如下命令以安装 native-ext-loader
工具。npm install native-ext-loader@latest --save-dev
2. 为了解决 webpack 无法处理 Node.js 的内置 'fs' 模块,我们需要执行以下命令安装
path-browserify
工具。npm install path-browserify --save-dev
3. 以 webpack项目为例,在
webpack.config.js
包含了项目构建的配置信息,webpack.config.js
文件的位置如下:通常情况下,
webpack.config.js
位于项目的根目录。使用
create-react-app
创建项目的情况下,此配置文件为 node_modules/react-scripts/config/webpack.config.js
。使用
vue-cli
创建项目的情况下,webpack 的配置存放在 vue.config.js
配置中的 configureWebpack
属性中。如您的工程文件经过了定制化,还请自行查找 webpack 配置。
首先使
webpack.config.js
在构建时可以接收名为 --target_platform
的命令行参数,以使代码构建过程按不同的目标平台特点正确打包,在 module.exports
之前添加以下代码:const os = require('os');const targetPlatform = (function(){let target = os.platform();for (let i=0; i<process.argv.length; i++) {if (process.argv[i].includes('--target_platform=')) {target = process.argv[i].replace('--target_platform=', '');break;}}if (!['win32', 'darwin'].includes) target = os.platform();return target;})();
注意:
os.platform()
返回的结果中,"darwin" 表示 Mac 平台。"win32" 表示 Windows 平台,不论 64 位还是 32 位。然后在
module
选项中添加以下配置,targetPlatform
变量可以使 rewritePath
可以根据不同的目标平台切换不同的配置:module: {rules: [{test: /\\.node$/,loader: 'native-ext-loader',options: {rewritePath: targetPlatform === 'win32' ? './resources' : '../Resources'// 针对开发环境// rewritePath: './node_modules/trtc-electron-sdk/build/Release'}},]}
该配置的含义是:
打包 Windows 下的
.exe
文件时,让 native-ext-loader
到 [应用程序根目录]/resources
目录下加载 TRTC SDK。打包 Mac 下的
.dmg
时,让 native-ext-loader
到 [应用程序目录]/Contents/Frameworsk/../Resources
目录下加载 TRTC SDK。本地开发运行时,让
native-ext-loader
到 ./node_modules/trtc-electron-sdk/build/Release
目录下加载 TRTC SDK,请参见 simple demo 配置。接着在
resolve
选项中添加以下配置,该配置用于处理 Node.js 核心模块在浏览器环境中的兼容性问题:resolve: {fallback: {"fs": false,"path": require.resolve("path-browserify"),}}
最后在
externals
中配置下列代码使得 webpack 允许加载本地模块:externals: {"trtc-electron-sdk": "commonjs trtc-electron-sdk"}
4. 设备权限申请示例代码:
const { systemPreferences } = require('electron');async function checkAndApplyDeviceAccessPrivilege() {if (process.platform === "darwin" || process.platform === 'win32') {// 检查并申请摄像头权限const cameraPrivilege = systemPreferences.getMediaAccessStatus("camera");if (cameraPrivilege !== "granted") {await systemPreferences.askForMediaAccess("camera");}// 检查并申请麦克风权限const micPrivilege = systemPreferences.getMediaAccessStatus("microphone");if (micPrivilege !== "granted") {await systemPreferences.askForMediaAccess("microphone");}// 检查访问屏幕权限const screenPrivilege = systemPreferences.getMediaAccessStatus("screen");if (screenPrivilege !== 'granted') {// 没有屏幕访问权限,做后续处理...}}}async function createWindow(width = 1366, height = 668) {await checkAndApplyDeviceAccessPrivilege();// ... 其他窗口创建逻辑}
步骤3. 创建 TRTC 实例
创建 TRTC 实例并设置监听,通过设置事件回调接口,您可以监听 SDK 在运行期间所发生的错误信息、警告信息、流量统计信息、网络质量信息以及各种音视频事件。
import TRTCCloud from 'trtc-electron-sdk';const rtcCloud = TRTCCloud.getTRTCShareInstance();function onError(errCode, errMsg) {// errorCode 可参考 https://cloud.tencent.com/document/product/647/32257#.E9.94.99.E8.AF.AF.E7.A0.81.E8.A1.A8console.log(errCode, errMsg);}function onWarning(warningCode, warningMsg) {// warningCode 可参考 https://cloud.tencent.com/document/product/647/32257#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8console.log(warningCode, warningMsg);}rtcCloud.on('onError', onError);rtcCloud.on('onWarning', onWarning);
步骤4. 进入房间
在调用
enterRoom
接口进房时需要填写两个关键参数,即 TRTCParams
和 TRTCAppScene
,接下来进行详细介绍:参数一:TRTCAppScene
该参数用于指定您的应用场景,即在线直播还是实时通话:
实时通话:包含
TRTCAppSceneVideoCall
和 TRTCAppSceneAudioCal
两个可选项,分别是视频通话和语音通话,该模式适合 1对1 的音视频通话,或者参会人数在 300 人以内的在线会议。在线直播:包含
TRTCAppSceneLIVE
和 TRTCAppSceneVoiceChatRoom
两个可选项,分别是视频直播和语音直播,该模式适合十万人以内的在线直播场景,但需要您在接下来介绍的 TRTCParams
参数中指定 角色(role) 这个字段,也就是将房间中的用户区分为 主播(anchor) 和 观众(audience) 两种不同的角色。参数二:TRTCParams
TRTCParams 由很多的字段构成,但通常您只需要关心如下几个字段的填写:
参数名称 | 字段含义 | 补充说明 | 数据类型 | 填写示例 |
SDKAppID | 应用 ID | 数字 | 1400000123 | |
userId | 用户 ID | 即用户名,只允许包含大小写英文字母(a-z、A-Z)、数字(0-9)及下划线和连词符。注意 TRTC 不支持同一个 userId 在两台不同的设备上同时进入房间,否则会相互干扰。 | 字符串 | “denny” 或者 “123321” |
userSig | 进房鉴权票据 | 字符串 | eJyrVareCeYrSy1SslI... | |
roomId | 房间号 | 数字类型的房间号。注意如果您想使用字符串类型的房间号,请使用 strRoomId 字段,而不要使用 roomId 字段,因为 strRoomId 和 roomId 不可以混用。 | 数字 | 29834 |
strRoomId | 房间号 | 字符串类型的房间号。注意 strRoomId 和 roomId 不可以混用,“123” 和 123 在 TRTC 后台服务看来并不是同一个房间。 | 字符串 | “29834” |
role | 角色 | 分为“主播”和“观众”两种角色,只有当 TRTCAppScene 被指定为 TRTCAppSceneLIVE 或 TRTCAppSceneVoiceChatRoom 这两种直播场景时才需要指定该字段。 | 枚举值 | TRTCRoleAnchor 或 TRTCRoleAudience |
注意:
TRTC 不支持同一个 userId 在两台不同的设备上同时进入房间,否则会相互干扰。
每个端在应用场景 appScene 上必须要进行统一,否则会出现一些不可预料的问题。
在准备好
TRTCAppScene
和 TRTCParams
这两个参数后,就可以调用 enterRoom
接口函数进入房间了。import { TRTCParams, TRTCRoleType, TRTCAppScene } from 'trtc-electron-sdk';const param = new TRTCParams();param.sdkAppId = 1400000123;param.userId = "denny";param.roomId = 123321;param.userSig = "xxx";param.role = TRTCRoleType.TRTCRoleAnchor;// 如果您的场景是“在线直播”,请将应用场景设置为 TRTC_APP_SCENE_LIVErtcCloud.enterRoom(param, TRTCAppScene.TRTCAppSceneLIVE);
调用接口后,您会收到来自 TRTCCallback 中的 onEnterRoom(result) 回调:
如果进房成功,result 会是一个正数(result > 0),表示加入房间的时间消耗,单位是毫秒(ms)。
如果进房失败,result 会是一个负数(result < 0),表示进房失败的错误码。
function onEnterRoom(result) {// onEnterRoom 参见 https://web.sdk.qcloud.com/trtc/electron/doc/zh-cn/trtc_electron_sdk/TRTCCallback.html#event:onEnterRoomif (result > 0) {console.log('Enter room succeed');} else {// 参见进房错误码 https://cloud.tencent.com/document/product/647/32257#.E8.BF.9B.E6.88.BF.E7.9B.B8.E5.85.B3.E9.94.99.E8.AF.AF.E7.A0.81console.log('Enter room failed');}}rtcCloud.on('onEnterRoom', onEnterRoom);
步骤5. 打开/关闭摄像头
startLocalPreview(views)
接口启动本地摄像头采集和预览,这个接口会启动默认的摄像头,可以通过 setCurrentCameraDevice() 接口选用其它摄像头 当开始渲染首帧摄像头画面时,您会收到 TRTCCallback 中的 onFirstVideoFrame('') 回调。Name | Type | Description |
views | Array.<HTMLElement> | HTMLElement | null | required 承载预览画面单个的 HTML 块节点或者 HTML 块节点数组 如果传入 null 则不预览摄像头画面,但不影响摄像头采集 |
// 要预览摄像头图像,您需要在 DOM 中放置一个 HTML 元素,// 这可以是一个 div 标签,假设其 ID 为 local-video。const view = document.getElementById('local-video');rtcCloud.startLocalPreview(view);
stopLocalPreview()
接口停止本地摄像头采集和预览。rtcCloud.stopLocalPreview();
步骤6. 打开/关闭麦克风
startLocalAudio(quality)
开启麦克风采集,请根据您的需求选择以下其中一个声音质量参数quality
。const { TRTCAudioQuality } = require('trtc-electron-sdk');// 开启麦克风采集,设置当前场景为:标准模式(默认模式)rtcCloud.startLocalAudio(TRTCAudioQuality.TRTCAudioQualityDefault);
// 开启麦克风采集,设置当前场景为:语音模式// 具有高的噪声抑制能力,有强有弱的网络阻力rtcCloud.startLocalAudio(TRTCAudioQuality.TRTCAudioQualitySpeech);
// 开启麦克风采集,设置当前场景为:音乐模式// 为获得高保真度,低音质损失,建议配合专业声卡使用rtcCloud.startLocalAudio(TRTCAudioQuality.TRTCAudioQualityMusic);
调用
stopLocalAudio()
关闭麦克风采集并停止推送本地音频信息。rtcCloud.stopLocalAudio()
步骤7. 播放/停止视频流
1. 当您收到 onUserVideoAvailable(userId, 1) 通知时,代表该路画面已经有可用的视频数据帧到达。
2. 您需要调用 startRemoteView(userId, views, streamType) 接口加载该用户的远程画面。 之后您会收到名为 onFirstVideoFrame(userId) 的首帧画面渲染回调。
Parameters:
Name | Type | Description |
userId | String | required 对方的用户标识 |
views | Array.<HTMLElement> | HTMLElement | null | required 承载预览画面单个的 HTML 块节点或者 HTML 块节点数组 如果传入 null 则不预览远端用户画面,但不影响拉取远端视频,适合需要自定义渲染的场景 |
streamType | TRTCVideoStreamType | required 视频流类型: TRTCVideoStreamTypeBig 大画面视频流 TRTCVideoStreamTypeSmall 小画面视频流 TRTCVideoStreamTypeSub 辅流(屏幕分享) |
// 要预览摄像头图像,您需要在 DOM 中放置一个 HTML 元素,// 这可以是一个 div 标签,假设其 ID 为 local-video。const view = document.getElementById('local-video');rtcCloud.startRemoteView("denny", view, TRTCVideoStreamType.TRTCVideoStreamTypeBig);
注意:
如果主播的上行网络和性能比较好,则可以同时送出大小两路画面。
SDK 不支持单独开启小画面,小画面必须依附于主画面而存在。
调用
stopRemoteView(userId, streamType)
停止播放远端画面。// 停止播放rtcCloud.stopRemoteView("denny", TRTCVideoStreamType.TRTCVideoStreamTypeBig); // 只停止播放 denny 画面rtcCloud.stopAllRemoteView(); // 停止播放所有远端画面
注意:
如果有屏幕分享的画面在显示,则屏幕分享的画面也会一并被关闭。
步骤8. 播放/停止音频流
默认情况下,SDK 将自动播放远程音频,因此您不需要调用任何 API 来手动播放它。
但当您不喜欢自动播放音频时,可以调用
muteRemoteAudio
选择播放或停止远端声音。// 静音rtcCloud.muteRemoteAudio("denny", true); // 仅静音 dennyrtcCloud.muteAllRemoteAudio(true); // 静音所有远端用户
// 取消静音rtcCloud.muteRemoteAudio("denny", false); // 仅取消静音 dennyrtcCloud.muteAllRemoteAudio(false); // 取消静音所有远端用户
步骤9. 退出房间
调用
exitRoom
退出当前的房间,SDK 会通过 TRTCCallback
中的 onExitRoom()
回调通知您。如果您要再次调用 enterRoom()
或者切换到其它的音视频 SDK,请等待 onExitRoom()
回调到来后再执行相关操作, 否则可能会遇到如摄像头、麦克风设备被强占等各种异常问题。const onExitRoom = (reason) => {if (reason == 0) {console.log( "Exit current room by calling the 'exitRoom' api of sdk ...");} else if (reason == 1) {console.log("Kicked out of the current room by server through the restful api...");} else if (reason == 2) {console.log("Current room is dissolved by server through the restful api...");}}// 监听 `onExitRoom` 回调rtcCloud.on('onExitRoom', onExitRoom);
步骤10. 应用打包
1. 打包可执行程序
安装打包工具:推荐使用打包工具
electron-builder
进行打包,您可以执行如下命令安装 electron-builder
。npm install electron-builder@latest --save-dev
2. 修改 package.json 配置
package.json
位于项目的根目录,其中包含了项目打包所必须的信息。但默认情况下,package.json
中的路径是需要修改才能顺利实现打包的,我们可以按如下步骤修改此文件: 1. 修改
main
配置。// 多数情况下,main 文件名称可以任意配置,例如 TRTCSimpleDemo 中的可以配置为:"main": "main.electron.js",// 但是,使用 create-react-app 脚手架创建的项目,main 文件必须配置为:"main": "public/electron.js",
2. 复制以下
build
配置,添加到您的 package.json
文件中,这是 electron-builder
需要读取到的配置信息。Mac 下因合规和设备原因,不同 SDK 版本需要使用不同的配置。"build": {"appId": "[appId 请自行定义]","directories": {"output": "./bin"},"asar": true,"win": {"extraFiles": [{"from": "node_modules/trtc-electron-sdk/build/Release/","to": "./resources","filter": ["**/*"]}]},"mac": {"extraFiles": [{"from": "node_modules/trtc-electron-sdk/build/Release/trtc_electron_sdk.node","to": "./Resources"}]}}
从 10.3 版本开始,Mac 因合规要求,拆解出了运行时的两个动态库,安装 SDK 后位于 node_modules/trtc-electron-sdk/build/mac-framework/ 目录下,构建应用安装包时,需要在 build.mac.extraFiles 下配置这两个动态库,否则会导致应用包运行时崩溃。
"build": {"appId": "[appId 请自行定义]","directories": {"output": "./bin"},"asar": true,"win": {"extraFiles": [{"from": "node_modules/trtc-electron-sdk/build/Release/","to": "./resources","filter": ["**/*"]}]},"mac": {"extraFiles": [{"from": "node_modules/trtc-electron-sdk/build/Release/trtc_electron_sdk.node","to": "./Resources"},{"from": "node_modules/trtc-electron-sdk/build/mac-framework/","to": "./Frameworks"}]}}
从 10.6 版本开始,Mac 下支持原生 ARM64 指令架构的包,同时提供 X64 和 ARM64 指令架构的动态库文件,支持使用 electron-builder 的 “--universal” 参数,构建双指令架构的应用包,优点是可同时在 X64 和 ARM64 芯片的设备上提供优良的性能体验,缺点是应用的包体积大约会增加 70%。不使用 “--universal” 参数时,构建的是单指令架构的应用包,默认与构建时使用的计算机 CPU 芯片类型一致,此时应用安装包在另一种 CPU 芯片类型的机器上将无法安装。
注意:electron-builder 需要升级到 23.0.2 或更高版本。
"build": {"appId": "[appId 请自行定义]","directories": {"output": "./bin"},"asar": true,"asarUnpack": "**\\\\*.{node,dll}","win": {"extraFiles": [{"from": "node_modules/trtc-electron-sdk/build/Release/","to": "./resources","filter": ["**/*"]}]},"mac": {"extraFiles": [{"from": "node_modules/trtc-electron-sdk/build/Release/${arch}/trtc_electron_sdk.node","to": "./Resources"},{"from": "node_modules/trtc-electron-sdk/build/mac-framework/${arch}/","to": "./Frameworks"}]}}
3. 在
scripts
节点下添加以下构建和打包的命令脚本:4. 本文以
create-react-app
和 vue-cli
项目为例,其它工具创建的项目也可以参考此配置:// create-react-app 项目请使用此配置"scripts": {"build:mac": "react-scripts build --target_platform=darwin","build:win": "react-scripts build --target_platform=win32","compile:mac": "electron-builder --mac","compile:mac-universal": "electron-builder --mac --universal", // 10.3 及以下版本不支持"compile:win64": "electron-builder --win --x64","pack:mac": "npm run build:mac && npm run compile:mac","pack:mac-universal": "npm run build:mac && npm run compile:mac-universal", // 10.3 及以下版本不支持"pack:win64": "npm run build:win && npm run compile:win64"}// vue-cli 项目请使用此配置"scripts": {"build:mac": "vue-cli-service build --target_platform=darwin","build:win": "vue-cli-service build --target_platform=win32","compile:mac": "electron-builder --mac","compile:mac-universal": "electron-builder --mac --universal", // 10.3 及以下版本不支持"compile:win64": "electron-builder --win --x64","pack:mac": "npm run build:mac && npm run compile:mac","pack:mac-universal": "npm run build:mac && npm run compile:mac-universal", // 10.3 及以下版本不支持"pack:win64": "npm run build:win && npm run compile:win64"}
参数 | 说明 |
main | Electron 的入口文件,一般情况下可以自由配置。但如果项目使用 create-react-app 脚手架创建,则入口文件必须配置为 public/electron.js |
build.asar | 是否开启 Electron 应用安装包的压缩功能,默认开启。 |
build.asarUnpack | 添加 build.asar 配置的例外文件。10.3 以后的版本,使用 `electron-builder --mac --universal` 命令构建双指令架构的应用包时,需要此配置,否则可能出现文件合并的失败或报错。 |
build.win.extraFiles | 打包 Windows 程序时,electron-builder 会把 from 所指目录下的所有文件复制到 bin/win-unpacked/resources(全小写) |
build.mac.extraFiles | 打包 Mac 程序时,electron-builder 会把 from 指向的 trtc_electron_sdk.node 文件复制到 bin/mac/your-app-name.app/Contents/Resources(首字母大写) |
build.directories.output | 打包文件的输出路径。例如这个配置会输出到 bin 目录下,可根据实际需要修改 |
build.scripts.build:mac | 以 Mac 平台为目标构建脚本 |
build.scripts.build:win | 以 Windows 平台为目标构建脚本 |
build.scripts.compile:mac | 编译为 Mac 下的 .dmg 安装文件 |
build.scripts.compile:win64 | 编译为 Windows 下的 .exe 安装文件 |
build.scripts.pack:mac | 先调用 build:mac 构建代码,再调用 compile:mac 打包成 .dmg 安装文件 |
build.scripts.pack:win64 | 先调用 build:win 构建代码,再调用 compile:win64 打包成 .exe 安装文件 |
3. 执行打包命令
打包 Mac.dmg 安装文件:
cd [项目目录]npm run pack:mac// ornpm run pack:mac-universal
成功执行后,打包工具会生成
bin/your-app-name-0.1.0.dmg
安装文件,请选择此文件发布。打包 Windows.exe 安装文件:
cd [项目目录]npm run pack:win64
成功执行后,打包工具会生成
bin/your-app-name Setup 0.1.0.exe
安装文件,请选择此文件发布。注意
TRTC Electron SDK 暂不支持跨平台打包(例如在 Mac 下打包 Windows 的 .exe 文件,或在 Windows 平台下打包 Mac 的 .dmg 文件)。目前我们正在研究跨平台打包方案,敬请期待。
常见问题
您可以在 API 参考 查看所有函数列表及其描述。
如果您的接入和使用中遇到问题,请参见 常见问题。