【寻声征文】如何用Electron SDK实现在线考试场景

# 我正在参加「寻声 2.0」征文活动, https://www.rtcdeveloper.cn/cn/community/discussion/57/25892

背景目标

随着AI技术、Web技术和远程视频会议技术的发展,传统的考试场景也有出现了AI智能导题、AI快速出卷、线上学生答题、AI标准化成绩分析等发展方向,从根本上杜绝了泄题漏题的问题。但是,考试作为一个严肃而认真的场合,监考过程还是需要老师人为参与,以保证考试的严肃与公正。那么,老师监考这个场景就需要运用到RTC技术。

设计思路

计划设计考试场景是1名监考老师,对应多名学生的场景,模拟实际的教室考场监考的场景。

  • 监考老师:推单路音频流,用于广播通知考试要求,并且可以及时与学生沟通交流;拉多名学生的视频流,用于监督学生行为。为了降低老师的电脑性能和网络带宽要求,平时拉流只拉小分辨率的视频;在1v1交流时,动态更新学生的视频尺寸。
  • 考试学生:推单路音视频流,用于被监考。按老师要求,可以推屏幕共享的视频,同时,老师的声音可以传递到学生端,用于1v1 RTC通讯。

老师端

初始化SDK,代码如下:

import { createAgoraRtcEngine } from 'agora-electron-sdk';
const engine = createAgoraRtcEngine();
engine.initialize({
    appId,
    logConfig: { filePath: Config.SDKLogPath },
    channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting,
});

单路音频推流,老师上传1路声音,代码如下:

engine.enableAudio();
engine.joinChannel(token, channelId, uid, {
    clientRoleType: ClientRoleType.ClientRoleBroadcaster,
});

多路视频拉流,老师同时拉多名学生的画面,入会后选择小尺寸画面,为了改善多路播放的性能问题:

engine.joinChannel(token, channelId, uid, {
    clientRoleType: ClientRoleType.ClientRoleBroadcaster,
});

// onUserJoined 回调入会成功后
engine.setRemoteDefaultVideoStreamType(VideoStreamLow);
engine.setupRemoteVideo(canvas);

单路1v1交流时,老师单独看单个学生画面,画面尺寸变大:

engine.setRemoteVideoStreamType(uid, VideoStreamHigh);

学生端

单路音视频推流,入会上传音视频,代码如下:

engine.joinChannel(token, channelId, uid, {
    clientRoleType: ClientRoleType.ClientRoleBroadcaster,
});
engine.enableAudio();
engine.enableVideo();

// 开启视频预览
engine.startPreview();

音频拉流,订阅老师的音频流,不订阅其他学生的音视频,代码如下:

engine.joinChannel(token, channelId, uid, {
    clientRoleType: ClientRoleType.ClientRoleBroadcaster,
});

// 取消订阅其他学生的音视频
engine.muteRemoteAudioStream(uid, true);
engine.muteRemoteVideoStream(uid, true);

屏幕共享,代码如下:

// 配置
const sources = engine.getScreenCaptureSources(
      { width: 1920, height: 1080 },
      { width: 64, height: 64 },
      true
);

// 采集
this.engine?.startScreenCaptureByDisplayId(
        sources.at(0).sourceId,
        {},
        {
          dimensions: { width, height },
          frameRate,
          bitrate,
          captureMouseCursor,
          excludeWindowList,
          excludeWindowCount: excludeWindowList.length,
          highLightWidth,
          highLightColor,
          enableHighLight,
        }
);

// 共享,用uid2和token2实现
engine.joinChannelEx(
      token2,
      { channelId, localUid: uid2 },
      {
        autoSubscribeAudio: false,
        autoSubscribeVideo: false,
        publishMicrophoneTrack: false,
        publishCameraTrack: false,
        clientRoleType: ClientRoleType.ClientRoleBroadcaster,
        publishScreenTrack: true,
      }
);

验证分析

本地通过模拟实现多路预览,观察CPU、内存和网络可以扛得住,基本符合预期。

看SDK内部通过Buffer.alloc提前分配了yuv内存,减少了yuv的拷贝,优化了性能消耗。

最终效果如下

后续开发

增加巡查老师的角色,用于巡查多个考场。

增加学生AI行为分析能力,协助老师及时发现有作弊嫌疑的学生。

增加学生端录制的场景,用于回放归档。

增加转推rtmp直播的能力,便于社会与公众监督。

增加IM接入的能力,便于文字通知和学生留言。





推荐阅读
相关专栏
前端与跨平台
90 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。