api
NavTalk 后端接口文档(MuseTalk & Forwarding)
本文档整理了当前项目中与 数字人 / 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。jobId或job_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,其中至少包含:
status:queued / processing / done / error等。job_id:任务 ID。position:队列位置。queue_size:当前队列总长度。result:当status == "done"时通常包含结果信息(例如结果文件路径)。
- 未找到任务:HTTP 404
- 成功(找到任务)时返回任务详情 JSON,其中至少包含:
返回示例(任务不存在):
{
"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_shiftextra_marginparsing_modeleft_cheek_widthright_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_name→type=system - 未匹配 →
type=user
- 匹配
model(可选):模型名称,传给计费系统,用于区分不同模型计费。
1.2 连接建立流程(afterConnectionEstablished)
-
校验 license:
调用BillingSystem.validateLicense(license, clientSession, dataSource),验证失败则直接关闭连接。 -
连接数限制:
使用UserConnectionManager检查当前用户是否已达到最大连接数:-
超限时,会向客户端发送 JSON:
{ "type": "session.connection_limit_exceeded", "message": "Connection limit exceeded. Current connections: X, Maximum allowed: Y" } -
然后关闭 WebSocket 连接。
-
-
GPU 分配与 Runpod 集成:
- 先尝试分配状态为“空闲”的 GPU(state=0)。
- 如果启用 Runpod(系统配置 ID=46 不为 0),可能会唤醒暂停中的 GPU 或动态创建新的 Pod。
- 若最终仍为
gpu == null,说明 GPU 资源已满:-
向客户端发送:
{ "type": "session.gpu_full", "message": "GPU资源已满,请稍后再试!" } -
关闭连接,并触发告警邮件。
-
-
构造目标 GPU WebSocket 地址:
- 保留原来的 path & query,只替换为 GPU 的 IP 与端口,并追加
type参数:
<protocol>://<gpu.ipAddress>:<gpu.port><原始 path>?<原始 query>&type=<system|user>其中:
protocol:来自配置gpuConfig.getWsProtocol()(ws或wss)。type:基于characterName和image表判断的system或user。
- 保留原来的 path & query,只替换为 GPU 的 IP 与端口,并追加
-
创建到 GPU 的 WebSocket 客户端:
- 使用
GpuClientEndpoint作为客户端 Endpoint,连接到上述目标 URI。 - 将
clientSession↔gpuSession的映射保存到gpuSessions。 - 创建聊天会话记录
ChatSession,并存入chatSessions(包含 webhook 地址)。
- 使用
-
计费初始化:
- 从系统配置获取计费间隔(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)
- 从
gpuSessions中移除并关闭 GPU WebSocket 连接。 - 更新
ChatSession状态为结束,并记录结束时间。 - 通过
UserConnectionManager为当前用户减少连接计数。 - 计费最终结算:
- 取出
billingSystem,设置isRunning = false停止计费循环。 - 调用
finalizeBilling()完成剩余时长计费与扣费。
- 取出
- GPU 回收:
- 若启用 Runpod,则使用
runpodId调用runpodClient.stopPod(runpodId),并将 GPU 状态更新为暂停(state=3)。 - 若未启用 Runpod:
- 如果存在
runpodId仍按上面逻辑处理。 - 否则直接将 GPU 状态更新为空闲(
state=0)。
- 如果存在
- 若启用 Runpod,则使用
2. GpuAvatarProxyHandler(Avatar HTTP 代理,统一前缀 /avatar)
2.1 提交 Avatar 生成任务(转发到 Python 服务)
-
类级别请求前缀:
@RequestMapping("/avatar") -
方法:POST
-
路径:
/avatar/generate_avatar -
说明:接收上游 Avatar 生成请求,查数据库获取
api_key,然后异步转发到 Python Avatar 服务(部署于 GPU 节点)。 -
请求体类型:
application/json→UserImage对象 -
关键字段(来自
UserImage):mediaUrl(必填):媒体地址(可为图片或视频)。avatarId(必填):Avatar 标识。userId(必填):用户 ID。jobId(可选但实际需要):任务 ID,对应 Python 侧的task_id。- 其他字段(如
status等)用于状态更新,不影响转发逻辑。
-
处理流程:
- 打印并校验参数,若
mediaUrl/avatarId/userId任一为空,则返回 400。 - 根据
userId查询projects表,获取api_key:- 查询不到 → 返回 403,提示“API key not found for user”。
- 创建新线程调用
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 原始内容... } } -
通过
HttpURLConnectionPOST 到上面获取的 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/json→UserImage对象。 -
关键字段:
jobId(必填):对应任务 ID。status(必填):要更新的状态值(业务自定义)。
-
处理逻辑:
- 使用
userImageService.lambdaUpdate():- 条件:
eq(UserImage::getJobId, request.getJobId()) - 更新:
set(UserImage::getStatus, request.getStatus())
- 条件:
- 使用
-
返回:
- 更新成功:HTTP 200,内容
"状态更新成功"。 - 未找到记录:HTTP 404,内容
"未找到对应的任务记录"。 - 处理异常:HTTP 500,内容
"处理状态更新失败: ..."。
- 更新成功:HTTP 200,内容
三、后续可扩展内容(建议)
后续如需进一步标准化接口,可基于本文件生成:
-
OpenAPI / Swagger 文档:
将上述接口转换为openapi.yaml,便于前端自动生成 SDK 与接口 Mock。 -
调用示例:
补充常用语言的调用示例,例如:- JavaScript(
axios/fetch)调用/avatar/generate_avatar。 - Python(
requests)调用/api/generate与/api/query_status。 - Web 前端通过 WebSocket 连接
GpuWebSocketProxyHandler的示例。
- JavaScript(
如需,我可以在本仓库中进一步补充这些示例与 OpenAPI 文件。
- 感谢你赐予我前进的力量

