ps-exam-monitor
v1.0.2
Published
高级屏幕监测系统 - 支持多显示器检测、屏幕共享监控、录制和分段上传
Maintainers
Readme
高级屏幕监测 SDK (Exam Monitor)
专为在线考试场景设计的防作弊屏幕监控解决方案。支持由浅入深的监控策略,提供多显示器检测、强制全屏共享、实时录制与截图、断流监听等核心能力。
✨ 核心特性
- 🖥 多显示器检测:利用现代浏览器 API (
getScreenDetails) 精确检测用户设备上的显示器数量。 - 🚫 防作弊策略:
- 强制单屏:检测到多显示器接入时,可自动阻止考试开始或中断监测。
- 强制整屏共享:通过
displaySurface校验,确保用户共享的是整个屏幕而不是某个窗口或标签页。
- 🎥 自动化录制:
- 智能分片:自动将录像切分为指定时长的片段,便于分段上传,降低丢失风险。
- 后台截图:即便页面处于后台或最小化,也能稳定截取屏幕快照。
- 🛡 状态监听:实时监听屏幕插拔、录制意外停止(用户点击"停止共享")等关键事件。
- 📦 离屏渲染优化:内部使用离屏 Canvas 和 Video 元素,大幅降低长时间运行的内存与 CPU 占用。
- 📝 TypeScript 支持:完全使用 TypeScript 编写,提供完整的类型定义。
📦 安装
# 使用 npm
npm install ps-exam-monitor
# 使用 pnpm
pnpm add ps-exam-monitor
# 使用 yarn
yarn add ps-exam-monitor🚀 快速开始
import { AdvancedScreenMonitor } from "ps-exam-monitor";
// 1. 初始化监测器
const monitor = new AdvancedScreenMonitor({
allowMultipleScreens: false, // 禁止连接多个显示器
requireMonitor: true, // 强制要求共享整个屏幕
onStreamEnded: (reason) => {
console.warn("监测意外中断:", reason);
alert("请不要停止屏幕共享!");
},
onSnapshot: (blob, timestamp) => {
// 处理截图 (例如上传到OSS)
uploadSnapshot(blob);
},
});
// 2. 启动监测
try {
const success = await monitor.start();
if (success) {
console.log("监测已启动,正在录制...");
// 获取实时流用于预览 (可选)
const stream = monitor.getStream();
if (stream) {
videoElement.srcObject = stream;
}
} else {
alert("启动失败:请确保只连接了一个显示器,并选择‘整个屏幕’进行共享。");
}
} catch (error) {
console.error("启动异常:", error);
}
// 3. 停止监测 (例如考试交卷时)
// monitor.stop();📖 API 文档
配置选项 (AdvancedScreenMonitorConfig)
| 选项 | 类型 | 默认值 | 说明 |
| :--------------------- | :-------- | :------- | :------------------------------------------------------------------------------------------- |
| allowMultipleScreens | boolean | false | 是否允许用户在连接多个显示器的情况下开始考试。 |
| maxScreens | number | 1 | 允许的最大显示器数量(仅当 allowMultipleScreens 为 true 时生效)。 |
| requireMonitor | boolean | true | 是否强制要求用户在共享时选择 "整个屏幕"。如果用户选择了 "窗口" 或 "标签页",监测将无法启动。 |
| recordVideo | boolean | true | 是否启用视频录制功能。 |
| videoQuality | number | 5 | 视频录制质量 (1-10),数值越高码率越高。 |
| enableSnapshot | boolean | true | 是否启用自动截图功能。 |
| snapshotInterval | number | 15000 | 截图间隔时间(毫秒),默认 15 秒。 |
| uploadInterval | number | 300000 | 视频分片上传间隔(毫秒),默认 5 分钟。 |
回调事件
| 事件方法 | 参数 | 说明 |
| :----------------- | :------------------------------------------------------------------- | :----------------------------------------------------- |
| onSnapshot | (blob: Blob, timestamp: number) | 每次截图完成时触发,返回 JPEG 格式的 Blob。 |
| onVideoChunk | (blob: Blob, startTime: number, endTime: number) | 视频片段录制完成时触发,返回 WebM/MP4 格式的 Blob。 |
| onStreamEnded | (reason: string) | 当监测因为各种原因(用户停止、设备拔出等)中断时触发。 |
| onScreensChanged | (screens: ScreenDetailInfo[], type: 'added'\|'removed'\|'changed') | 当检测到显示器插拔或配置变化时触发。 |
| onError | (error: Error) | 内部发生错误时触发。 |
实例方法
start(): Promise<boolean>启动监测流程。会依次执行环境检测、请求权限、开始录制。返回true表示启动成功。stop(): void停止监测。会停止流、清理定时器、并触发最后一次onVideoChunk回调以保存剩余录像。getStream(): MediaStream | null获取当前的媒体流对象。可用于在页面上展示实时预览(Live Preview)。getScreenInfo(): ScreenInfo获取当前的屏幕配置信息,包括屏幕数量、分辨率等。isActive(): boolean检查当前监测器是否处于活跃运行状态。
🌐 浏览器兼容性
本 SDK 依赖现代 Web API,推荐使用 Chrome 100+ 或 Edge 100+ 以获得完整体验。
| 功能 | Chrome / Edge | Firefox | Safari | 说明 |
| :--------------- | :------------ | :-------- | :-------- | :-------------------------------------------- |
| 基础录制 | ✅ 支持 | ✅ 支持 | ✅ 支持 | 基于 navigator.mediaDevices.getDisplayMedia |
| 强制全屏检测 | ✅ 支持 | ⚠️ 部分 | ❌ 不支持 | 依赖 displaySurface约束与属性 |
| 多屏高级检测 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 | 依赖 window.getScreenDetails (实验性 API) |
注意:在不支持
getScreenDetails的浏览器中,SDK 会自动降级,跳过物理显示器数量的硬件检测,但仍会通过分辨率启发式算法尝试检测是否为全屏共享。
🛠 开发与构建
# 安装依赖
pnpm install
# 启动本地开发 Demo
pnpm dev
# 构建生产版本 (输出到 lib/)
pnpm build📄 许可证
ISC License
