本文為您介紹遠程監考考生端、監考端的代碼示例及集成說明。
項目構成
本次開源代碼包含兩個前端倉庫:
監考端:exam-invigilator
考生端:exam-examinee
前提條件
已接入、運行、部署開源的Appserver服務。具體操作,請參見服務端集成示例源碼。
已創建OSS Bucket,并配置好直播推拉流域名。如未配置,請參見控制臺創建存儲空間、快速開始視頻直播完成Bucket與推拉流域名配置。
項目框架
本項目使用UmiJS框架開發,技術棧為React+TypeScript。詳細說明請參見UmiJS 官方文檔。
項目運行
開源項目地址
項目地址:阿里云考場場景方案。
準備環境
安裝Node環境,詳細信息請參見UmiJS 快速上手教程。
配置AppServer的地址
修改src/config.ts里的 appServer
配置項,將其填寫為您的服務端域名和路徑前綴,更多配置項請參考下文擴展配置項章節。
// 配置 APPServer
appServer: {
origin: "", // 配置 APPServer 服務域名,例子: https://xxx.xxx.xxx,結尾請勿包含 /
apiPrefixPath: "/exam/", // 配置api接口路徑前綴
},
創建考場生成體驗鏈接
遠程監控Web開源項目不包含考試管理、考場管理、用戶管理等業務功能,需要您根據開源的AppServer 自行實現。本地開發時,監考端、考生端正常運行需要通過URL傳入roomId(考場ID)、userId(用戶ID)、token(身份檢驗字符串)。因此,你首先需要通過服務端createRoom 接口(詳情見服務端接口文檔)創建一個考場,創建成功后返回的ID即為考場ID、createTeacher為監考員ID;而 userId、token 是需要您自行實現,開源工程中并不會校驗token,隨意傳入字符串即可,userId設定為examinee1 、examinee2至 examinee5。
若創建考場接口返回的數據如下所示:
{
"success":true,
"data":{
"id":"12345",
"createdAt":"2023-10-20T14:34:40+08:00",
"updatedAt":"2023-10-20T14:34:40+08:00",
"name":"test exam",
"examId":"12345",
"status":0,
"audioStatus":0,
"imGroupId":"12345",
"createTeacher":"teacher1"
}
}
則本地體驗URL為:
// 若考生端本地服務端口為 8001,則體驗地址為
http://localhost:8001?roomId=12345&userId=examinee1&token=xxxx
// 若監考端本地服務端口為 8002,則體驗地址為
http://localhost:8002?roomId=12345&userId=teacher1&token=xxxx&role=0
考場鏈接生成腳本
我們還開源了創建考場的腳本,腳本為監考端工程內的script/genroom.mjs
文件。在運行項目前需要先生成考場的URL,具體操作步驟如下。
打開監考端工程內的
script/genroom.mjs
文件,并將您的AppServer
域名賦值給apiOrigin
變量,根據具體監考端和考生端項目的運行端口號修改對應的變量。// 請輸入您的服務端的域名,結尾請勿是 / const apiOrigin = ''; // 監考端域名,請根據您的實際情況更改,特別是本地運行時,要注意監考端的端口是否一致 const invigilatorBasePath = 'http://localhost:8000'; // 考生端域名,請根據您的實際情況更改,特別是本地運行時,要注意考生端的端口是否一致 const examineeBasePath = 'http://localhost:8001';
執行如下命令,運行genroom.mjs腳本生成本地體驗URL,
npm install axios --save node script/genroom.mjs
得到的體驗格式如下。
監考端體驗地址 -> http://localhost:8000?roomId=***&userId=teacher&token=xxx&role=0 考生端副機位體驗地址 -> http://localhost:8001?roomId=***&userId=examinee1&token=xxxx 考生端主機位體驗地址 -> http://localhost:8001?roomId=***&userId=examinee1&token=xxxx#/pc
其中8000端口對應的是監考端項目的運行端口,8001端口對應的是考生端項目的運行端口,開發者可以根據自己項目的運行端口號進行調整。
推流/播放地址規則說明
在遠程監考的集成過程中,考生畫面的推流/播放地址、老師音頻的推流/播放地址均需要您按照一定的規則進行生成,本節為您介紹遠程監考的推流/播放地址生成規則。
了解阿里云推流和播放地址格式。詳細說明,請參見生成推流地址和播放地址、鑒權代碼示例。
基于阿里云的客戶服務經驗,推薦您使用如下格式。
考生畫面的推流地址:artc://webrtcpush.example.com/appname/examid-roomid-userid?token=*********
appname:通常是一個固定值,如您的應用名稱或公司名稱等。您需要設置的appname需要與上文配置的錄制模板、轉碼模板指定的appname一致,此時錄制和轉碼才會生效。
examid:建議設置為本場考試編號。
roomid:某場考試中,具體某個考場的編號。
userid:具體參與考試的用戶編號。
考生畫面的播放地址(原始畫面):artc://webrtcpull.example.com/appname/examid-roomid-userid?token=*********。
考生畫面的播放地址(轉碼后的畫面): artc://webrtcpull.example.com/appname/examid-roomid-userid_templateName?token=*********。
templateName為上文您設置的轉碼模板的名稱。
老師音頻的推流地址:artc://webrtcpush.example.com/appname/examid-roomid-userid?token=*********。
老師音頻的播放地址:artc://webrtcpull.example.com/appname/examid-roomid-userid?token=*********。
運行項目
按照以下步驟進行操作:
參考考場鏈接生成腳本,生成體驗考場及對應監考端和考生端頁面的體驗URL。
先在監考端工程中運行如下指令,然后在考生端工程中運行如下指令。
// 安裝 npm 包 npm install // 安裝完成后,執行 dev 指令,運行成功后根據提示使用瀏覽器訪問即可 npm run dev
運行成功,界面如下。
復制第一步生成的URL到瀏覽器中打開即可開始體驗。
構建配置
// 運行build指令即可構建最終產物至./dist目錄下
npm run build
構建的文件主要包括index.html、umi.js和umi.css,其余的是按需加載的資源文件。您可以將生成的./dist目錄下的所有文件上傳至您的服務器或CDN服務中,也可以使用您的內部部署系統進行部署。
您需要根據您的實際情況,配置位于根目錄下的 .umirc.ts文件中的publicPath參數。
若您最終訪問的頁面是單獨加載生成的js、css資源,則無需配置publicPath。
若需直接使用index.html,請參考以下示例,并根據您的實際情況進行配置。
import fs from 'fs';
import path from 'path';
const packagejson = fs.readFileSync(path.resolve('./package.json'));
const json = JSON.parse(packagejson.toString());
export default {
// 省略其他配置參數
// 生成的 index.html 里使用的umi.js 、umi.css地址的公共路徑的默認值是 /
// 若 index.html 部署的地址是 http://g.alicdn.com/publicPath/exam/0.0.1/index.html
// 若不配置 publicPath 直接訪問測試、線上環境 index.html,所加載的umi.js將會是 http://g.alicdn.com/umi.js
// 顯然不是跟index.html目錄下了,所以請根據您實際情況配置為真實路徑 或者使用相對路徑 ./
// 例子中使用了項目的name 、version在部署目錄中,請根據您實際情況配置
publicPath:
process.env.NODE_ENV === 'production'
? `/publicPath/${json.name}/${json.version}/`
: './',
}
擴展配置項
在遠程監考系統中,考生端和監考端的功能配置項均存儲在對應項目中的src/config.ts
文件中,您可以根據實際業務需求進行配置,具體說明如下:
考生端
const config: IConfig = {
aliyunUid: "",
// pagePath當前用于本地開發調試時設置PC考生頁上的副機位二維碼的 url
pagePath: "",
// 配置 APPServer
appServer: {
origin: "", // 配置 APPServer 服務域名,例子: https://xxx.xxx.xxx
apiPrefixPath: "/exam/", // 配置api接口路徑前綴
},
// 配置日志服務
reporter: {
enable: false, // 是否開啟埋點
host: "", // 所在地域的服務入口
projectName: "", // sls 的工程名稱
logstore: "", // sls 的 logstore
},
// 配置本地錄制
localRecorder: {
enable: false, // 是否開啟本地錄制
// 模式支持 OSS 或 VOD
mode: "OSS",
// OSS 模式時有用,注意:開頭、結束字符必須要是 /
// 若遇到 403 問題,檢查服務端獲取 STS 接口的 policy 里的倉庫路徑與 basePath 是否匹配
basePath: "/record/local/",
// VOD 模式時有用
vod: {
region: "cn-shanghai",
// 創建的額外參數,詳情請看 http://bestwisewords.com/zh/vod/developer-reference/api-vod-2017-03-21-createuploadvideo#api-detail-35
// 注意 Title、StorageLocation 這里設置無效,若有特殊要求,請至 VODUploader 文件中修改
params: {
Tags: "AUIExam",
},
},
},
// 防作弊服務配置項
cheatDetect: {
licenseKey: "", // 防作弊 SDK 的 license
licenseDomain: "", // 防作弊 SDK 允許運行的域名(localhost不受限制)
},
// 移動端攝像頭切換模塊的配置項
mobileCameraSwitcher: {
enable: false, // 是否展示該模塊
},
// 默認攝像頭流參數
defaultVideoProfile: {
name: "custom_360_800k", // 名稱,可根據實際情況修改
data: {
// 低配低版本安卓手機,若高于 360P 可能取到的畫面是黑屏
// 正式考試時建議請勿配置高于 360P(640*360/360*640)
width: 640, // 視頻寬度
height: 360, // 視頻高度
frameRate: 30, // 幀率
maxBitrate: 800, // 最大碼率
},
},
};
appServer
配置您部署的服務端appServer的域名和API前綴路徑。
pagePath
當前頁面的域名+路徑,主要應用于主機位頁面(src->pages->pc)本地開發調試時,設置進入考生移動端二維碼的URL,當域名為localhost或127.0.0.1時,將自動替換為此配置值,其他情況則使用當前的origin+pathname。
aliyunUid
開通直播、點播、OSS等服務的阿里云userId(主賬號的userid),當使用VOD上傳時,該字段為必填項。
reporter
SLS日志的配置項。若要使用埋點統計功能,則需要將enable設為true,同時填寫projectName、host和logstore。有關projectName和logstore的獲取方法,請參見快速入門。
使用SLS日志,將會產生相應費用。計費說明請參見按量付費。
localRecorder
考生端還可以通過localRecorder設置是否開啟本地錄制功能。該功能在推流失敗時(例如網絡異常),會將本地音視頻內容錄制并存儲在瀏覽器中,然后在有網絡條件時上傳至您配置的OSS Bucket。
支持OSS和VOD兩種存儲模式,請根據實際情況選擇。兩種模式的上傳均使用STS臨時授權方案。對于VOD模式,請參閱使用STS臨時授權方案上傳視頻;對于OSS模式,請參閱使用STS臨時訪問憑證訪問OSS 文檔。
cheatDetect
在工程中,我們支持使用防作弊SDK來輔助遠程監考。請查看遠程監考智能防作弊SDK以了解其功能及購買License,并配置相應的licenseKey、licenseDomain等參數。
mobileCameraSwitcher
考生在移動端默認使用前置攝像頭,如果您將enable參數設置為true,那么考生界面將支持切換前后攝像頭。
defaultVideoProfile
您可以在此配置項中設置默認攝像頭流的分辨率、碼率和幀率。
監考端
const config: IConfig = {
aliyunUid: "",
// 配置 APPServer
appServer: {
origin: "", // 配置 APPServer 服務域名,例子: https://xxx.xxx.xxx,結尾請勿包含 /
apiPrefixPath: "/exam/", // 配置api接口路徑前綴
},
// 配置日志服務
reporter: {
enable: false, // 是否開啟埋點
host: "", // 所在地域的服務入口
projectName: "", // sls 的工程名稱
logstore: "", // sls 的 logstore
},
// 防作弊檢測消息相關功能
detectList: {
enable: true,
},
// 多機位配置項
mutilMonitor: {
enable: true, // 是否需要多機位,若不開啟,則僅展示 mobile 副機位的流
preferMainMonitor: true, // 是否優先展示 pc 主機位的流
},
};
appServer
配置您部署的服務端appServer的域名和API前綴路徑。
aliyunUid
開通直播、點播、OSS等服務的阿里云userId,注意是主賬號的userid。
reporter
SLS日志的配置項。若要使用埋點統計功能,則需要將enable設為true,并填寫projectName、host和logstore。有關projectName和logstore的獲取方法,請參見快速入門。
使用SLS日志,將會產生相應費用。計費說明,請參見按使用功能計費。
detectList
如果考生端開啟了防作弊檢測,您可以在監考端啟用此參數,啟用后將在左側顯示疑似作弊消息列表模塊。
mutilMonitor
監考端默認展示考生副機位(移動端)的畫面。如果您需要支持切換至考生畫面,并默認顯示主機位(PC)畫面,您可以使用enable和preferMainMonitor參數。
技術細節
本節為您介紹項目中的一些技術細節,方便您對源碼進行修改,進行更具定制化的開發擴展。
主副機位
考生端目前支持同時打開主副機位兩個頁面,默認哈希路由 #/ 時為副機位,#/pc 時為主機位。
主機位
主機位頁面是為考生正面監考,運行在 PC 設備上,包含環境設備檢測頁(路由:#/pc/deviceTest),以及 PC 監考頁(路由:#/pc)。建議默認打開檢測頁(URL示例:localhost:8001?roomId=12345&userId=examinee1&token=xxxx#/pc/deviceTest),檢測通過后將自測跳轉 PC 監考頁。
設備檢測
如截圖所示,正式進入考場時會對攝像頭、麥克風、揚聲器、屏幕共享這四項設備進行檢測,通過后跳轉 PC 監考頁。
PC監考頁
PC監考頁左邊側邊欄將展示當前 PC 攝像頭的畫面,底下為移動端副機位的二維碼,當副機位監考頁也進入推流后將加載移動端的畫面。
考題區域需要由您根據您的實際情況進行開發。
副機位
副機位也稱為側機位,運行于移動端瀏覽器或 webview 中,考生掃主機位上的二維碼即可進入(注意:本地開發時要配置 pagePath,或者直接在 PC 上打開本地的副機位頁面)。
監考端
監考端支持切換查看考生的主副機位畫面,當使用口播、連麥等功能時將于當前查看的機位進行通信。
重要類說明
工程中的src->core文件夾下的文件為核心邏輯,您可重點閱讀以下類的源碼。
core/Interaction.ts
對阿里云互動消息SDK做二次封裝,使更好地適配考試業務。詳細說明,請參見互動消息SDK文檔。
core/RadioTimer.ts
用于定時系統廣播。
core/rts-publisher.ts
推流組件src->components->rts->Publish中所用的核心推流邏輯,詳細說明,請參見aliyun-rts-sdk文檔。
core/rts-subscriber.ts
拉流組件src->components->rts->Subscribe中所用的核心拉流邏輯,詳細說明,請參見aliyun-rts-sdk文檔。
core/AudioPlayer.ts
用于iOS系統播放音頻,解決部分iOS環境播放音頻的異常。
utils/Reporter.ts
用于埋點統計。
utils/LocalMock.ts
用于本地開發初期提供mock數據,可以在頁面URL上增加mock=1參數(例如:http://localhost:8000/?mock=1),那么就會使用到本地的mock數據。大部分數據都可以靜態mock,有鑒權的推拉流地址需要替換。
getIMToken方法中的accessToken字段需要設置為互動消息服務取到的Token,可參考互動消息建立長連接文檔生成。