WebScreen 高光录制接口文档
1. 文档范围
本文汇总 WebScreen 对外提供的全部高光接口,以及 WebScreen 依赖的 SaaS 内部接口。
高光录制与整堂录制是两套独立业务:
- 原整堂录制接口保持不变。
- 所有高光接口统一使用
/highlight前缀。 -
HIGHLIGHTCONFIG.enabled只控制高光查询、录制和文件检查,不影响原整堂录制;GET /highlight/status始终可用于健康检查。 - 高光文件使用
{classId}_highlight_{highlightId}.mp4,不会覆盖整堂录像{classId}.mp4。
示例服务地址:
http://127.0.0.1:3001
除 GET /highlight/status 外,请求均使用:
Content-Type: application/json
当前 WebScreen 接口没有应用层鉴权,只应开放给可信内网或经过访问控制的调用方。
2. 接口总览
| 方法 | 路径 | 用途 | 是否启动录制 |
|---|---|---|---|
| POST | /highlight/preview/by-class |
预览指定课堂的全部高光及目标文件信息 | 否 |
| POST | /highlight/preview/by-site |
预览指定站点、时间范围内的全部高光 | 否 |
| POST | /highlight/recording/by-class |
提交指定课堂的全部高光录制 | 是 |
| POST | /highlight/recording/by-site |
提交指定站点、时间范围内的全部高光录制 | 是 |
| POST | /highlight/recording/scheduled |
运行一次独立的高光定时任务 | 是 |
| POST | /highlight/fileExists |
查询指定课堂的全部高光文件状态 | 否 |
| POST | /highlight/files |
根据高光明细批量查询文件状态 | 否 |
| GET | /highlight/status |
查询当前进程内的高光队列状态 | 否 |
3. 公共约定
3.1 高光字段
| 字段 | 类型 | 说明 |
|---|---|---|
highlightId |
Integer | 高光唯一 ID,对应 SaaS 高光记录的 id
|
classId |
String | 课堂号,对应 SaaS 高光记录的 meetingNumber
|
siteId |
String | 机构编码,必须位于 HIGHLIGHTCONFIG.siteIds
|
beginTime |
Integer | 高光开始时间,13 位毫秒时间戳 |
endTime |
Integer | 高光结束时间,13 位毫秒时间戳 |
classId、siteId 只允许字母、数字、下划线和短横线,最长 128 个字符。
3.2 任务状态
| 状态 | 说明 |
|---|---|
not_generated |
本地、OSS 和当前任务队列均未发现文件 |
queued |
已进入等待队列 |
recording |
web_capture_c 正在录制 |
uploading |
本地文件已生成,等待服务器搬运到 OSS |
generated |
OSS 文件已经存在,可以返回播放地址 |
invalid |
高光字段、站点或时间段校验失败 |
failed |
录制任务执行失败 |
3.3 HTTP 状态和错误响应
| HTTP 状态 | code |
说明 |
|---|---|---|
| 200 | 0 或 1 | 请求正常完成;文件查询接口使用 1 表示尚未全部生成 |
| 400 | 10 | 请求参数错误、站点未启用或高光功能未启用 |
| 502 | SaaS 返回码或 -1 | SaaS 高光接口、录制任务接口或 OSS 查询失败 |
| 500 | -1 | WebScreen 内部异常 |
错误示例:
{
"code": 10,
"message": "高光录制功能未启用"
}
4. 预览课堂高光
POST /highlight/preview/by-class
该接口查询 SaaS 高光数据并计算录制地址、文件名和当前文件状态,但不会加入录制队列。
请求:
{
"classId": "2008975651"
}
成功响应:
{
"code": 0,
"message": "success",
"data": [
{
"highlightId": 5,
"classId": "2008975651",
"siteId": "xdyui2",
"beginTime": 1785895298000,
"endTime": 1785895343000,
"duration": 45000,
"status": "not_generated",
"fileName": "2008975651_highlight_5.mp4",
"localPath": "/root/web_capture_release/media/xdyui2/20260805/2008975651_highlight_5.mp4",
"ossKey": "oss/xdyui2/20260805/2008975651_highlight_5.mp4",
"url": null,
"playbackUrl": "https://pclive.xuedianyun.com/...&recBeginTime=1785895298000&recEndTime=1785895343000"
}
]
}
没有高光时返回 code=0、message=无高光数据、data=[]。
5. 预览站点高光
POST /highlight/preview/by-site
请求字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
siteId |
String | 是 | 机构编码 |
beginTime |
Integer | 否 | 查询开始时间,13 位毫秒时间戳 |
endTime |
Integer | 否 | 查询结束时间,13 位毫秒时间戳 |
pageSize |
Integer | 否 | 调用 SaaS 时的分页大小,范围 1~1000 |
请求:
{
"siteId": "xdyui2",
"beginTime": 1785859200000,
"endTime": 1785945599999,
"pageSize": 100
}
WebScreen 会自动读取全部分页。响应项与 /highlight/preview/by-class 相同。
6. 按课堂提交高光录制
POST /highlight/recording/by-class
请求:
{
"classId": "2008975651"
}
成功响应:
{
"code": 0,
"message": "success",
"data": [
{
"highlightId": 5,
"classId": "2008975651",
"siteId": "xdyui2",
"beginTime": 1785895298000,
"endTime": 1785895343000,
"status": "queued"
}
]
}
接口返回表示任务已经接收,不表示 MP4 已经生成。调用方应继续查询 /highlight/fileExists 或 /highlight/status。
重复提交同一 siteId + highlightId 时,WebScreen 会检查内存任务、本地文件和 OSS,不会重复录制已经存在的高光。
7. 按站点提交高光录制
POST /highlight/recording/by-site
请求字段与 /highlight/preview/by-site 相同。
请求:
{
"siteId": "xdyui2",
"beginTime": 1785859200000,
"endTime": 1785945599999
}
成功响应:
{
"code": 0,
"message": "success",
"data": {
"received": 3,
"queued": 2,
"recording": 1,
"uploading": 0,
"generated": 0,
"invalid": 0,
"failed": 0
}
}
这里的状态数量是本次提交结果的快照,不是全局队列统计。
8. 运行高光定时任务
POST /highlight/recording/scheduled
无请求体。该接口与原整堂录制 GET /recording 完全独立。
当 sourceMode=site 时:
- 按 Asia/Shanghai 计算前一天
00:00:00.000至23:59:59.999。 - 遍历
HIGHLIGHTCONFIG.siteIds。 - 查询并提交所有有效高光。
响应:
{
"code": 0,
"message": "success",
"data": {
"mode": "site",
"beginTime": 1785859200000,
"endTime": 1785945599999,
"received": 3,
"queued": 3,
"recording": 0,
"uploading": 0,
"generated": 0,
"invalid": 0,
"failed": 0
}
}
当 sourceMode=task 时,只处理同时满足以下条件的 SaaS 录制任务:
status = 0
onlyHighlight = 1
siteId 位于 HIGHLIGHTCONFIG.siteIds
响应额外包含:
{
"mode": "task",
"sourceTasks": 10,
"pendingTasks": 2
}
任务模式目前尚未实现向 SaaS 回写完成状态,不建议在正式环境启用。
建议的独立 cron:
57 7 * * * curl -fsS -X POST http://127.0.0.1:3001/highlight/recording/scheduled >/dev/null 2>&1
原整堂录制 cron 保持原样,两者不要使用同一个接口。
9. 查询课堂全部高光文件
POST /highlight/fileExists
请求:
{
"siteId": "xdyui2",
"classId": "2008975651"
}
全部生成时:
{
"code": 0,
"message": "文件已生成",
"onlyHighlight": 1,
"classUrlList": [
{
"highlightId": 5,
"classId": "2008975651",
"siteId": "xdyui2",
"beginTime": 1785895298000,
"generated": true,
"status": "generated",
"url": "https://xdymp4.xuedianyun.com/oss/xdyui2/20260805/2008975651_highlight_5.mp4"
}
]
}
只要存在未生成项,就返回:
{
"code": 1,
"message": "部分文件未生成",
"onlyHighlight": 1,
"classUrlList": []
}
实际 classUrlList 仍包含所有已生成和未生成项目;上例省略了项目明细。课堂没有高光时返回 code=1、message=文件未生成。
10. 按明细批量查询高光文件
POST /highlight/files
适合调用方已经持有高光 ID 和开始时间、不希望 WebScreen 再按课堂查询 SaaS 的场景。一次最多 1000 条。
请求:
{
"items": [
{
"highlightId": 5,
"classId": "2008975651",
"siteId": "xdyui2",
"beginTime": 1785895298000
}
]
}
响应:
{
"code": 0,
"message": "success",
"data": [
{
"highlightId": 5,
"classId": "2008975651",
"siteId": "xdyui2",
"beginTime": 1785895298000,
"generated": false,
"status": "recording",
"url": null
}
]
}
11. 查询高光队列状态
GET /highlight/status
响应:
{
"code": 0,
"message": "success",
"data": {
"queued": 2,
"recording": 1,
"knownTasks": 5
}
}
| 字段 | 说明 |
|---|---|
queued |
当前等待录制的任务数 |
recording |
当前正在录制的任务数 |
knownTasks |
当前进程内保留的全部已知任务数 |
队列状态只保存在当前 Node.js 进程内,PM2 重启后会清空;本地文件和 OSS 文件不会丢失。
12. 配置
配置文件:config/config.json。
"HIGHLIGHTCONFIG": {
"enabled": true,
"sourceMode": "site",
"siteIds": ["xdyui2"],
"apiBaseUrl": "https://saas.xuedianyun.com",
"pageSize": 100,
"taskPageSize": 100,
"maxPages": 1000,
"maxConcurrent": 2,
"maxDurationMs": 21600000,
"apiTimeoutMs": 10000,
"apiRetryCount": 2,
"apiRetryBaseDelayMs": 500,
"loadGraceMs": 60000,
"endGraceMs": 10000,
"taskRetentionMs": 86400000,
"outputNamespace": "",
"outputBaseUrl": "https://xdymp4.xuedianyun.com"
}
| 字段 | 说明 |
|---|---|
enabled |
高光业务开关;不影响整堂录制,关闭后状态接口仍可访问 |
sourceMode |
定时入口的数据源:site 或 task
|
siteIds |
允许处理的机构编码列表 |
pageSize |
SaaS 高光站点查询分页大小 |
taskPageSize |
SaaS 录制任务查询分页大小 |
maxPages |
自动分页安全上限 |
maxConcurrent |
高光录制最大并发数 |
maxDurationMs |
单条高光允许的最大时长 |
apiTimeoutMs |
SaaS 接口超时时间 |
apiRetryCount |
SaaS 接口失败重试次数 |
loadGraceMs |
回放页面加载预留时间 |
endGraceMs |
录制结束预留时间 |
taskRetentionMs |
完成任务在内存中的保留时间 |
outputNamespace |
可选输出隔离目录;正式环境通常留空 |
outputBaseUrl |
OSS 对外访问地址 |
OSS 文件查询还需要环境变量:
ALIBABA_CLOUD_ACCESS_KEY_ID
ALIBABA_CLOUD_ACCESS_KEY_SECRET
13. 文件规则
文件名:{classId}_highlight_{highlightId}.mp4
本地: {PROJECTCATALOG}/media/{siteId}/{yyyyMMdd}/{fileName}
OSS: oss/{siteId}/{yyyyMMdd}/{fileName}
URL: {outputBaseUrl}/oss/{siteId}/{yyyyMMdd}/{fileName}
yyyyMMdd 按 beginTime 对应的 Asia/Shanghai 日期计算。
录制先写入 {PROJECTCATALOG}/.highlight_tmp,完成后再移动到正式 media 目录。WebScreen 不主动上传 OSS,由服务器已有搬运程序处理,并使用 download.json 作为目录完成标记。
14. WebScreen 依赖的 SaaS 内部接口
以下接口由 WebScreen 内部调用,不应由普通前端直接调用。
| 方法 | 路径 | 用途 |
|---|---|---|
| POST | /3m/api/highlight/getByClassPrivate.do |
根据课堂号获取全部高光 |
| POST | /3m/api/highlight/getBySitePrivate.do |
根据站点和时间范围分页获取高光 |
| POST | /3m/api/recording/getRecordingTasksPrivate.do |
sourceMode=task 时获取录制任务 |
SaaS 高光记录示例:
{
"id": 5,
"meetingNumber": "2008975651",
"siteId": "xdyui2",
"beginTime": 1785895298000,
"endTime": 1785895343000,
"type": 0,
"more": ""
}
字段映射:
id → highlightId
meetingNumber → classId
更详细的 SaaS 请求签名和响应说明见 getByClassPrivate.md 与 getBySitePrivate.md。
15. 调用顺序建议
单课堂人工验证:
POST /highlight/preview/by-class
→ POST /highlight/recording/by-class
→ GET /highlight/status
→ POST /highlight/fileExists
每日自动录制:
cron
→ POST /highlight/recording/scheduled
→ 查询前一天高光
→ 加入高光队列
→ 生成本地 MP4 和 download.json
→ 服务器搬运到 OSS
→ POST /highlight/fileExists 查询结果