- macOs支持 x64 、arm64
- windows支持 ia32 、 x64
- electron支持 12.0.18~22.3.27
前提:electron 版本 >=14.0.0, 需要install @electron/remote
npm install @electron/remote --global-style --no-save --legacy-peer-deps
win:需要在windows平台上执行install
32位:
npm install @plasosdk/plaso-electron-sdk --plaso_electron_sdk_arch=ia32 --plaso_electron_sdk_platform=win32 --global-style --no-save
64位:
npm install @plasosdk/plaso-electron-sdk --plaso_electron_sdk_arch=x64 --plaso_electron_sdk_platform=win32 --global-style --no-save
mac:需要在mac平台上执行install
intel:
npm install @plasosdk/plaso-electron-sdk --plaso_electron_sdk_arch=x64 --plaso_electron_sdk_platform=darwin --global-style --no-save
arm:
npm install @plasosdk/plaso-electron-sdk --plaso_electron_sdk_arch=arm --plaso_electron_sdk_platform=darwin --global-style --no-save
将下载的npm包放到 应用本地的 node_modules目录下,一般是electron应用的 resources/app 目录下
主进程需要require包
require('@plasosdk/plaso-electron-sdk')
// electron 版本>=14.0.0 时:需要在主进程里 初始化、启动 remote
const electronVersion = process.versions['electron'];
if (electronVersion && versionComp(electronVersion, '14.0.0') >= 0) {
const electronStore = require('@electron/remote/main');
electronStore.initialize();
// mainWindow: 主进程打开的渲染进程窗口
electronStore.enable(mainWindow.webContents);
}
(1)调用方法:createLiveClassWindow
(2)入参参考: 2、实时课堂参数说明
(1)调用方法:createPrepareClassWindow
(2)入参参考:3、备课课堂参数说明
1.2.3.3、确定日志的写入位置
// 代码示例
const PlasoElectronSdk = window.require('@plasosdk/plaso-electron-sdk');
const logFilePath = "C:/Users/userName/Desktop/electronDemo/electron12.0.18_x32/resources/app";
PlasoElectronSdk.initLogConfig(logFilePath);
1.2.3.4、创建 课堂/备课 窗口
// 代码示例
const PlasoElectronSdk = window.require('@plasosdk/plaso-electron-sdk');
const classObj = {};
//创建实时课堂
PlasoElectronSdk.createLiveClassWindow(classObj)
// or 创建备课课堂
PlasoElectronSdk.createPrepareClassWindow(classObj)
类型:Object
参数 | 是否必传 | 类型 | 默认值 | 说明 |
---|---|---|---|---|
displayAvatarUrl | 否 | string | 无 | 用户头像地址 |
classMembers | 否 | object[] | 无 | 1、课对应的班级用户信息 2、初始化课堂参与人 3、最多支持2000人,需要支持更多学生需要联系伯索平台进行额外申请 { /** 唯一标识该用户的id / loginName: string, /* 用户显示的姓名 / name: string, /* 用户角色,"speaker","assistant","listener","superlistener" 之一 / upimeRole: string, /* 用户的id,和云学堂业务强相关,sdk用户非必要 / unique_id: number | string /* 用户头像图片的url,非必要 */ displayAvatarUrl: string, } |
enableENC | 否 | boolean | true | 是否启用降噪 |
enableRTC3A | 否 | boolean | true | 是否启用3A。 false:关闭回音消除、关闭降噪、关闭增益控制 |
version | 是 | string | 无 | 正式使用时的线上对应的sdk版本,具体的版本需要在对接时确定,格式参考:1.53.901 对接时一般不在线上环境测试,所以需要在classOptions里传入对应环境的 dhost、rhost,具体格式参考如下 |
query | 是 | string | 无 | 进课堂必传字段,具体拼接逻辑见下文 |
supportShowResourceCenter | 否 | boolean | false | true:显示资料中心,但核心的云盘和获取云盘文件地址的逻辑需要用户自己实现 |
supportSaveBoard | 否 | boolean | false | 是否支持保存板书 |
dhost | 否 | string | 无 | https://${environment}.plaso.cn/ environment可选值:dev、test、itest、ftest |
rhost | 否 | string | 无 | https://${environment}.plaso.cn/static/yxtsdk/ environment可选值:dev、test、itest、ftest |
enableLiveNewShareRegion | 否 | boolean | false | 是否允许区域共享 |
enableLiveNewShareInTouch | 否 | boolean | false | 是否支持触屏模式下的新桌面共享(左侧新增按钮窗口来切换显示工具栏) 建议开启 |
enableLiveNewShare | 否 | boolean | false | 是否支持新桌面共享 开启新桌面共享需要开启electron透明窗口,且可能触发electron本身存在的长时间透传导致的在应用上鼠标失焦问题 |
enableLiveSign | 否 | boolean | false | 是否支持签到 |
residentCamera | 否 | boolean | false | 常驻摄像头:只对学生或游客生效 |
对象的组成参数说明如下表格:
参数 | 类型 | 说明 |
---|---|---|
appId | string | 在申请接入时,伯索平台给予的appId |
validBegin | number | 请求课堂开始生效起始时间的Unix Epoch 时间戳,单位秒:(时间戳/1000再取整) |
validTime | number | 请求的签名在课堂的有效时间段(断网重连后会重新校验签名),单位秒,建议: 24 * 60 * 60 s |
endTime | number | 请求课堂结束时间的Unix Epoch 时间戳,单位秒:(时间戳/1000再取整) |
appType | string | 应用类型,必填,目前为固定值:liveclassSDK |
userType | string | 用户类型,目前有三个值可选: speaker,assistant,listener; speaker:主讲,有控制其他listener是否可写可说话的权限; assistant:助教,也有控制权限 listener:学生 |
meetingType | string | 课堂类型,传入值:private。 当选择private类型时,每一个进入课堂者,必须提供loginName,这是唯一标识该用户的id,相同的loginName登录,后进入者会使前一个强制登出 |
mediaType | string | 媒体类型:audio, video audio: 语音实时课堂 video:有头像权限的课堂,含语音权限 |
meetingId | string | 课堂ID,唯一标识该课堂;使用ASSIIC字符,不得包含/,,空格等;长度在40字节以内的字符串 |
loginName | string | 唯一标识该用户的id,不能为空,相同的loginName登录,后面一个会使前面一个登出; |
d_dimension | string | 1280x720 定义界面尺寸为16:9 界面 |
userName | string | 登录的用户名,在列表中显示用 |
vendorType | number | rtc类型 2:agora |
videoStream | number | 课堂类型,与mediaType需要对应上 2:视频课堂 1:语音课堂 |
enableNewClassExam | number | 新版随堂测选择题:1; 新版随堂测填空题:2; 新版随堂测选择+填空:3,建议:3 |
d_enableReRecording | number | 主讲、助教都可以重新录制课堂:3 |
参数 | 类型 | 默认值 | 建议值 | 说明 |
---|---|---|---|---|
topic | string | 无 | 非空 | 显示该课堂的名称 |
onlineMode | number | 6 | 无 | 上台学生数,默认:6 |
d_enableOMO | number | 0 | 无 | 是否开启站播模式,1:开启;0:关闭 |
d_delayEndTimes | number | 0 | 无 | 单节课最大延迟下课次数:1、2、3、4 |
d_delayEnd | number | 0 | 无 | 单次延时时间,单位秒:560、10 * 60、1560、20 * 60、30*60 |
d_restrictAssistantPerm | number | 0 | 无 | 是否开启了:大班课限制助教权限 1:开启 0:关闭 |
d_enableAvatarFreeScale | number | 0 | 无 | 开启头像任意比例缩放 0:关闭 1:开启,默认关闭 (非录制课堂、非无头像录制模式下,裁剪掉的老师/助教头像也会被录到回放中) |
d_enableObjectEraser | number | 0 | 无 | 新板书配置,二进制位存储 default: 0;默认关闭对象擦 7:手写(对象擦); |
d_vote | number | 0 | 1 | 0:未开放投票;1:开放投票 |
d_sharpness | number | 10 | 无 | 头像推流清晰度、桌面共享清晰度 仅onlineMode === 1 时生效: 10:标清 20:高清 21: 高清流畅 30:超清 31: 超清流畅 |
isNewMT | number | 0 | 1 | 是否支持 移动授课模式; 建议传1 |
d_enableDualCamera | number | 0 | 无 | 是否开启双摄,1:开启,0: 关闭 |
(1)用户把featureObj作为参数传给自己的接口,接口返回值必须返回签名字符串:signature
(2)获取signature后需要把 signature加到 featureObj 中作为一个参数
featureObj.signature = signature;
(3)服务端接口生成 signature 规则如下:
https://open.plaso.cn/doc-6285173?nav=01HEQ5Y5RXKMCPBPF6S8T3VK56
signKey:机构申请接入时,伯索平台给予的key
/*!----------演示签名代码------------- */
// 业务参数,根据接口文档中定义,自行生成填写
const featureObj = {"name":"test"};
//平台分配给机构的key
const signKey = 'a_secret';
// 业务参数和签名验证混合后排序
const afterSortParam = Object.keys(featureObj).sort();
const res = []
for (let key of afterSortParam) {
res.push(`${key}=${featureObj[key]}`);
}
// 排序后连接成字符串
const content = res.join("&");
const crypto = require('crypto');
// 使用分配的signKey来加密生成签名串signature
const signature = crypto.createHmac('sha1', signKey).update(content).digest('hex').toUpperCase();
(1)获取 完整的featureObj后,遍历对象生成query 字符串
每个参数值用 encodeURIComponent 编码
// 代码示例:其中featureObj对象包含signature
function genQuery(featureObj) {
const keys = Object.keys(featureObj).sort();
const res = [];
for (let key of keys) {
res.push(key + "=" + encodeURIComponent(featureObj[key]);
}
return res.join("&");
}
genQuery(featureObj)
query字符串格式示例:
appId=plaso&appType=liveclassSDK&d_dimension=1280x720&dhost=https%3A%2F%2Fdev.plaso.cn%2F&enableHiliter=true&enableNewClassExam=1&enableVideoMark=true&env=dev&loginName=t_1&mediaType=video&meetingId=test_1742442362&meetingType=public&signature=A226198904A392579B98987FB4CD5478AB3F5587&upimeTeacherTool=1151&userName=%E8%80%81%E5%B8%881&userType=speaker&validBegin=1742442364&validTime=99999&vendorType=2&videoStream=2'
// 课堂结束后的回调,回调参数为 课堂的meetingId
(meetingId: string)=>void
类型:Object
参数 | 类型 | 说明 |
---|---|---|
loginName | String | 唯一标识该用户的id,不能为空,相同的loginName登录,后面一个会使前面一个登出; |
username | String | 登录的用户名,在列表中显示用 |
version | String | 正式使用时的线上对应的sdk版本,具体的版本需要在对接时确定,格式参考:1.53.901 对接时一般不在线上环境测试,所以需要在classOptions里传入对应环境的 dhost、rhost,具体格式参考 以下 可选参数中的说明 |
参数 | 类型 | 说明 |
---|---|---|
displayAvatarUrl | String | 用户头像地址 |
topic | String | 默认值是中文的 “备课课堂” |
d_enableObjectEraser | number | 新板书配置,二进制位存储 default: 0;默认关闭对象擦 7:手写(对象擦); 注意:该值需要和实时课堂的传值一样 |
dhost | String | https://${environment}.plaso.cn/ environment可选值:dev、test、itest、ftest |
rhost | String | https://${environment}.plaso.cn/static/yxtsdk/ environment可选值:dev、test、itest、ftest |
注意:
1、备课课堂直接通过任务栏关闭不会清空本地记录的板书内容,下次进入后会 板书交互会和上次进入的板书 配置一致(即使 d_enableObjectEraser 参数 值变动了)
electron 的窗口参数,详情参考 electron官方文档
type electronWinOptions = object;
// 课堂窗口打开渲染成功后的回调,回调参数为 窗口id
type onClassWindowReadyFn = (winId: number)=>void;
// 课堂窗口关闭后的回调,回调参数为 窗口id
type onClassWindowLeaveFn = (winId: number)=>void;
注意:
1、filePath 对应的文件资源,用户保存在自己的云端时,需要把 本次保存的备课文件的 相关资源放在同一特定目录下
2、每次保存生成的备课文件 都放在一个新的目录下,不同的备课文件不能共用一个目录
3、备课保存的资源文件名 不能更改,info.pb 是固定的文件名
// 保存板书方法,具体的保存逻辑由外部实现,取消保存板书时,callback传false, 不然传true
type FileParams = {
/** 备课相关资源文件的本地地址*/
filePath: string[],
/** 备课文件 类型*/
fileType: 'png' | 'pb' | string
}
type onSaveBoardFn = (
params: {
fileInfo: FileParams[],
fileName?: string
},
callback: (result: boolean) => void
) => void;
fileInfo 格式如下:
// 通知外部用户打开自己的资料中心,资料中心的具体ui和逻辑由外部用户自己实现
type onOpenResourceCenterFn = () => void;
// 通过 insertObject 插入的文件传入 参数 info 时,怎么从info中获取文件的可访问地址的逻辑在用户那,所以需要函数从外部用户获取外部用户传入的文件地址
type onGetExtFileNameFn = (info: any[])=>Promise<string>
初始化课堂窗口日志位置,窗口崩溃时会在同级目录下生成reports 文件夹存储dump,在 调用createLiveClassWindow 前设置
日志默认位置:
windows:C:\Users\${userName}\AppData\Roaming\${appName}\P403FileTemp
path.join(remote.app.getPath('userData'), '/P403FileTemp/')
参数示例:
// 代码示例
const PlasoElectronSdk = window.require('@plasosdk/plaso-electron-sdk');
const logFilePath = "C:/Users/userName/Desktop/electronDemo/electron12.0.18_x32/resources/app";
PlasoElectronSdk.initLogConfig(logFilePath);
返回包的版本,格式:x.x.x
type getVersion = ()=>string;
创建实时课堂窗口,入参参考 见 “2、实时课堂入参说明”
/**
* @typedef {Object} classOptionsType
* @property {boolean} [debug] - 是否开启课堂窗口debug模式
* @property {string} query - 进课堂的必备query
* @property {string} [version] - 格式参考:1.53.901
*/
/**
* @typedef {Object} FileParams
* @property {string[]} filePath - 备课文件本地地址
* @property {'png' | 'pb' | string} fileType
*/
/**
* @typedef {Object} classWindowType
* @property {classOptionsType} classOptions 进课堂参数对象
* @property {Object} [electronWinOptions] 自定义electron的窗口参数
* @property {(winId: number)=>void} [onClassWindowReadyFn] 课堂窗口打开渲染成功后的回调
* @property {(winId: number)=>void} [onClassWindowLeaveFn] 课堂窗口关闭后的回调
* @property {(meetingId: string)=>void} [onClassFinishedFn] 课堂结束后的回调
* @property {(
* params: {
* fileInfo: FileParams[],
* fileName?: string
* },
* callback: (result: boolean) => void
* ) => void} [onSaveBoardFn] 保存板书,具体的保存逻辑由外部实现,取消保存板书时,callback传false, 不然传true
* @property {()=>void} [onOpenResourceCenterFn] 通知外部用户打开自己的资料中心,资料中心的具体ui和逻辑由外部用户自己实现
*
*/
/**
* @param {classWindowType} classWindowProps
* @returns
*/
function createClassWindow(classWindowProps) {/**
* @typedef {Object} classOptionsType
* @property {boolean} [debug] - 是否开启课堂窗口debug模式
* @property {string} query - 进课堂的必备query,其中部分参数需要签名
*/
/**
* @typedef {Object} liveClassWindowType
* @property {classOptionsType} classOptions 进课堂参数对象
* @property {Object} [electronWinOptions] 自定义electron的窗口参数
* @property {(winId: number)=>void} [onClassWindowReadyCb] 课堂窗口打开渲染成功后的回调
* @property {()=>void} [onClassWindowLeaveCb] 课堂窗口关闭后的回调
* @property {()=>void} [onClassFinishedCb] 课堂结束后的回调
*/
/**
* @param {liveClassWindowType} liveClassWindowProps
* @returns
*/
function createLiveClassWindow({
classOptions,
electronWinOptions,
onClassWindowReadyCb,
onClassWindowLeaveCb,
onClassFinishedCb,
}){
......
}
创建备课课堂窗口,入参参考 见 “3、备课课堂入参说明”
参数详情 参考 createLiveClassWindow方法的说明
用户从自己的云盘 往 实时课堂/备课课堂 插入文件
/** 插入的文件类型 */
const FILE_TYPE = {
IMAGE: 2,
PDF: 3,
WORD: 4,
EXCEL: 5,
AUDIO: 6,
VIDEO: 7,
DOC: 14,
XLS: 15,
// ppt
NPPT:17,
// 备课文件
PREPARE_LESSONS: 22,
};
/** 插入外部云盘里的文件,文件需要遵循特定的数据结构 */
/**
* @typedef {Object} fileDataObj
* @property {number} type 插入文件的格式,内容参考 FILE_TYPE
* @property {any[]} [info] 具体的文件信息数组,除备课外,内容都由用户自己定义
* @property {string} [title] 文件名称,需要带后缀
* @property {string} [url] 文件的可下载地址
*/
/**
* @param {string | number} winId 课堂id
* @param {fileDataObj} fileData 文件数据
*/
type insertObject = (webContentId, fileData) => void;
1、 插入 备课文件 的格式如下,其中 fileLocationPath为 插入的备课文件资源的地址前缀,比如要本地插入一个备课文件(info.pb),其完整地址为C:\Users\xxx\AppData\Roaming\plaso_sdk\prepareLessonsTemp\draft.swap\info.pb,则此时fileLocationPath = C:\Users\xxx\AppData\Roaming\plaso_sdk\prepareLessonsTemp\draft.swap
// 备课的fileData格式
const fileData = {
type: 22,
info: ['pb', , , fileLocationPath]
}
注意:
1、保存备课文件时,需要把 info.pb 和其他的图片文件放在同一个目录下,这样才可以通过一个 目录地址获取 备课的所有资源
1、title 需要带有文件后缀名
// 图片的fileData格式,不需要info属性
const fileData = {
type: 2,
title: 'xxxxxx.xxx',
url: 'xxxxxx',
}
// ppt的fileData格式,不需要info属性
const fileData = {
type: 17,
title: 'xxxxxx',
url: 'xxxxxx',
}
1、可以设置url属性为 公开可访问的音视频文件全路径,
2、或者设置info属性为表示文件信息的数组,可以通过 进课堂时传入的 getExtFileName 方法 可以获取文件有效路径
// audio、video 的fileData格式
const fileData = {
type: 6 或 7,
title: 'xxxxxx',
url: 'xxxxxx',
}
或
const fileData = {
type: 6 或 7,
title: 'xxxxxx',
info: [xxxxxx],
}
1、可以设置 url属性 为公开可访问的 pdf、word、execl 文件全路径,
2、或者设置 info属性 为表示文件信息的数组,可以通过 进课堂时传入的 getExtFileName 方法 可以获取文件有效路径
// pdf、word、execl 的fileData格式,不需要info属性
const fileData = {
type: 3 或 4 或 5 或 14 或 15,
title: 'xxxxxx',
url: 'xxxxxx',
}
或
const fileData = {
type: 3 或 4 或 5 或 14 或 15,
title: 'xxxxxx',
info: [xxxxxx],
}
step1、进课堂时,对象 classOptions.supportShowResourceCenter 需要是 true
step2、在课堂内点击资料中心后,会触发进课堂时传入的回调函数 onOpenResourceCenterFn,此时用户在 onOpenResourceCenterFn函数内打开自己的云盘
step3、选择号文件后,通过 PlasoElectronSdk.insertObject 方法插入文件,方法入参参考 insertObject说明
step4、insertObject 方法 入参 有info 时,此时 会触发进课堂时传入的回调函数 onGetExtFileNameFn 来获取文件的线上地址
1、参考文档: 历史课堂接入方式
2、课堂里插入需要 调用 回调 onGetExtFileNameFn 方法的文件时,对应的历史课堂 则需要自己包装一层,具体逻辑参考 :播放历史课堂-jssdk集成
(1)用户的课堂外主窗口销毁时需要销毁课堂窗口
(2)electron 版本>=14.0.0 时:需要在主进程里 启动 remote
try {
const electronStore = require('@electron/remote/main');
electronStore.initialize();
// mainWindow 预期的渲染进程窗口
electronStore.enable(mainWindow.webContents);
} catch (error) {
console.error('Module not found', 'Please run `npm install @electron/remote` to enable remote module and update electron version to 22.0.0 or higher');
}
(3)基于 此包封装新包时:注意 @electron/remote 这个包的位置需要 和新包处于同级目录,需要把 和该包同级的@electron/remote移到新包的同级目录处
(4)确保 仅最后的node_moudles 的顶层有 @electron/remote