Files
slogan/styleagent/controller/avatar_controller.go
T
admin fd13efb9c0 feat: 3D 化身服务端预渲染(Node 渲染器 + 帧轮播 + 降级)
- Node 渲染器(three r162 + headless-gl + pngjs):gen-templates 程序化生成简化人体 GLB(6 脸 × 6 体 × 5 肤色),render.js 绕 Y 轴 36 帧 256x512 白底渲染
- agent/render.go:RenderAvatarFrames 帧目录缓存复用 + GLB 缺失自动生成 + 15 分钟超时;render.enabled/node_bin 配置,node_bin 路径缺失回退 PATH
- Build 异步化:写库 processing → goroutine 渲染 → done+frames_url / failed+error(客户端降级静态占位);修 BodyMeasurement 无记录时 Build 报错
- avatar_model 容错 ALTER 加 frames_url 列;AvatarGetRes 透传 frames_url
- TDD:renderJob 状态机测试(成功 done / 失败 failed 降级)
- 客户端 avatar_viewer 帧轮播(120ms × 36 帧,errorBuilder 降级占位),avatar_provider 解析 frames_url
- Dockerfile 双阶段:node:20-alpine 编译 gl 原生模块 + 运行时带 nodejs/libglvnd
2026-07-31 15:37:02 +08:00

40 lines
1.0 KiB
Go

package controller
import (
"context"
"slogan-agent/common"
"slogan-agent/styleagent/model/dto"
"slogan-agent/styleagent/service"
"github.com/gogf/gf/v2/frame/g"
)
type avatar struct{}
var Avatar = new(avatar)
func (c *avatar) Build(ctx context.Context, req *dto.AvatarBuildReq) (res *dto.AvatarBuildRes, err error) {
a, err := service.AvatarService.Build(ctx, common.GetUserId(g.RequestFromCtx(ctx)))
if err != nil {
return nil, err
}
return &dto.AvatarBuildRes{AvatarId: a.Id, Status: a.BuildStatus}, nil
}
func (c *avatar) Get(ctx context.Context, req *dto.AvatarGetReq) (res *dto.AvatarGetRes, err error) {
a, err := service.AvatarService.Get(ctx, common.GetUserId(g.RequestFromCtx(ctx)))
if err != nil || a == nil {
return &dto.AvatarGetRes{}, nil
}
return &dto.AvatarGetRes{
FaceTemplateId: a.FaceTemplateId,
BodyTemplateId: a.BodyTemplateId,
SkinToneIndex: a.SkinToneIndex,
GlbUrl: a.GlbUrl,
FramesUrl: a.FramesUrl,
BuildStatus: a.BuildStatus,
Error: a.Error,
}, nil
}