nimeet 文档中心
English

Electron(桌面) 快速开始与功能指南

Electron(桌面):前置条件、安装、Token、加入频道、发布订阅、事件、错误处理与排障;接口名与签名在构建时取自公开 SDK 接口定义。

接口小节由公开 SDK 接口定义生成

版本 v1.1.0 · 更新于 2026-10-26 · 修订 1

Electron 端 = Web SDK 的公开面 + 桌面采集桥。渲染进程里用的还是 @nimeet/rtc-web 那套 AgoraRTC 形状的 API,桌面端额外提供「枚举窗口/屏幕源」和「source-pinned 屏幕共享」,因为浏览器的 getDisplayMedia 无法指定某个窗口。

前置条件

  • Node.js ≥ 22、pnpm 10;Electron ≥ 28(主进程/预加载/渲染进程三处都要改)。
  • contextIsolation: true(默认)。本 SDK 的桌面桥通过预加载脚本注入,不依赖 nodeIntegration。
  • 已拿到 appId 和一个能签发 Token 的后端(见 控制台开通服务与获取凭证)。

安装

bash
pnpm add @nimeet/sdk-electron @nimeet/rtc-web

三个入口分别给三处用:@nimeet/sdk-electron/main(主进程)、@nimeet/sdk-electron/preload(预加载)、@nimeet/sdk-electron(渲染进程/通用工具)。

获取 Token

与 Web 完全相同:Token 由你的后端调 POST /v1/tokens 签发,渲染进程只拿 { appId, rtcToken, rtcUid }。 主进程也不要持有 customerSecret——它会出现在崩溃转储和用户可读的文件系统里。

加入频道

主进程注册桌面桥:

javascript
// main.js(主进程)
const { app, BrowserWindow, ipcMain, desktopCapturer } = require('electron');
const { registerDesktopBridge } = require('@nimeet/sdk-electron/main');

app.whenReady().then(() => {
  registerDesktopBridge({ ipcMain, desktopCapturer });
});

预加载脚本暴露最小面:

javascript
// preload.js(预加载)
const { contextBridge, ipcRenderer } = require('electron');
const { exposeDesktopBridge } = require('@nimeet/sdk-electron/preload');

exposeDesktopBridge(contextBridge, ipcRenderer);

渲染进程里用 Web 形状的客户端入会(与 Web 端同一套方法):

javascript
import AgoraRTC from '@nimeet/rtc-web';

const client = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' });
client.on('user-published', async (user, mediaType) => {
  await client.subscribe(user, mediaType);
  if (mediaType === 'video') user.videoTrack?.play('remote-player');
});
const uid = await client.join(appId, 'weekly-sync', rtcToken, rtcUid);

发布与订阅

摄像头/麦克风与 Web 一致;屏幕共享用「源」而不是默认选择器:

javascript
import { pickPrimarySource, groupSources } from '@nimeet/sdk-electron';

// window.nimeetDesktop 由预加载脚本注入
const sources = await window.nimeetDesktop.getSources({ types: ['screen', 'window'] });
const groups = groupSources(sources);          // 按「屏幕 / 窗口」分组,供下拉框使用
const primary = pickPrimarySource(sources);    // 主屏,作为默认值

const screenTrack = await AgoraRTC.createScreenVideoTrack(
  { electronScreenSourceId: primary.id },
  'disable',
);
await client.publish(screenTrack);

electronScreenSourceId 是「钉住的源」(字段名来自 ScreenVideoTrackInitConfig):共享期间不会因为用户切换窗口而变——这是桌面端与浏览器 getDisplayMedia 最重要的区别。

事件

与 Web 相同的事件集(user-joined / user-published / connection-state-change / token-privilege-will-expire / network-quality…), 另外桌面桥额外提供两个通道事件(前缀 nimeet:desktop:):

事件方向用途
nimeet:desktop:sources渲染 ← 主返回屏幕/窗口源列表
nimeet:desktop:capture-permission渲染 ← 主macOS 屏幕录制权限状态(Chromium 不暴露该状态)

错误处理

常见错误来源有三类,建议分开处理:

  1. RTC 错误:与 Web 相同的 AgoraRTCError(code 字符串);
  2. IPC 错误:主进程未注册桥 → 渲染进程 window.nimeetDesktop 为 undefined;预加载未注入 → 同上;
  3. 系统权限:macOS「屏幕录制」未授权时,源列表为空而不是报错。
javascript
const sources = await window.nimeetDesktop?.getSources({ types: ['screen'] }) ?? [];
if (sources.length === 0) {
  // macOS:引导用户去 系统设置 → 隐私与安全性 → 屏幕录制 勾选本应用后重启
}

排障

现象原因处理
window.nimeetDesktop 是 undefined预加载未执行 / contextIsolation 配置不符检查 webPreferences.preload 路径与打包后文件是否存在
源列表为空(macOS)屏幕录制权限未授予系统设置授权后重启应用(权限变更不会热生效)
共享出黑屏选中的是受保护的窗口(如 DRM 播放器)改用整屏源
渲染进程报 require is not defined用了 CommonJS 写法渲染进程按 ESM 写,或让打包器处理
打包后 IPC 报 No handler registered主进程注册桥的代码被 tree-shaking 掉在主进程入口显式调用 registerDesktopBridge

