Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
张艾宸
/
webScreen
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
huz1xuan
2026-08-07 13:50:26 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
f86915aa88d02d1a30545c07f68fa4d47942b9c3
f86915aa
1 parent
7afd9cc9
feat: 拆分高光录制接口与整堂录制
隐藏空白字符变更
内嵌
并排对比
正在显示
9 个修改的文件
包含
619 行增加
和
45 行删除
HIGHLIGHT_API.md
HIGHLIGHT_DEPLOYMENT.md
HIGHLIGHT_DEPLOYMENT_USAGE_TEST.md
HIGHLIGHT_MP4_SPEC.md
README.md
routes/highlightRecording.js
routes/index.js
services/highlightRecordingService.js
test/highlightRoutes.test.js
HIGHLIGHT_API.md
0 → 100644
查看文件 @
f86915a
# WebScreen 高光录制接口文档
## 1. 文档范围
本文汇总 WebScreen 对外提供的全部高光接口,以及 WebScreen 依赖的 SaaS 内部接口。
高光录制与整堂录制是两套独立业务:
-
原整堂录制接口保持不变。
-
所有高光接口统一使用
`/highlight`
前缀。
-
`HIGHLIGHTCONFIG.enabled` 只控制高光查询、录制和文件检查,不影响原整堂录制;`GET /highlight/status`
始终可用于健康检查。
-
高光文件使用
`{classId}_highlight_{highlightId}.mp4`,不会覆盖整堂录像 `{classId}.mp4`
。
示例服务地址:
```
text
http://127.0.0.1:3001
```
除
`GET /highlight/status`
外,请求均使用:
```
http
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 内部异常 |
错误示例:
```
json
{
"code"
:
10
,
"message"
:
"高光录制功能未启用"
}
```
## 4. 预览课堂高光
```
http
POST /highlight/preview/by-class
```
该接口查询 SaaS 高光数据并计算录制地址、文件名和当前文件状态,但不会加入录制队列。
请求:
```
json
{
"classId"
:
"2008975651"
}
```
成功响应:
```
json
{
"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. 预览站点高光
```
http
POST /highlight/preview/by-site
```
请求字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
|
`siteId`
| String | 是 | 机构编码 |
|
`beginTime`
| Integer | 否 | 查询开始时间,13 位毫秒时间戳 |
|
`endTime`
| Integer | 否 | 查询结束时间,13 位毫秒时间戳 |
|
`pageSize`
| Integer | 否 | 调用 SaaS 时的分页大小,范围 1~1000 |
请求:
```
json
{
"siteId"
:
"xdyui2"
,
"beginTime"
:
1785859200000
,
"endTime"
:
1785945599999
,
"pageSize"
:
100
}
```
WebScreen 会自动读取全部分页。响应项与
`/highlight/preview/by-class`
相同。
## 6. 按课堂提交高光录制
```
http
POST /highlight/recording/by-class
```
请求:
```
json
{
"classId"
:
"2008975651"
}
```
成功响应:
```
json
{
"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. 按站点提交高光录制
```
http
POST /highlight/recording/by-site
```
请求字段与
`/highlight/preview/by-site`
相同。
请求:
```
json
{
"siteId"
:
"xdyui2"
,
"beginTime"
:
1785859200000
,
"endTime"
:
1785945599999
}
```
成功响应:
```
json
{
"code"
:
0
,
"message"
:
"success"
,
"data"
:
{
"received"
:
3
,
"queued"
:
2
,
"recording"
:
1
,
"uploading"
:
0
,
"generated"
:
0
,
"invalid"
:
0
,
"failed"
:
0
}
}
```
这里的状态数量是本次提交结果的快照,不是全局队列统计。
## 8. 运行高光定时任务
```
http
POST /highlight/recording/scheduled
```
无请求体。该接口与原整堂录制
`GET /recording`
完全独立。
当
`sourceMode=site`
时:
1.
按 Asia/Shanghai 计算前一天
`00:00:00.000` 至 `23:59:59.999`
。
2.
遍历
`HIGHLIGHTCONFIG.siteIds`
。
3.
查询并提交所有有效高光。
响应:
```
json
{
"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 录制任务:
```
text
status = 0
onlyHighlight = 1
siteId 位于 HIGHLIGHTCONFIG.siteIds
```
响应额外包含:
```
json
{
"mode"
:
"task"
,
"sourceTasks"
:
10
,
"pendingTasks"
:
2
}
```
任务模式目前尚未实现向 SaaS 回写完成状态,不建议在正式环境启用。
建议的独立 cron:
```
cron
57 7 * * * curl -fsS -X POST http://127.0.0.1:3001/highlight/recording/scheduled >/dev/null 2>&1
```
原整堂录制 cron 保持原样,两者不要使用同一个接口。
## 9. 查询课堂全部高光文件
```
http
POST /highlight/fileExists
```
请求:
```
json
{
"siteId"
:
"xdyui2"
,
"classId"
:
"2008975651"
}
```
全部生成时:
```
json
{
"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"
}
]
}
```
只要存在未生成项,就返回:
```
json
{
"code"
:
1
,
"message"
:
"部分文件未生成"
,
"onlyHighlight"
:
1
,
"classUrlList"
:
[]
}
```
实际
`classUrlList` 仍包含所有已生成和未生成项目;上例省略了项目明细。课堂没有高光时返回 `code=1`、`message=文件未生成`
。
## 10. 按明细批量查询高光文件
```
http
POST /highlight/files
```
适合调用方已经持有高光 ID 和开始时间、不希望 WebScreen 再按课堂查询 SaaS 的场景。一次最多 1000 条。
请求:
```
json
{
"items"
:
[
{
"highlightId"
:
5
,
"classId"
:
"2008975651"
,
"siteId"
:
"xdyui2"
,
"beginTime"
:
1785895298000
}
]
}
```
响应:
```
json
{
"code"
:
0
,
"message"
:
"success"
,
"data"
:
[
{
"highlightId"
:
5
,
"classId"
:
"2008975651"
,
"siteId"
:
"xdyui2"
,
"beginTime"
:
1785895298000
,
"generated"
:
false
,
"status"
:
"recording"
,
"url"
:
null
}
]
}
```
## 11. 查询高光队列状态
```
http
GET /highlight/status
```
响应:
```
json
{
"code"
:
0
,
"message"
:
"success"
,
"data"
:
{
"queued"
:
2
,
"recording"
:
1
,
"knownTasks"
:
5
}
}
```
| 字段 | 说明 |
|---|---|
|
`queued`
| 当前等待录制的任务数 |
|
`recording`
| 当前正在录制的任务数 |
|
`knownTasks`
| 当前进程内保留的全部已知任务数 |
队列状态只保存在当前 Node.js 进程内,PM2 重启后会清空;本地文件和 OSS 文件不会丢失。
## 12. 配置
配置文件:
`config/config.json`
。
```
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 文件查询还需要环境变量:
```
text
ALIBABA_CLOUD_ACCESS_KEY_ID
ALIBABA_CLOUD_ACCESS_KEY_SECRET
```
## 13. 文件规则
```
text
文件名:{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 高光记录示例:
```
json
{
"id"
:
5
,
"meetingNumber"
:
"2008975651"
,
"siteId"
:
"xdyui2"
,
"beginTime"
:
1785895298000
,
"endTime"
:
1785895343000
,
"type"
:
0
,
"more"
:
""
}
```
字段映射:
```
text
id → highlightId
meetingNumber → classId
```
更详细的 SaaS 请求签名和响应说明见
`getByClassPrivate.md` 与 `getBySitePrivate.md`
。
## 15. 调用顺序建议
单课堂人工验证:
```
text
POST /highlight/preview/by-class
→ POST /highlight/recording/by-class
→ GET /highlight/status
→ POST /highlight/fileExists
```
每日自动录制:
```
text
cron
→ POST /highlight/recording/scheduled
→ 查询前一天高光
→ 加入高光队列
→ 生成本地 MP4 和 download.json
→ 服务器搬运到 OSS
→ POST /highlight/fileExists 查询结果
```
...
...
HIGHLIGHT_DEPLOYMENT.md
查看文件 @
f86915a
...
...
@@ -123,10 +123,10 @@ curl -X POST http://127.0.0.1:3001/highlight/fileExists \
## 8. 验证 cron 全量模式
先手工执行
原
cron 入口:
先手工执行
独立的高光
cron 入口:
```
bash
wget -qO- http://127.0.0.1:3001/recording
curl -fsS -X POST http://127.0.0.1:3001/highlight/recording/scheduled
```
响应
`data.mode` 应为 `site`
,时间窗应为 Asia/Shanghai 前一天。
...
...
@@ -134,7 +134,7 @@ wget -qO- http://127.0.0.1:3001/recording
确认无误后配置:
```
cron
57 7 * * *
wget -qO- http://127.0.0.1:3001/recording
>/dev/null 2>&1
57 7 * * *
curl -fsS -X POST http://127.0.0.1:3001/highlight/recording/scheduled
>/dev/null 2>&1
```
## 9. 切换任务模式
...
...
@@ -188,7 +188,7 @@ https://xdymp4.xuedianyun.com/oss/xdyui2/{yyyyMMdd}/{classId}_highlight_{highlig
pm2 restart webScreen
```
关闭后,
`GET /recording`
继续运行原整课录制逻辑。高光使用独立文件名,不覆盖旧整课
MP4。
关闭后,
高光查询、录制和文件检查接口停止处理,状态接口仍可访问;
`GET /recording`
始终运行原整堂录制逻辑。高光使用独立文件名,不覆盖旧整堂
MP4。
## 12. 上线 CrazyTalk 前检查
...
...
HIGHLIGHT_DEPLOYMENT_USAGE_TEST.md
查看文件 @
f86915a
...
...
@@ -334,7 +334,7 @@ N 条高光时,`classUrlList` 必须有 N 条记录。
手工调用 cron 入口:
```
bash
wget -qO- http://127.0.0.1:3001/recording
curl -fsS -X POST http://127.0.0.1:3001/highlight/recording/scheduled
```
检查:
...
...
@@ -365,7 +365,7 @@ pm2 restart webScreen
4.
其他站点
`status=0, onlyHighlight=1`
:不录制。
```
bash
wget -qO- http://127.0.0.1:3001/recording
curl -fsS -X POST http://127.0.0.1:3001/highlight/recording/scheduled
```
检查:
...
...
@@ -381,7 +381,7 @@ wget -qO- http://127.0.0.1:3001/recording
只有单课堂、重复录制、OSS 搬运和全量模式全部通过后才启用:
```
cron
57 7 * * *
wget -qO- http://127.0.0.1:3001/recording
>/dev/null 2>&1
57 7 * * *
curl -fsS -X POST http://127.0.0.1:3001/highlight/recording/scheduled
>/dev/null 2>&1
```
```
bash
...
...
@@ -465,7 +465,7 @@ echo "$DISPLAY"
pm2 restart webScreen
```
关闭后,
`GET /recording` 恢复原整课
逻辑。`POST /recording`、`POST /recordingTask`、`POST /fileExists`
和实时录制接口不变。
关闭后,
高光查询、录制和文件检查接口停止处理,状态接口仍可访问;
`GET /recording` 始终执行原整堂录制
逻辑。`POST /recording`、`POST /recordingTask`、`POST /fileExists`
和实时录制接口不变。
## 21. 测试记录模板
...
...
HIGHLIGHT_MP4_SPEC.md
查看文件 @
f86915a
...
...
@@ -10,12 +10,12 @@ WebScreen 根据 SaaS 高光记录,把每个 `beginTime/endTime` 时间段录
-
一个高光时间段生成一个 MP4;N 条高光生成 N 个文件。
-
当前只在
`xdyui2`
测试,验证后再增加 CrazyTalk。
-
WebScreen 只生成本地文件;服务器已有任务定时移动到 OSS。
-
原定时任务每天
`07:57` 调用 `GET /recording`
。
-
高光定时任务使用独立的
`POST /highlight/recording/scheduled`
,不占用整堂录制入口
。
-
任务模式暂时只处理
`status=0`
;后端状态回写规则待确认。
## 2. 兼容原则
高光开关缺失或关闭时,
`GET /recording`
完整执行原整课录制逻辑
。
原
`GET /recording`
始终执行整堂录制逻辑,不读取高光开关
。
```
json
{
...
...
@@ -25,10 +25,11 @@ WebScreen 根据 SaaS 高光记录,把每个 `beginTime/endTime` 时间段录
}
```
只有显式配置
`enabled: true`
才
进入高光录制。因此旧服务器、旧站点和旧客户不受影响
。
只有显式配置
`enabled: true` 才
能调用 `/highlight/*`
高光业务接口。关闭高光不会关闭或改变整堂录制
。
以下接口保持原行为:
-
`GET /recording`
-
`POST /recording`
-
`POST /recordingTask`
-
`POST /fileExists`
...
...
@@ -38,19 +39,13 @@ WebScreen 根据 SaaS 高光记录,把每个 `beginTime/endTime` 时间段录
## 3. 定时触发
WebScreen 本身不创建 cron。
服务器已有
cron:
WebScreen 本身不创建 cron。
高光需要独立
cron:
```
cron
57 7 * * *
wget http://127.0.0.1:3001/recording &
57 7 * * *
curl -fsS -X POST http://127.0.0.1:3001/highlight/recording/scheduled >/dev/null 2>&1
```
建议部署时改成不落 wget 临时文件的等价写法:
```
cron
57 7 * * * wget -qO- http://127.0.0.1:3001/recording >/dev/null 2>&1
```
`GET /recording` 读取 `HIGHLIGHTCONFIG.sourceMode`
:
`POST /highlight/recording/scheduled` 读取 `HIGHLIGHTCONFIG.sourceMode`
:
-
`site`
:全量高光模式。
-
`task`
:指定课堂任务模式。
...
...
@@ -97,7 +92,7 @@ WebScreen 本身不创建 cron。服务器已有 cron:
流程:
1.
cron 调用
`
GET /recording
`
。
1.
cron 调用
`
POST /highlight/recording/scheduled
`
。
2.
按 Asia/Shanghai 计算前一天
`00:00:00.000` 至 `23:59:59.999`
。
3.
遍历
`HIGHLIGHTCONFIG.siteIds`
。
4.
分页调用
`getBySitePrivate.do`
。
...
...
@@ -288,7 +283,7 @@ WebScreen 调用 `getByClassPrivate.do` 获取该课堂全部高光,再逐条
5.
`sourceMode=task` 只处理 `status=0 && onlyHighlight=1`
。
6.
`/highlight/fileExists`
返回课堂全部高光文件状态和地址。
7.
原
`/fileExists`
响应不变。
8.
删除或关闭
`HIGHLIGHTCONFIG` 后,
`GET /recording`
恢复原整课
录制。
8.
删除或关闭
`HIGHLIGHTCONFIG` 后,
高光接口拒绝处理,原 `GET /recording`
仍执行整堂
录制。
## 13. 已知待办
...
...
README.md
查看文件 @
f86915a
node调用录制文件
2025-0306 新的dev分支
\ No newline at end of file
2025-0306 新的dev分支
高光录制接口见
[
HIGHLIGHT_API.md
](
./HIGHLIGHT_API.md
)
。
...
...
routes/highlightRecording.js
查看文件 @
f86915a
...
...
@@ -72,6 +72,20 @@ router.post('/recording/by-site', async function (req, res) {
}
});
// 独立的高光定时入口,不占用原整堂录制 GET /recording。
router
.
post
(
'/recording/scheduled'
,
async
function
(
req
,
res
)
{
try
{
const
data
=
await
service
.
runScheduledRecording
();
return
res
.
send
({
code
:
0
,
message
:
data
.
received
?
'success'
:
'无高光数据'
,
data
});
}
catch
(
error
)
{
return
sendError
(
res
,
error
);
}
});
router
.
post
(
'/fileExists'
,
async
function
(
req
,
res
)
{
try
{
const
data
=
await
service
.
getClassFileStatuses
(
req
.
body
||
{});
...
...
routes/index.js
查看文件 @
f86915a
...
...
@@ -8,11 +8,6 @@ require('dotenv').config(); // 加载环境变量
const
method
=
require
(
"../config/method"
)
const
config
=
require
(
"../config/config"
)
const
{
highlightRecordingService
,
HighlightValidationError
,
HighlightUpstreamError
}
=
require
(
'../services/highlightRecordingService'
);
const
version
=
'v1.2.0.20251208'
;
// const { GETCLASSURL, GETCLASSURLPARAMETER, PROJECTCATALOG, PROJECTWINCATALOG, BACKMEDIACONFIG } = config
const
{
YesterdayTime
,
getDayTime
,
getRequestClassIds
,
dayTimeYMD
}
=
method
...
...
@@ -219,23 +214,6 @@ router.get('/recording', async function (req, res, next) {
if
(
!
fileConfig
)
return
false
const
parsedConfig
=
JSON
.
parse
(
fileConfig
)
if
(
parsedConfig
.
HIGHLIGHTCONFIG
&&
parsedConfig
.
HIGHLIGHTCONFIG
.
enabled
===
true
)
{
try
{
const
data
=
await
highlightRecordingService
.
runScheduledRecording
()
res
.
send
({
code
:
"0"
,
message
:
data
.
received
?
"success"
:
"无高光数据"
,
data
})
}
catch
(
error
)
{
new
MediaCreat
().
wrieLog
(
"高光录制任务读取失败:------>"
+
(
error
.
message
||
error
))
if
(
error
instanceof
HighlightValidationError
)
{
res
.
status
(
400
).
send
({
code
:
"1"
,
message
:
error
.
message
})
}
else
if
(
error
instanceof
HighlightUpstreamError
)
{
res
.
status
(
502
).
send
({
code
:
String
(
error
.
upstreamCode
),
message
:
error
.
message
})
}
else
{
res
.
status
(
500
).
send
({
code
:
"-1"
,
message
:
"高光录制任务读取失败"
})
}
}
return
}
const
{
GETCLASSURLPARAMETER
}
=
parsedConfig
siteIds
=
GETCLASSURLPARAMETER
.
siteId
if
(
siteIds
.
length
==
0
)
{
...
...
services/highlightRecordingService.js
查看文件 @
f86915a
...
...
@@ -821,6 +821,7 @@ class HighlightRecordingService {
}
async
getFileStatuses
(
items
)
{
this
.
ensureFeatureEnabled
();
this
.
cleanupTasks
();
const
config
=
this
.
readConfig
();
const
allowedSiteIds
=
new
Set
(
this
.
getAllowedSiteIds
());
...
...
test/highlightRoutes.test.js
查看文件 @
f86915a
...
...
@@ -42,6 +42,13 @@ async function run() {
assert
.
strictEqual
(
invalidFiles
.
status
,
400
);
assert
.
strictEqual
(
invalidFiles
.
body
.
code
,
10
);
const
disabledFiles
=
await
request
(
server
,
'POST'
,
'/highlight/files'
,
{
items
:
[{
highlightId
:
5
,
classId
:
'1001'
,
siteId
:
'xdyui2'
,
beginTime
:
1785895298000
}]
});
assert
.
strictEqual
(
disabledFiles
.
status
,
400
);
assert
.
strictEqual
(
disabledFiles
.
body
.
code
,
10
);
assert
.
strictEqual
(
disabledFiles
.
body
.
message
,
'高光录制功能未启用'
);
const
invalidPreview
=
await
request
(
server
,
'POST'
,
'/highlight/preview/by-class'
,
{});
assert
.
strictEqual
(
invalidPreview
.
status
,
400
);
assert
.
strictEqual
(
invalidPreview
.
body
.
code
,
10
);
...
...
@@ -50,6 +57,51 @@ async function run() {
assert
.
strictEqual
(
invalidClassFiles
.
status
,
400
);
assert
.
strictEqual
(
invalidClassFiles
.
body
.
code
,
10
);
const
disabledScheduled
=
await
request
(
server
,
'POST'
,
'/highlight/recording/scheduled'
);
assert
.
strictEqual
(
disabledScheduled
.
status
,
400
);
assert
.
strictEqual
(
disabledScheduled
.
body
.
code
,
10
);
assert
.
strictEqual
(
disabledScheduled
.
body
.
message
,
'高光录制功能未启用'
);
const
originalRunScheduledRecording
=
highlightRecordingService
.
runScheduledRecording
;
try
{
highlightRecordingService
.
runScheduledRecording
=
async
()
=>
({
mode
:
'site'
,
beginTime
:
1785945600000
,
endTime
:
1786031999999
,
received
:
2
,
queued
:
2
,
recording
:
0
,
uploading
:
0
,
generated
:
0
,
invalid
:
0
,
failed
:
0
});
const
scheduled
=
await
request
(
server
,
'POST'
,
'/highlight/recording/scheduled'
);
assert
.
strictEqual
(
scheduled
.
status
,
200
);
assert
.
strictEqual
(
scheduled
.
body
.
code
,
0
);
assert
.
strictEqual
(
scheduled
.
body
.
message
,
'success'
);
assert
.
strictEqual
(
scheduled
.
body
.
data
.
mode
,
'site'
);
assert
.
strictEqual
(
scheduled
.
body
.
data
.
received
,
2
);
highlightRecordingService
.
runScheduledRecording
=
async
()
=>
({
mode
:
'site'
,
beginTime
:
1785945600000
,
endTime
:
1786031999999
,
received
:
0
,
queued
:
0
,
recording
:
0
,
uploading
:
0
,
generated
:
0
,
invalid
:
0
,
failed
:
0
});
const
scheduledEmpty
=
await
request
(
server
,
'POST'
,
'/highlight/recording/scheduled'
);
assert
.
strictEqual
(
scheduledEmpty
.
body
.
code
,
0
);
assert
.
strictEqual
(
scheduledEmpty
.
body
.
message
,
'无高光数据'
);
}
finally
{
highlightRecordingService
.
runScheduledRecording
=
originalRunScheduledRecording
;
}
const
originalGetClassFileStatuses
=
highlightRecordingService
.
getClassFileStatuses
;
highlightRecordingService
.
getClassFileStatuses
=
async
()
=>
[
{
highlightId
:
4
,
classId
:
'1001'
,
siteId
:
'xdyui2'
,
generated
:
true
,
status
:
'generated'
,
url
:
'https://example/4.mp4'
},
...
...
请
注册
或
登录
后发表评论