本文档整理了当前项目中与 数字人 / Avatar / 实时 GPU 服务 相关的接口,覆盖:

  • Python 服务:MuseTalk(端口 8813 / 8814 / 8816)
  • Java 服务:Forwarding 中的 GpuWebSocketProxyHandler(WebSocket)与 GpuAvatarProxyHandler(REST)

文档以 接口路径 + 请求方式 + 关键参数 + 返回说明 的形式给出,便于前后端联调与排查问题。


一、MuseTalk:Python 服务接口

1. app.py(推理任务队列服务,端口默认 8813)

1.1 健康检查

  • 方法:GET
  • 路径/health
  • 说明:检查服务是否可用,并返回当前队列信息。
  • 请求参数:无
  • 返回示例
{
  "status": "ok",
  "ffmpeg": true,
  "queue": 1
}

字段说明:

  • status:固定为 "ok" 表示服务正常。
  • ffmpeg:FFmpeg 探测结果,true/false
  • queue:当前任务队列长度(包括正在处理的 1 个任务)。

1.2 提交推理任务(音频 + 视频)

  • 方法:POST

  • 路径/process/api/enqueue/infer

  • 说明:提交“音频 + 视频”任务到队列,异步生成数字人口型视频。

  • 请求类型multipart/form-data

  • 表单字段

    • 文件:
      • audio(必填):音频文件。
      • video(必填):视频文件。
    • 文本:
      • userId(必填):用户 ID。
      • license(必填):项目/授权 License。
      • jobIdjob_id(可选):任务 ID,不传可在上游自行约定或生成。
      • 可选参数(均有默认值):
        • bbox_shift(默认 0)
        • extra_margin(默认 10)
        • parsing_mode(默认 "jaw"
        • left_cheek_width(默认 90)
        • right_cheek_width(默认 90)
  • 返回:HTTP 状态码 202 Accepted

返回 JSON 示例:

{
  "status": "accepted",
  "job_id": "your-job-id",
  "position": 0,
  "queue_size": 1
}

字段说明:

  • status"accepted" 表示已进入队列。
  • job_id:任务 ID,建议由上游生成并透传。
  • position:在队列中的位置(0 表示当前/即将处理)。
  • queue_size:当前队列总长度(包含正在处理的任务)。

1.3 查询任务状态

  • 方法:GET

  • 路径/process/api/status/<job_id>

  • 说明:根据 job_id 查询任务的当前状态与结果。

  • 路径参数

    • job_id:提交任务时使用的任务 ID。
  • 返回

    • 成功(找到任务)时返回任务详情 JSON,其中至少包含:
      • statusqueued / processing / done / error 等。
      • job_id:任务 ID。
      • position:队列位置。
      • queue_size:当前队列总长度。
      • result:当 status == "done" 时通常包含结果信息(例如结果文件路径)。
    • 未找到任务:HTTP 404

返回示例(任务不存在):

{
  "status": "error",
  "message": "job not found"
}

1.4 获取结果文件

  • 方法:GET

  • 路径/process/results/<path:filename>

  • 说明:根据文件名访问生成结果文件。

  • 路径参数

    • filename:结果目录下的相对路径。
  • 返回:结果文件内容(通常为视频流)。
    前端一般根据 status 查询接口拿到文件名后,再通过该接口拉取结果。


2. app_interface.py(数字人生成网关,端口默认 8814)

2.1 提交数字人生成任务(统一入口)

  • 方法:POST

  • 路径/api/generate

  • 说明:统一的“数字人视频生成”入口,支持多种组合形式,内部使用任务队列异步处理。

  • 请求类型application/json

  • 请求体字段

    • license(必填):授权/项目 License。
    • task_id(必填):任务 ID。
    • data(必填):业务数据对象,根据不同字段组合决定具体生成模式。常见字段包括:
      • 媒体相关:
        • image_url:图片地址。
        • video_url:视频地址。
        • audio_url:音频地址。
        • audio_base64:Base64 编码音频。
      • 文本 & 声音:
        • content:文字内容。
        • voice:TTS 声音模型/角色。
      • 系统角色:
        • character_name:系统预置角色名称(如 navtalk.Alex 等)。
      • 可选控制参数(均有默认值):
        • bbox_shift
        • extra_margin
        • parsing_mode
        • left_cheek_width
        • right_cheek_width

内部根据 data 的组合调用不同的处理方法(method01 ~ method09),典型组合示例:

  • image_url + audio_url:图片 + 音频 → 生成视频。

  • image_url + content + voice:图片 + 文本 → TTS → 生成视频。

  • video_url + audio_url:视频 + 音频 → 生成视频。

  • video_url + content + voice:视频 + 文本 → TTS → 生成视频。

  • character_name + audio_url:系统角色 + 音频 → 生成视频。

  • character_name + content + voice:系统角色 + 文本 → TTS → 生成视频。

  • image_url + audio_base64:图片 + Base64 音频 → 生成视频。

  • video_url + audio_base64:视频 + Base64 音频 → 生成视频。

  • character_name + audio_base64:系统角色 + Base64 音频 → 生成视频。

  • 返回

    • 成功:HTTP 200

      {
        "status": "started",
        "task_id": "your-task-id"
      }
      
    • 失败:HTTP 500,返回错误信息。

2.2 查询生成任务状态

  • 方法:GET

  • 路径/api/query_status

  • 说明:根据 license + task_id 查询数字人生成任务状态和结果。

  • 请求类型:Query 参数

  • 请求参数

    • license(必填)
    • task_id(必填)
  • 返回

    • 找到任务:

      {
        "status": 2,
        "video_url": "https://xxx/blob.core.windows.net/easyai/uploadFiles/2025/..."
      }
      

      其中 status 为数据库中记录的任务状态(数值含义视 api_result 表约定)。

    • 未找到任务:HTTP 404

      {
        "error": "Task not found"
      }
      
    • 数据库异常:HTTP 500


3. avatar_api.py(Avatar API 服务,端口默认 8816,统一前缀 /avatar

3.1 服务健康检查

  • 方法:GET

  • 路径/avatar/health

  • 说明:检查 Avatar 服务健康状态及队列情况。

  • 请求参数:无

  • 返回示例

{
  "status": "healthy",
  "message": "Avatar生成服务运行正常",
  "queue_info": {
    "queue_size": 0,
    "total_tasks": 0,
    "pending_tasks": 0,
    "processing_tasks": 0,
    "completed_tasks": 0,
    "failed_tasks": 0,
    "max_workers": 2,
    "active_workers": 2
  }
}

3.2 提交 Avatar 生成任务

  • 方法:POST

  • 路径/avatar/generate_avatar

  • 说明:提交 Avatar 生成任务到内部队列,由后台线程异步处理。

  • 请求类型application/json

  • 请求体字段

    • 必填:
      • media_url:媒体地址(图片或视频)。
      • avatar_id:Avatar 标识。
      • task_id:任务 ID。
      • api_key:调用方 API Key(通常对应项目维度)。
    • 可选:
      • bbox_shift(默认 0)
      • version(默认 "v15"
      • extra_margin(默认 0)
      • parsing_mode(默认 "raw"
      • base_path(默认值:RESULTS_DIR/api_key
  • 返回

    • 成功:HTTP 202

      {
        "success": true,
        "task_id": "your-task-id",
        "message": "任务已提交到队列,请使用task_id查询进度",
        "queue_position": 1
      }
      
    • 参数缺失:HTTP 400,返回 success=false 和错误描述。

    • 内部异常:HTTP 500。

3.3 查询单个任务状态

  • 方法:GET

  • 路径/avatar/task_status/<task_id>

  • 说明:根据 task_id 查询 Avatar 生成任务状态。

  • 路径参数

    • task_id:任务 ID。
  • 返回

    • 成功:

      {
        "success": true,
        "task_info": {
          "task_id": "xxx",
          "status": "completed",
          "message": "Avatar生成完成",
          "result": { "..." : "..." },
          "error": null,
          "create_time": 1710000000,
          "start_time": 1710000010,
          "end_time": 1710000020,
          "duration": 10.0,
          "parameters": {
            "bbox_shift": 0,
            "version": "v15",
            "extra_margin": 0,
            "parsing_mode": "raw",
            "base_path": "/path/to/results"
          }
        }
      }
      
    • 任务不存在:HTTP 404

      {
        "success": false,
        "error": "任务不存在"
      }
      

3.4 列出任务列表

  • 方法:GET

  • 路径/avatar/tasks

  • 说明:按条件列出任务列表,用于后台查看。

  • Query 参数

    • status(可选):过滤状态,如 pending / processing / completed / failed
    • limit(可选,默认 20):最大返回条数。
  • 返回示例

{
  "success": true,
  "tasks": [ { "task_id": "...", "status": "...", ... } ],
  "total": 10
}

3.5 取消任务

  • 方法:DELETE

  • 路径/avatar/task/<task_id>

  • 说明:取消指定任务,仅对 pending 状态有效。

  • 路径参数

    • task_id:任务 ID。
  • 返回

    • 成功取消:

      {
        "success": true,
        "message": "任务已取消"
      }
      
    • 任务不存在:HTTP 404。

    • 任务非 pending 状态:HTTP 400。

3.6 获取 Avatar 信息

  • 方法:GET

  • 路径/avatar/avatar_info/<avatar_id>

  • 说明:读取 Avatar 对应的配置/信息文件。

  • 路径参数

    • avatar_id:Avatar 标识。
  • Query 参数

    • version(可选,默认 "v15"
    • base_path(可选,默认 "./results"
  • 返回

    • 成功:

      {
        "success": true,
        "avatar_info": { "...": "..." }
      }
      
    • 文件不存在:HTTP 404。

3.7 全局错误返回(avatar_api)

  • 400:{"success": false, "error": "请求参数错误"}
  • 404:{"success": false, "error": "资源不存在"}
  • 500:{"success": false, "error": "内部服务器错误"}

二、Forwarding:Java 服务接口

1. GpuWebSocketProxyHandler(实时对话 WebSocket 代理)

该类为 Spring 的 TextWebSocketHandler,具体 WebSocket 路径由 WebSocket 配置类决定(如 /ws/realtime 等)。这里重点整理“接入约定”和消息协议。

1.1 WebSocket 连接约定

  • URL 示例
ws(s)://forwarding-host/ws/realtime?license=XXX&characterName=navtalk.Alex&model=gpt-4.1-realtime
  • Query 参数
    • license(必填):用于调用 BillingSystem.validateLicense 校验账号与套餐。
    • characterName(可选):Avatar 名称,用于查询 image 表,判断是系统角色还是用户角色:
      • 匹配 image.image_nametype=system
      • 未匹配 → type=user
    • model(可选):模型名称,传给计费系统,用于区分不同模型计费。

1.2 连接建立流程(afterConnectionEstablished)

  1. 校验 license
    调用 BillingSystem.validateLicense(license, clientSession, dataSource),验证失败则直接关闭连接。

  2. 连接数限制
    使用 UserConnectionManager 检查当前用户是否已达到最大连接数:

    • 超限时,会向客户端发送 JSON:

      {
        "type": "session.connection_limit_exceeded",
        "message": "Connection limit exceeded. Current connections: X, Maximum allowed: Y"
      }
      
    • 然后关闭 WebSocket 连接。

  3. GPU 分配与 Runpod 集成

    • 先尝试分配状态为“空闲”的 GPU(state=0)。
    • 如果启用 Runpod(系统配置 ID=46 不为 0),可能会唤醒暂停中的 GPU 或动态创建新的 Pod。
    • 若最终仍为 gpu == null,说明 GPU 资源已满:
      • 向客户端发送:

        {
          "type": "session.gpu_full",
          "message": "GPU资源已满,请稍后再试!"
        }
        
      • 关闭连接,并触发告警邮件。

  4. 构造目标 GPU WebSocket 地址

    • 保留原来的 path & query,只替换为 GPU 的 IP 与端口,并追加 type 参数:
    <protocol>://<gpu.ipAddress>:<gpu.port><原始 path>?<原始 query>&type=<system|user>
    

    其中:

    • protocol:来自配置 gpuConfig.getWsProtocol()wswss)。
    • type:基于 characterNameimage 表判断的 systemuser
  5. 创建到 GPU 的 WebSocket 客户端

    • 使用 GpuClientEndpoint 作为客户端 Endpoint,连接到上述目标 URI。
    • clientSessiongpuSession 的映射保存到 gpuSessions
    • 创建聊天会话记录 ChatSession,并存入 chatSessions(包含 webhook 地址)。
  6. 计费初始化

    • 从系统配置获取计费间隔(ID=45)。
    • 依据用户账号、model 等实例化 BillingSystem,调用 startRealtimeBilling(intervalTime) 启动计费线程。
    • billingSystem 存入 clientSession 的 attributes 中,用于连接关闭时做最终结算。

1.3 消息转发与Webhook(handleTextMessage)

  • 客户端 → 服务器:
    收到来自前端的文本消息 payload 后:
    • 原样转发到对应的 gpuSession(GPU WebSocket)。
    • 解析 JSON,当 type == "conversation.item.create" 时:
      • 将消息内容写入 chat_message 表。
      • 通过 WebhookPushUtil 异步推送到预配置的 webhookUrl

1.4 连接关闭流程(afterConnectionClosed)

  1. gpuSessions 中移除并关闭 GPU WebSocket 连接。
  2. 更新 ChatSession 状态为结束,并记录结束时间。
  3. 通过 UserConnectionManager 为当前用户减少连接计数。
  4. 计费最终结算
    • 取出 billingSystem,设置 isRunning = false 停止计费循环。
    • 调用 finalizeBilling() 完成剩余时长计费与扣费。
  5. GPU 回收
    • 若启用 Runpod,则使用 runpodId 调用 runpodClient.stopPod(runpodId),并将 GPU 状态更新为暂停(state=3)。
    • 若未启用 Runpod:
      • 如果存在 runpodId 仍按上面逻辑处理。
      • 否则直接将 GPU 状态更新为空闲(state=0)。

2. GpuAvatarProxyHandler(Avatar HTTP 代理,统一前缀 /avatar

2.1 提交 Avatar 生成任务(转发到 Python 服务)

  • 类级别请求前缀@RequestMapping("/avatar")

  • 方法:POST

  • 路径/avatar/generate_avatar

  • 说明:接收上游 Avatar 生成请求,查数据库获取 api_key,然后异步转发到 Python Avatar 服务(部署于 GPU 节点)。

  • 请求体类型application/jsonUserImage 对象

  • 关键字段(来自 UserImage):

    • mediaUrl(必填):媒体地址(可为图片或视频)。
    • avatarId(必填):Avatar 标识。
    • userId(必填):用户 ID。
    • jobId(可选但实际需要):任务 ID,对应 Python 侧的 task_id
    • 其他字段(如 status 等)用于状态更新,不影响转发逻辑。
  • 处理流程

    1. 打印并校验参数,若 mediaUrl/avatarId/userId 任一为空,则返回 400。
    2. 根据 userId 查询 projects 表,获取 api_key
      • 查询不到 → 返回 403,提示“API key not found for user”。
    3. 创建新线程调用 forwardAvatarTaskToPython(avatarRequest, taskId, apiKey)
      • 首先调用 getAvailableGpuUrl()

        • 查询 gpu 表,筛选 type = 4 AND state = 0 的空闲 GPU。

        • 使用轮询算法在可用 GPU 列表中选择一个:

          http://<ip_address>:<port>/avatar/generate_avatar
          
      • 构建 JSON 请求体:

        {
          "task_id": "jobId",
          "media_url": "mediaUrl",
          "avatar_id": "avatarId",
          "api_key": "apiKey",
          "data": { ...UserImage 原始内容... }
        }
        
      • 通过 HttpURLConnection POST 到上面获取的 Python 服务 URL。

  • 返回

    • 成功接收并启动转发线程:

      {
        "status": "success",
        "message": "Avatar generation started",
        "task_id": "jobId"
      }
      
    • 失败:

      • 数据库异常:HTTP 500。
      • API Key 不存在:HTTP 403。
      • 其他异常:HTTP 500,附带错误消息。

2.2 更新 Avatar 任务状态(供 Python 回调)

  • 方法:POST

  • 路径/avatar/update_status

  • 说明:由 Python Avatar 服务回调,用于更新 UserImage 任务状态。

  • 请求体类型application/jsonUserImage 对象。

  • 关键字段

    • jobId(必填):对应任务 ID。
    • status(必填):要更新的状态值(业务自定义)。
  • 处理逻辑

    • 使用 userImageService.lambdaUpdate()
      • 条件:eq(UserImage::getJobId, request.getJobId())
      • 更新:set(UserImage::getStatus, request.getStatus())
  • 返回

    • 更新成功:HTTP 200,内容 "状态更新成功"
    • 未找到记录:HTTP 404,内容 "未找到对应的任务记录"
    • 处理异常:HTTP 500,内容 "处理状态更新失败: ..."

三、后续可扩展内容(建议)

后续如需进一步标准化接口,可基于本文件生成:

  • OpenAPI / Swagger 文档
    将上述接口转换为 openapi.yaml,便于前端自动生成 SDK 与接口 Mock。

  • 调用示例
    补充常用语言的调用示例,例如:

    • JavaScript(axios / fetch)调用 /avatar/generate_avatar
    • Python(requests)调用 /api/generate/api/query_status
    • Web 前端通过 WebSocket 连接 GpuWebSocketProxyHandler 的示例。

如需,我可以在本仓库中进一步补充这些示例与 OpenAPI 文件。