RECORDING_API.md 5.9 KB

WebScreen V2 录制接口

1. 范围

原接口保持原实现不变:

POST /recordingTask
POST /fileExists

新增:

POST /recordingTaskV2
POST /recordingTaskV2/scheduled
POST /fileExistsV2

V2 兼容原整课录制格式,并通过 SaaS 字段 onlyHighlight=1 支持仅录高光。不支持也不需要“整课和高光同时录制”。不录制站点已经由 xdySDK 上游流程筛除。

onlyHighlight 行为
不传或 0 复用原整课录制实现
1 仅录制该课堂的高光时刻

2. cron 统一入口

正式定时任务只调用 WebScreen 内部入口,不负责查询或转换 SaaS 数据:

POST /recordingTaskV2/scheduled

请求体为空。WebScreen 会自行完成:

  1. 分页调用 SaaS /3m/api/recording/getRecordingTasksPrivate.do。
  2. 生成接口要求的 timestamp 和 authId。
  3. 根据 onlyHighlight 将任务交给现有 V2 整课或高光流程。
  4. 使用本地任务快照防止 cron 重复投递。

该入口只允许从 WebScreen 所在服务器的回环地址调用,不作为公网接口开放。

配置:

"RECORDINGV2CONFIG": {
  "taskListUrl": "https://saas.xuedianyun.com/3m/api/recording/getRecordingTasksPrivate.do",
  "pageSize": 100,
  "maxPages": 1000,
  "maxTasksPerRun": 4,
  "maxFullConcurrent": 2,
  "apiTimeoutMs": 10000,
  "apiRetryCount": 2,
  "apiRetryBaseDelayMs": 500
}

maxTasksPerRun 限制一次 cron 最多新接收多少个任务;重复任务不占用该额度。 maxFullConcurrent 限制同时运行的整课录制进程数。高光录制仍由 HIGHLIGHTCONFIG.maxConcurrent 单独限制。

cron 示例:

31 7-20 * * * curl -fsS -X POST http://127.0.0.1:3001/recordingTaskV2/scheduled >> /var/log/webscreen_recording_v2.log 2>&1

成功响应:

{
  "code": "0",
  "message": "success",
  "data": {
    "received": 12,
    "taskCount": 12,
    "pages": 1,
    "inspected": 5,
    "accepted": 4,
    "duplicates": 1,
    "noMedia": 0,
    "invalid": 0,
    "limited": true
  }
}

3. 创建 V2 录制任务

POST /recordingTaskV2
Content-Type: application/json

3.1 兼容原整课请求

{
  "list": [
    {
      "siteId": "doctest",
      "classId": "487012832",
      "yymmdd": "20260805"
    }
  ],
  "maxMedia": 1
}

未传 onlyHighlight 时,V2 调用现有整课录制代码,文件仍为 {classId}.mp4。

3.2 仅高光请求

V2 可直接接受 SaaS getRecordingTasksPrivate.do 返回项的字段形式:

{
  "list": [
    {
      "id": "ff808081956a495901956a498d0f0001",
      "siteId": "doctest",
      "meetingNumber": "487012832",
      "beginTime": "2026-08-05 10:00:00",
      "endTime": "2026-08-05 11:00:00",
      "status": 0,
      "onlyHighlight": 1
    }
  ]
}

字段兼容关系:

V2 字段 兼容字段 说明
classId meetingNumber 课堂号,二者任选其一
taskId id 可选;SaaS 任务 ID,用于辅助追踪和幂等
yymmdd classStartTime 原整课目录日期,格式 yyyyMMdd
beginTime/endTime — 可选;用于精确限定课堂高光时间范围,接受 13 位毫秒时间戳或 SaaS 时间格式
onlyHighlight — 只有值 1 表示仅高光,其他值按整课兼容

如果现有 cron 已经把 SaaS 任务映射为 classId/siteId/yymmdd,只需在原映射中 增加 onlyHighlight。高光状态回写使用 siteId + classId,不依赖 SaaS 任务 id。

仅高光流程:

  1. 调用 /3m/api/highlight/getByClassPrivate.do 获取课堂高光。
  2. 只保留站点、课堂一致且位于课堂时间范围内的数据。
  3. 每条高光生成一个 MP4。
  4. 全部高光本地录制完成后向 SaaS 回写 status=2;返回 code=0 即表示更新成功。
  5. SaaS 正常返回空高光数组时回写 status=3;接口失败不能当作无高光。

getBySitePrivate.do 不属于单课堂任务主流程,只用于批量排查或补录。

3.3 响应

{
  "code": "0",
  "message": "success",
  "accepted": 1,
  "duplicates": 0,
  "noMedia": 0,
  "v": "v1.2.0.20251208"
}
字段 说明
accepted 本次接收的整课或高光任务数
duplicates 已处理或正在执行的重复任务数
noMedia onlyHighlight=1 但 SaaS 正常返回零条高光的任务数

4. 查询 V2 录制文件

POST /fileExistsV2
Content-Type: application/json

请求:

{
  "siteId": "doctest",
  "classId": "487012832"
}

也兼容原整课查询日期:

{
  "siteId": "doctest",
  "classId": "487012832",
  "classStartTime": "20260805"
}

V2 根据 onlyHighlight 判断文件类型:0 或不传查询整课文件,1 通过 SaaS getByClassPrivate.do 获取高光列表并检查对应文件。本地任务快照不作为高光文件查询的前置条件。

整课成功响应:

{
  "code": 0,
  "message": "文件已生成",
  "fileExists": true,
  "onlyHighlight": 0,
  "classUrl": "https://xdymp4.xuedianyun.com/oss/doctest/20260805/487012832.mp4",
  "files": [
    {
      "type": "full",
      "url": "https://xdymp4.xuedianyun.com/oss/doctest/20260805/487012832.mp4"
    }
  ]
}

高光成功响应:

{
  "code": 0,
  "message": "文件已生成",
  "fileExists": true,
  "onlyHighlight": 1,
  "files": [
    {
      "type": "highlight",
      "highlightId": 5,
      "url": "https://xdymp4.xuedianyun.com/oss/doctest/20260805/487012832_highlight_5.mp4"
    }
  ]
}

任一目标文件尚未生成时:

{
  "code": 1,
  "message": "文件未生成",
  "fileExists": false,
  "files": []
}

查询接口只检查明确的 OSS Key,不触发录制,也不重新调用 SaaS 高光接口。

5. 文件规则

整课:oss/{siteId}/{yyyyMMdd}/{classId}.mp4
高光:oss/{siteId}/{yyyyMMdd}/{classId}_highlight_{highlightId}.mp4

高光日期按每条高光 beginTime 的 Asia/Shanghai 日期计算。