Нет описания

彭峰 cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад
deploy cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад
src cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад
test cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад
.dockerignore 64a0c17a7e feat: initialize yuban business server 1 месяц назад
.env.example cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад
.gitignore 64a0c17a7e feat: initialize yuban business server 1 месяц назад
Dockerfile 64a0c17a7e feat: initialize yuban business server 1 месяц назад
README.md cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад
openapi.yaml cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад
package-lock.json cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад
package.json cf5c1a9e59 fix: make long transcription jobs recoverable 4 недель назад

README.md

yuban-server

yuban-server 是自传语伴新增业务能力的独立 Node.js 服务。它承载旧服务器尚未实现的长录音异步转写,并可在严格校验用户访问权限后提交权威逐字稿。

首个能力是“历史长录音异步转写”:浏览器提交旧对象存储中的录音 URL,新服务临时下载并转为 16kHz 单声道 PCM WAV,调用讯飞 IST,最后返回完整正文和说话人分段。生产启用权威落库后,服务会先写入并回读校验 ChatVoice;浏览器写入只作为兼容性兜底。

边界

  • 默认不读写业务表;只有显式启用权威逐字稿落库时,才会校验并更新请求指定的 ChatVoice。
  • 永不写入 ChatSession、Article、会员或订单等其他业务表。
  • 不替代旧服务器中已经正常运行的接口。
  • 只调用旧 Parse 的 /users/me 校验现有 Session Token;不会实现第二套用户系统。
  • 转写任务和正文会原子写入持久目录,默认保留 30 天;生产必须挂载持久卷。
  • 日志不打印录音 URL、Session Token、逐字稿正文或讯飞原始结果。
  • 默认每个用户最多同时运行 2 个任务、保留 20 个临时任务,避免合法账号误触发任务风暴。

    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
    New->>Old: 写入并回读校验 ChatVoice 权威逐字稿
    Web->>Old: 兼容性回读/兜底保存
    

接口

GET /health

健康检查,不返回密钥或任务内容。

POST /recording-transcription/jobs

创建异步任务,正常情况下立即返回 HTTP 202。

{
  "audioUrl": "https://file.yuban.co/path/recording.mp3",
  "chatVoiceId": "ChatVoice-object-id",
  "durationMs": 3600000,
  "roleType": 1,
  "roleNum": 0,
  "requestId": "chatVoice-object-id"
}

请求头:

Authorization: Bearer <现有 Parse Session Token>
Idempotency-Key: <ChatVoice objectId 或稳定请求 ID>
Content-Type: application/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 时增加:

{
  "result": {
    "text": "完整逐字稿……",
    "segments": [
      {
        "text": "片段正文",
        "startMs": 0,
        "endMs": 1200,
        "speakerId": "1"
      }
    ],
    "charCount": 15732,
    "sha256": "..."
  }
}

任务状态为 queued、running、retry_wait、completed、failed 或 cancelled。临时错误会进入 retry_wait 并由 Worker 自动重试。

POST /recording-transcription/jobs/:jobId/retry

为已经 failed 或 cancelled 且仍保留源请求的任务创建新 jobId。新任务包含 parentJobId,不会继续查询已经失败的旧任务。

POST /recording-transcription/jobs/:jobId/cancel

取消尚未完成的任务。讯飞侧可能已经收到音频,但新服务会停止继续轮询,也不会返回逐字稿。

完整契约见 openapi.yaml。

本地运行

要求:Node.js 22+、ffmpeg、ffprobe。

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:

docker build -t yuban-server:1.1.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.1.0

deploy/nginx.conf.example 展示了 HTTPS 反向代理配置。不要让 Node 端口直接暴露到公网。生产环境至少要完成:

  1. 生产入口使用 https://server.yuban.co;Node 端口只监听反向代理所在主机。
  2. 把 CORS_ALLOWED_ORIGINS 限制为真实 Angular 域名(精确匹配,不要使用 *):

    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 可用性。

权威逐字稿服务端落库需要额外配置 CANONICAL_PERSISTENCE_ENABLED=true 和仅存在于服务器环境中的 PARSE_MASTER_KEY。创建任务时服务会先用用户 Session Token 校验 ChatVoice 访问权限,完成后才用服务凭据写入并回读 hash/字数。

前端接入

只为历史长录音重转写配置新服务地址:

<script>
  window.__YUBAN_RUNTIME_CONFIG__ = {
    ...(window.__YUBAN_RUNTIME_CONFIG__ || {}),
    recordingTranscriptionBusinessApiBaseUrl: 'https://server.yuban.co'
  };
</script>

旧服务器地址不需要更改。实时录音、已有长语音上传、数据保存、故事生成等现有链路仍走原接口。