下一步

平台信息

项值
平台Electron(桌面)
语言TypeScript
SDK 包@nimeet/sdk-electron
接口版本4.6.2
兼容参考声网 electron 端 API

本端公开接口与声网 electron 端 API 对齐;安装与运行要求见上面前置条件。

可用性

该端 SDK:正式可用。本页代码片段使用公开 API;运行时的能力边界以实际发布的 SDK 包为准。

加入频道链路

下列方法名、参数类型与返回值与同端 API 参考一致。一个平台若有多个重载,这里展示最常用的那一个;完整重载见同端 API 参考页。

步骤接口方法重载数
订阅远端媒体IBaseSpatialAudioEnginemuteRemoteAudioStream1
创建实例 / 初始化ILocalSpatialAudioEngineinitialize1
续期 TokenIMusicContentCenterrenewToken1
开启视频与本地预览IRtcEngineenableVideo1
加入频道IRtcEnginejoinChannel1
离开频道IRtcEngineleaveChannel1
频道场景IRtcEnginesetChannelProfile1
切换角色IRtcEnginesetClientRole1
绑定本地画面IRtcEnginesetupLocalVideo1
typescript
muteRemoteAudioStream(uid: number, mute: boolean): number
initialize(): number
renewToken(token: string): number
enableVideo(): number
joinChannel(token: string, channelId: string, uid: number, options: ChannelMediaOptions): number
leaveChannel(options?: LeaveChannelOptions): number
setChannelProfile(profile: ChannelProfileType): number
setClientRole(role: ClientRoleType, options?: ClientRoleOptions): number
setupLocalVideo(canvas: VideoCanvas): number

事件与回调

回调注册在 IRtcEngineEventHandler 上;不同端的命名可能不同,完整清单见同端 API 参考页。

回调签名用途
onConnectionStateChangedonConnectionStateChanged(connection: RtcConnection, state: ConnectionStateType, reason: ConnectionChangedReasonType): void入会结果 / 连接状态变化:据此更新 UI 并决定是否重连。
onUserJoinedonUserJoined(connection: RtcConnection, remoteUid: number, elapsed: number): void远端用户加入:分配画面容器。
onFirstRemoteVideoDecodedonFirstRemoteVideoDecoded(connection: RtcConnection, remoteUid: number, width: number, height: number, elapsed: number): void远端视频状态:首帧解码后即可渲染。
onUserOfflineonUserOffline(connection: RtcConnection, remoteUid: number, reason: UserOfflineReasonType): void远端用户离开:释放容器与订阅。
onRequestTokenonRequestToken(connection: RtcConnection): voidToken 即将过期:调用服务端续期后 `renewToken`。
onErroronError(err: ErrorCodeType, msg: string): void运行时错误:`err` 为声网错误号,按错误码表分流。
onNetworkQualityonNetworkQuality(connection: RtcConnection, remoteUid: number, txQuality: QualityType, rxQuality: QualityType): void网络质量:上报到水晶球或提示用户。

错误码

常量值
ErrAborted20
ErrAdmGeneralError1005
ErrAdmInitPlayout1008
ErrAdmInitRecording1011
ErrAdmStartPlayout1009
ErrAdmStartRecording1012
ErrAdmStopPlayout1010
ErrAdmStopRecording1013
ErrAlreadyInUse19
ErrBitrateLimit115
ErrBufferTooSmall6
ErrCertRaw1001
ErrClientIsBannedByServer123
ErrConnectionInterrupted111
ErrConnectionLost112
ErrDatastreamDecryptionFailed122
ErrDecryptionFailed120
ErrEncryptedStreamNotAllowedPublish130
ErrFailed1
ErrInitNetEngine21
ErrInvalidAppId101
ErrInvalidArgument2
ErrInvalidChannelName102
ErrInvalidState8
ErrInvalidTokennull
ErrInvalidUserAccount134
ErrInvalidUserId121
ErrJoinChannelRejected17
ErrLeaveChannelRejected18
ErrNoPermission9
ErrNoServerResources103
ErrNotInChannel113
ErrNotInitialized7
ErrNotReady3
ErrNotSupported4
ErrOk0
ErrPcmsendBufferoverflow201
ErrPcmsendFormat200
ErrRefused5
ErrResourceLimited22
ErrSetClientRoleNotAuthorized119
ErrSizeTooLarge114
ErrStreamMessageTimeout117
ErrTimedout10
ErrTokenExpired109
ErrTooManyDataStreams116
ErrVdmCameraNotAuthorized1501
IRtcEnginenull

平台 REST 层用 REST 错误码;SDK 层把连接/鉴权失败映射成声网错误号,映射表见 各端 SDK 错误标识。

本页由文档构建流水线生成 · 2026-10-31 01:24:02 UTC · 文档中心 v1.1.0.

内容依据公开 API 定义.

ni-meet 是自建 RTC PaaS,媒体面基于 LiveKit(Apache-2.0),并与声网 API 兼容。