huz1xuan

docs: 补充高光录制部署与测试手册

# WebScreen 高光录制部署、使用与测试手册
## 1. 范围
本文用于同事在新 Linux 服务器部署 WebScreen,并只对 `xdyui2` 验证高光 MP4 录制。
当前规则:
- 一个高光时间段生成一个 MP4。
- 一个课堂有 N 条高光,生成 N 个 MP4。
- 全量模式录制 xdyui2 前一天全部高光。
- 任务模式只处理 `status=0 && onlyHighlight=1`。
- WebScreen 只生成本地文件,服务器原任务负责搬运到 OSS。
- 暂不启用 CrazyTalk。
不要直接覆盖现有正式录制服务器。
## 2. 交付物和外部依赖
项目包:
```text
webScreen-full-latest.zip
```
包内含源码、Git 历史、`.env`、`node_modules`、文档和测试。`node_modules` 来自 macOS,Linux 必须重新安装。
项目不包含 `web_capture_c`。需从现有录制服务器复制完整运行目录:
```text
/root/web_capture_release
/root/web_capture_release/linux-x64/web_capture_c
```
同时复制其动态库、字体、浏览器运行环境和显示服务配置。
## 3. 部署前检查
```bash
date
timedatectl
node -v
npm -v
ss -lntp | grep ':3001'
df -h /root
test -x /root/web_capture_release/linux-x64/web_capture_c && echo CAPTURE_OK
```
要求:
- 时区为 `Asia/Shanghai`,NTP 已同步。
- Node.js 与现有正式服务器一致。
- 端口 `3001` 未被占用。
- 录制程序可执行,磁盘空间充足。
## 4. 解压和安装
```bash
cd /root
unzip webScreen-full-latest.zip
cd /root/webScreen
mv node_modules node_modules.macos.bak
npm install
npm test
```
预期测试输出:
```text
highlightRecordingService tests passed
highlight routes tests passed
```
## 5. 环境变量
`.env` 需要包含:
```text
ALIBABA_CLOUD_ACCESS_KEY_ID=...
ALIBABA_CLOUD_ACCESS_KEY_SECRET=...
```
只检查是否存在:
```bash
grep -q '^ALIBABA_CLOUD_ACCESS_KEY_ID=' .env && echo ACCESS_KEY_ID_OK
grep -q '^ALIBABA_CLOUD_ACCESS_KEY_SECRET=' .env && echo ACCESS_KEY_SECRET_OK
```
这两个变量只用于查询 OSS 状态;WebScreen 不主动上传文件。
## 6. 配置
编辑 `/root/webScreen/config/config.json`。保留服务器原有:
- `GETCLASSURL`
- `GETCLASSURLPARAMETER`
- `PROJECTWINCATALOG`
- `PROJECTCATALOG`
- `BACKMEDIACONFIG`
- `classLastNumber`
目录应与服务器一致:
```json
"PROJECTWINCATALOG": "/root/web_capture_release/linux-x64",
"PROJECTCATALOG": "/root/web_capture_release"
```
`BACKMEDIACONFIG.url` 必须指向已支持 `recBeginTime/recEndTime` 的 PCLive 测试版本。保留验证服务器已确认可用的 `devback` 或测试路径,不在代码中硬编码。
高光配置:
```json
"HIGHLIGHTCONFIG": {
"enabled": false,
"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=false`。验证 JSON:
```bash
node -e "JSON.parse(require('fs').readFileSync('config/config.json')); console.log('config ok')"
```
## 7. 启动服务
测试期间先不要配置 cron。
```bash
npm run pm2
pm2 show webScreen
curl http://127.0.0.1:3001/highlight/status
```
若 PM2 已有同名进程:
```bash
pm2 restart webScreen
```
状态接口预期:
```json
{
"code": 0,
"message": "success",
"data": {
"queued": 0,
"recording": 0,
"knownTasks": 0
}
}
```
查看日志:
```bash
pm2 logs webScreen --lines 100
```
## 8. 开启 xdyui2
基础服务正常后修改:
```json
"enabled": true,
"sourceMode": "site",
"siteIds": ["xdyui2"]
```
```bash
pm2 restart webScreen
```
## 9. 准备测试课堂
选择一个 xdyui2 已结束课堂:
- 至少两条高光。
- 回放正常。
- 最好含教师、学生音视频、屏幕共享和声音。
记录:
```text
siteId:xdyui2
classId:__________
高光数量:__________
课堂日期:__________
```
## 10. 只读预览
预览不会启动录制程序:
```bash
curl -X POST http://127.0.0.1:3001/highlight/preview/by-class \
-H 'Content-Type: application/json' \
-d '{"classId":"替换为课堂号"}'
```
逐条检查:
- `siteId` 是 `xdyui2`。
- `highlightId` 不重复。
- `classId` 正确。
- `beginTime/endTime` 是 13 位毫秒时间戳。
- `duration = endTime - beginTime`。
- `playbackUrl` 含正确的 `recBeginTime/recEndTime`。
- 文件名为 `{classId}_highlight_{highlightId}.mp4`。
- 路径位于 `/root/web_capture_release/media/xdyui2/{yyyyMMdd}/`。
返回“无高光数据”时,先让后端确认高光表确实存在记录。
## 11. 单课堂录制
```bash
curl -X POST http://127.0.0.1:3001/highlight/recording/by-class \
-H 'Content-Type: application/json' \
-d '{"classId":"替换为课堂号"}'
```
新任务初始状态应为 `queued`;已有文件可能返回 `uploading` 或 `generated`。
观察队列和进程:
```bash
watch -n 2 'curl -s http://127.0.0.1:3001/highlight/status'
tail -f /root/webScreen/log/$(date +%Y%m%d).txt
ps -ef | grep '[w]eb_capture_c'
```
响应返回后不能立即停止 PM2;录制在后台队列继续执行。
## 12. 本地文件验证
```bash
find /root/web_capture_release/media/xdyui2 -type f -name '课堂号_highlight_*.mp4' -ls
```
要求:
- N 条高光生成 N 个文件。
- 文件名中的 `highlightId` 不同。
- 文件大小大于 0。
- 不覆盖旧 `{classId}.mp4`。
- 日期目录包含 `download.json`。
- `.highlight_tmp` 无本次任务残留。
如有 ffprobe:
```bash
ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 /完整/文件路径.mp4
```
人工播放检查:
- 开始位置接近 `beginTime`。
- 结束位置接近 `endTime`。
- 教师、学生、屏幕共享画面正常。
- 声音正常。
- 文件不是整堂课堂。
## 13. 重复录制验证
再次调用同一课堂的 `/highlight/recording/by-class`。
要求:
- 不再启动新的 `web_capture_c`。
- 文件数量不增加。
- 原文件不被覆盖。
- OSS 已有文件时也不重复录制。
## 14. OSS 搬运和多地址查询
等待服务器原搬运任务执行。预期 OSS Key:
```text
oss/xdyui2/{yyyyMMdd}/{classId}_highlight_{highlightId}.mp4
```
查询:
```bash
curl -X POST http://127.0.0.1:3001/highlight/fileExists \
-H 'Content-Type: application/json' \
-d '{"siteId":"xdyui2","classId":"替换为课堂号"}'
```
OSS 尚不可见时:
```text
status = uploading
generated = false
```
OSS 可见后:
```text
status = generated
generated = true
url = https://xdymp4.xuedianyun.com/oss/...
```
N 条高光时,`classUrlList` 必须有 N 条记录。
## 15. 前一天全量验证
保持:
```json
"sourceMode": "site",
"siteIds": ["xdyui2"]
```
手工调用 cron 入口:
```bash
wget -qO- http://127.0.0.1:3001/recording
```
检查:
- `code` 为 `"0"`。
- `data.mode` 为 `site`。
- `beginTime/endTime` 是 Asia/Shanghai 前一天。
- 只查询 xdyui2。
- 前一天每条有效高光都进入队列。
## 16. 任务模式验证
全量模式通过后改为:
```json
"sourceMode": "task"
```
```bash
pm2 restart webScreen
```
请后端创建四组任务:
1. `status=0, onlyHighlight=1, siteId=xdyui2`:应录制。
2. `status!=0, onlyHighlight=1`:不录制。
3. `status=0, onlyHighlight=0`:不进入高光录制。
4. 其他站点 `status=0, onlyHighlight=1`:不录制。
```bash
wget -qO- http://127.0.0.1:3001/recording
```
检查:
- `data.mode` 为 `task`。
- `pendingTasks` 只统计第一类任务。
- 使用 `taskList.meetingNumber` 查询课堂高光。
后端尚未确认任务状态回写接口。当前依靠内存队列、本地文件和 OSS 文件避免重复录制。
## 17. 启用每日 cron
只有单课堂、重复录制、OSS 搬运和全量模式全部通过后才启用:
```cron
57 7 * * * wget -qO- http://127.0.0.1:3001/recording >/dev/null 2>&1
```
```bash
crontab -l
```
任务每天 `07:57` 执行。任务模式中新任务最多等待约 24 小时,业务已确认可接受。
## 18. 日常使用
```bash
pm2 show webScreen
curl http://127.0.0.1:3001/highlight/status
pm2 logs webScreen --lines 200
tail -n 200 /root/webScreen/log/$(date +%Y%m%d).txt
```
手工补录:
```bash
curl -X POST http://127.0.0.1:3001/highlight/recording/by-class \
-H 'Content-Type: application/json' \
-d '{"classId":"课堂号"}'
```
查询地址:
```bash
curl -X POST http://127.0.0.1:3001/highlight/fileExists \
-H 'Content-Type: application/json' \
-d '{"siteId":"xdyui2","classId":"课堂号"}'
```
## 19. 故障排查
### 高光录制功能未启用
检查 `HIGHLIGHTCONFIG.enabled=true`,修改后执行 `pm2 restart webScreen`。
### SaaS 接口 code=4
检查服务器时间、NTP、`apiBaseUrl` 和最新代码。签名时间戳必须是 13 位毫秒。
### 无高光数据
检查高光表记录、`meetingNumber`、`siteId=xdyui2`,以及全量模式时间窗是否为前一天。
### web_capture_c 启动失败
```bash
ls -l /root/web_capture_release/linux-x64/web_capture_c
ldd /root/web_capture_release/linux-x64/web_capture_c
echo "$DISPLAY"
```
比较正式服务器的显示服务、字体、浏览器依赖和 PM2 环境变量。
### 一直是 uploading
检查搬运任务是否运行,是否支持 `{classId}_highlight_{highlightId}.mp4`、`download.json` 和 `oss/xdyui2/{yyyyMMdd}/`。
### OSS文件状态查询失败
检查 `.env`、AccessKey 权限、OSS 网络和 bucket `xdymp4`。OSS 查询异常不会被当作“文件不存在”。
### 视频时间错误
确认 `playbackUrl` 的 `recBeginTime/recEndTime` 与接口原值完全一致。不能传 duration,不能换算相对秒数。
## 20. 回滚
优先使用配置回滚:
```json
"HIGHLIGHTCONFIG": {
"enabled": false
}
```
```bash
pm2 restart webScreen
```
关闭后,`GET /recording` 恢复原整课逻辑。`POST /recording`、`POST /recordingTask`、`POST /fileExists` 和实时录制接口不变。
## 21. 测试记录模板
```text
测试服务器:
测试日期:
测试人员:
Git 提交(执行 git rev-parse --short HEAD):
站点:xdyui2
课堂号:
高光记录数:
本地 MP4 数量:
OSS MP4 数量:
预览接口:通过 / 失败
单课堂录制:通过 / 失败
时间范围:通过 / 失败
音频:通过 / 失败
教师视频:通过 / 失败
学生视频:通过 / 失败
屏幕共享:通过 / 失败
重复录制:通过 / 失败
OSS 搬运:通过 / 失败
多地址查询:通过 / 失败
前一天全量:通过 / 失败
任务模式:通过 / 失败 / 未测试
问题记录:
结论:可继续验证 / 需要修复
```
... ...