HIGHLIGHT_API.md 12.4 KB

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 时:

  1. 按 Asia/Shanghai 计算前一天 00:00:00.000 至 23:59:59.999。
  2. 遍历 HIGHLIGHTCONFIG.siteIds。
  3. 查询并提交所有有效高光。

响应:

{
  "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 查询结果