# yuban-server `yuban-server` 是自传语伴新增业务能力的独立 Node.js 服务。它只承载旧服务器尚未实现、且不负责正式数据读写的业务接口。 首个能力是“历史长录音异步转写”:浏览器提交旧对象存储中的录音 URL,新服务临时下载并转为 16kHz 单声道 PCM WAV,调用讯飞 IST,最后返回完整正文和说话人分段。浏览器再通过原有 `server.fmode.cn`/Parse 接口把结果保存到 `ChatVoice`。 ## 边界 - 不查询或写入 `ChatVoice`、`ChatSession`、`Article`、会员、订单等业务表。 - 不替代旧服务器中已经正常运行的接口。 - 只调用旧 Parse 的 `/users/me` 校验现有 Session Token;不会实现第二套用户系统。 - 转写任务和正文仅作为本机临时运行状态保存,默认 24 小时后删除。 - 日志不打印录音 URL、Session Token、逐字稿正文或讯飞原始结果。 - 默认每个用户最多同时运行 2 个任务、保留 20 个临时任务,避免合法账号误触发任务风暴。 ```mermaid sequenceDiagram participant Web as Angular 前端 participant Old as 旧服务器 / Parse participant New as yuban-server participant OSS as 对象存储 participant ASR as 讯飞 IST Web->>Old: 读取 ChatVoice.audioUrl Web->>New: POST /recording-transcription/jobs New->>Old: /users/me 校验 Session Token New-->>Web: 202 + jobId New->>OSS: 临时下载录音 New->>New: ffmpeg 转码 New->>ASR: 提交并轮询转写 Web->>New: GET /recording-transcription/jobs/:jobId New-->>Web: 完整 text + segments + SHA-256 Web->>Old: 使用原接口保存 ChatVoice 权威逐字稿 ``` ## 接口 ### `GET /health` 健康检查,不返回密钥或任务内容。 ### `POST /recording-transcription/jobs` 创建异步任务,正常情况下立即返回 HTTP `202`。 ```json { "audioUrl": "https://file.yuban.co/path/recording.mp3", "durationMs": 3600000, "roleType": 1, "roleNum": 0, "requestId": "chatVoice-object-id" } ``` 请求头: ```text Authorization: Bearer <现有 Parse Session Token> Idempotency-Key: Content-Type: application/json ``` 响应: ```json { "success": true, "reused": false, "job": { "id": "7d84a8db-4b55-43d8-b9f7-6d20d35c443f", "status": "queued", "stage": "queued", "progress": 0, "createdAt": "2026-08-05T09:00:00.000Z", "updatedAt": "2026-08-05T09:00:00.000Z", "heartbeatAt": null, "expiresAt": "2026-08-06T09:00:00.000Z" } } ``` ### `GET /recording-transcription/jobs/:jobId` 查询任务。`completed` 时增加: ```json { "result": { "text": "完整逐字稿……", "segments": [ { "text": "片段正文", "startMs": 0, "endMs": 1200, "speakerId": "1" } ], "charCount": 15732, "sha256": "..." } } ``` 任务状态为 `queued`、`running`、`completed`、`failed` 或 `cancelled`;阶段为 `queued`、`downloading`、`transcoding`、`submitting`、`transcribing`、`completed`、`failed`、`cancelled`。 ### `POST /recording-transcription/jobs/:jobId/cancel` 取消尚未完成的任务。讯飞侧可能已经收到音频,但新服务会停止继续轮询,也不会返回逐字稿。 完整契约见 [openapi.yaml](./openapi.yaml)。 ## 本地运行 要求:Node.js 22+、`ffmpeg`、`ffprobe`。 ```bash cp .env.example .env # 填写讯飞凭据和前端来源白名单 npm test npm start ``` 服务默认监听 `http://127.0.0.1:3200`(生产示例使用 `0.0.0.0:3200`)。本项目仅使用 Node 内置模块,不需要安装 npm 运行依赖。 开发环境若暂时不连接旧 Parse,可使用 `NODE_ENV=development AUTH_MODE=disabled`;生产环境会拒绝关闭认证。 ## 生产部署 推荐使用 Docker: ```bash docker build -t yuban-server:1.0.0 . docker run -d \ --name yuban-server \ --restart unless-stopped \ --env-file .env \ -p 127.0.0.1:3200:3200 \ -v yuban-server-jobs:/app/var/jobs \ yuban-server:1.0.0 ``` `deploy/nginx.conf.example` 展示了 HTTPS 反向代理配置。不要让 Node 端口直接暴露到公网。生产环境至少要完成: 1. 配置 HTTPS 域名,例如 `business-api.yuban.co`。 2. 把 `CORS_ALLOWED_ORIGINS` 限制为真实 Angular 域名(精确匹配,不要使用 `*`): ```env CORS_ALLOWED_ORIGINS=https://www.yuban.co,https://yuban.co,http://localhost:4200,http://127.0.0.1:4200 ``` 3. 保持 `ALLOWED_AUDIO_HOSTS=file.yuban.co` 或更窄。 4. 仅在服务器环境变量中保存讯飞密钥。 5. 监控 `/health`、任务失败率、磁盘容量和 ffmpeg/ffprobe 可用性。 ## 前端接入 只为历史长录音重转写配置新服务地址: ```html ``` 旧服务器地址不需要更改。实时录音、已有长语音上传、数据保存、故事生成等现有链路仍走原接口。