Kubernetes & Omniverse 动画管线工作流#

在此设置中,您将在 Kubernetes 集群中运行微服务,该集群支持两个独立的头像动画流实例。
工作流配置包含以下组件
Audio2Face-3D 微服务:将语音音频转换为面部动画,包括口型同步
动画图 微服务:管理和混合动画状态
Omniverse 渲染器 微服务:渲染器,根据加载的头像场景可视化动画数据
Gstreamer 客户端:捕获并显示图像和音频流数据作为用户前端
头像场景:3D 场景和头像模型数据的集合,在动画图和 Omniverse 渲染器微服务之间共享,并从 NGC 资源中拉取
先决条件#
在开始之前,请确保已安装并检查开发设置中的所有先决条件。
此外,本节假设满足以下先决条件
注意
请注意,
minikube
和microk8s
版本1.29
和1.30
已报告驱动程序问题。如果您遇到错误Cuda failure: CUDA driver version is insufficient for CUDA runtime version
,请考虑切换到microk8s 1.24
,经验证该版本可以正常工作。
最后,您需要访问公共 NGC 目录,这是下载 Avatar Configurator 所必需的。
硬件要求#
本指南假设您有足够的 GPU 资源。单个渲染器将消耗高达 8 GB 的 GPU 内存(取决于头像场景)。要运行如管线中所示的两个渲染器,我们建议使用两个 GPU。或者,您可以配置设置为在单个 GPU 上仅运行一个渲染器(请参阅调整 UCS 应用程序以适应单渲染器和 GPU)。
每个组件都有自己的硬件要求。工作流的要求是其组件的总和。
Audio2Face-3D 微服务
动画图 微服务
Omniverse 渲染器 微服务
下载 UCS 应用程序文件#
下载以下文件并将它们放在一个空的 ucs_apps
目录中
更新 animation_pipeline_params.yaml
文件的 avatar-renderer-a.livestream.host
属性以使用您自己的 IP 地址(hostname -I
将显示您的 IP 地址)。对 avatar-renderer-b
执行相同的操作。
注意
上述配置假设您有权访问两个 GPU,并且它为每个 GPU 部署一个渲染器。
调整 UCS 应用程序以适应单渲染器和 GPU#
为了减少所需的 GPU 资源,您可以通过注释掉包含 avatar-renderer-b
的所有部分和行来调整 UCS 应用程序配置,以在单个 GPU 上运行一个渲染器
animation_pipeline.yaml: (行: 49-53, 69-70)
animation_pipeline_values.yaml: (行: 38-56)
animation_pipeline_params.yaml: (行: 62-73)
配置资源下载器#
动画图微服务和 Omniverse 渲染器微服务都使用 USD 场景配置。默认情况下,UCS 应用程序配置微服务以从 NGC 下载头像场景。但是,还有其他下载资源的方法,您也可以创建自己的资源下载器 init 容器,如资源下载器部分所述。
构建 UCS 应用程序#
rm -rf _build/animation_pipeline*
ucf_app_builder_cli app build ucs_apps/animation_pipeline.yaml ucs_apps/animation_pipeline_params.yaml -o _build/animation_pipeline
部署 UCS 应用程序#
name=animation-pipeline
namespace=$name
kubectl create namespace $namespace
kubectl create secret docker-registry ngc-docker-reg-secret --docker-server=nvcr.io --docker-username='$oauthtoken' --docker-password=$NGC_CLI_API_KEY -n $namespace
kubectl create secret generic ngc-api-key-secret --from-literal=NGC_CLI_API_KEY=$NGC_CLI_API_KEY -n $namespace
然后,启动部署
helm upgrade --install --cleanup-on-fail --namespace $namespace $name _build/animation_pipeline/ -f _build/animation_pipeline/values.yaml -f ucs_apps/animation_pipeline_values.yaml
检查 Pod 状态
watch kubectl get pods -n $namespace
启动所有 Pod 将需要长达 30 分钟。您需要等到它们都指示为就绪。
准备流式传输#
我们将创建两个独立的头像流实例。
为动画图微服务添加两个不同的流 ID
stream_id_1=$(uuidgen)
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X POST -s http://127.0.0.1:8020/streams/$stream_id_1
# If using two renderers:
stream_id_2=$(uuidgen)
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X POST -s http://127.0.0.1:8020/streams/$stream_id_2
验证日志中是否存在“Sending Animation Data to output for stream_id <stream_id_#>”
kubectl logs -n $namespace -c ms ia-animation-graph-microservice-deployment-0
将流 ID 添加到 Omniverse 渲染器微服务
kubectl exec -n $namespace -c ms avatar-renderer-a-deployment-0 -- curl -X POST -s http://127.0.0.1:8021/streams/$stream_id_1
# If using two renderers:
kubectl exec -n $namespace -c ms avatar-renderer-b-deployment-0 -- curl -X POST -s http://127.0.0.1:8021/streams/$stream_id_2
验证两个渲染器微服务中都存在日志“Rendering animation data”
kubectl logs -n $namespace -c ms avatar-renderer-a-deployment-0
# If using two renderers:
kubectl logs -n $namespace -c ms avatar-renderer-b-deployment-0
设置和启动 Gstreamer#
我们将使用 Gstreamer 捕获图像和音频输出流,以可视化两个头像场景。
安装 Gstreamer 插件
sudo apt-get install gstreamer1.0-plugins-bad gstreamer1.0-libav
使用 ucs_apps/animation_pipeline_params.yaml 中指定的端口。默认端口为视频 9020/9030 和音频 9021/9031。
在各自的终端中运行以下每个命令
# Avatar stream 1
gst-launch-1.0 -v udpsrc port=9020 caps="application/x-rtp" ! rtpjitterbuffer drop-on-latency=true latency=20 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! fpsdisplaysink text-overlay=0 video-sink=autovideosink
gst-launch-1.0 -v udpsrc port=9021 caps="application/x-rtp,clock-rate=16000" ! rtpjitterbuffer ! rtpL16depay ! audioconvert ! autoaudiosink sync=false
# Avatar stream 2 (if using two renderers)
gst-launch-1.0 -v udpsrc port=9030 caps="application/x-rtp" ! rtpjitterbuffer drop-on-latency=true latency=20 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! fpsdisplaysink text-overlay=0 video-sink=autovideosink
gst-launch-1.0 -v udpsrc port=9031 caps="application/x-rtp,clock-rate=16000" ! rtpjitterbuffer ! rtpL16depay ! audioconvert ! autoaudiosink sync=false
或者,您也可以将音频和视频流一起录制到文件中
# Avatar stream 1
gst-launch-1.0 -e -v udpsrc port=9021 caps="application/x-rtp,clock-rate=16000" ! rtpjitterbuffer ! rtpL16depay ! audioconvert ! matroskamux name=mux ! filesink location="stream_id_1.mkv" udpsrc port=9020 caps="application/x-rtp" ! rtpjitterbuffer drop-on-latency=true latency=20 ! rtph264depay ! h264parse ! mux.
# Avatar stream 2 (if using two renderers)
gst-launch-1.0 -e -v udpsrc port=9031 caps="application/x-rtp,clock-rate=16000" ! rtpjitterbuffer ! rtpL16depay ! audioconvert ! matroskamux name=mux ! filesink location="stream_id_2.mkv" udpsrc port=9030 caps="application/x-rtp" ! rtpjitterbuffer drop-on-latency=true latency=20 ! rtph264depay ! h264parse ! mux.
测试动画图接口#
回到您的主终端,让我们为头像 1 设置一个新的姿势
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X PUT -s http://127.0.0.1:8020/streams/$stream_id_1/animation_graphs/avatar/variables/posture_state/Talking
或更改头像的位置
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X PUT -s http://127.0.0.1:8020/streams/$stream_id_1/animation_graphs/avatar/variables/position_state/Left
或启动一个手势
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X PUT -s http://127.0.0.1:8020/streams/$stream_id_1/animation_graphs/avatar/variables/gesture_state/Pulling_Mime
或触发一个面部表情
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X PUT -s http://127.0.0.1:8020/streams/$stream_id_1/animation_graphs/avatar/variables/facial_gesture_state/Smile
或者,在启用端口转发后,您可以浏览动画图微服务 (http://127.0.0.1:8020/docs) 或 Omniverse 渲染器微服务 (http://127.0.0.1:8021/docs) 的 OpenAPI 接口
kubectl port-forward -n $namespace ia-animation-graph-microservice-deployment-0 8020:8020
kubectl port-forward -n $namespace avatar-renderer-a-deployment-0 8021:8021
您可以在此处找到所有有效的变量值:默认动画图。
测试 Audio2Face-3D#
在单独的选项卡中,激活端口转发
kubectl port-forward -n $namespace a2f-with-emotion-a2f-deployment-XXX 50010:50010
kubectl port-forward -n $namespace ia-animation-graph-microservice-deployment-0 8020:8020
请注意,Audio2Face-3D Pod 有一个随机后缀,必须在上述命令中进行调整。
现在让我们使用一个示例音频文件输入到 Audio2Face-3D,以驱动面部说话动画。
通常,您会通过其 gRPC API 将音频发送到 Audio2Face-3D。为了方便起见,一个 Python 脚本允许您通过命令行执行此操作。按照设置脚本的步骤操作。
该脚本附带一个示例音频文件,该文件与 Audio2Face-3D 兼容。运行以下命令以将示例音频文件发送到 Audio2Face-3D
注意
Audio2Face-3D 要求音频为 16KHz 单声道格式。
python3 validate.py -u 127.0.0.1:50010 -i $stream_id_1 Mark_joy.wav
提取崩溃转储#
列出保存崩溃转储的目录
kubectl exec -n $namespace -c ms avatar-renderer-a-deployment-0 -- ls -alh /home/ace/asset
将崩溃转储 (<uuid>.zip) 复制到本地文件系统
kubectl cp -n $namespace avatar-renderer-a-deployment-0:/home/ace/asset/526ab2d4-72be-4f3d-d83ad384-893d4b00.dmp.zip -c ms 526ab2d4-72be-4f3d-d83ad384-893d4b00.dmp.zip
如果需要,复制到不同的机器
scp.exe -r <username>@<hostname>:<folder_path>/*.zip .\Downloads\
更改头像场景#
要修改或切换默认头像场景,您可以使用头像配置器。
下载并解压缩它,并通过运行 ./run_avatar_configurator.sh
启动它。

一旦它成功启动(第一次启动需要更长时间来编译着色器),您就可以创建自定义的新场景并保存它。
现在,您需要将新场景上传到 NGC(请参阅将版本上传到 NGC 资源)并调整 UCS 应用程序配置中的相关链接并重新部署它。
清理:移除流#
您可以使用以下命令清理流
kubectl exec -n $namespace -c ms avatar-renderer-a-deployment-0 -- curl -X DELETE -s http://127.0.0.1:8021/streams/$stream_id_1
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X DELETE -s http://127.0.0.1:8020/streams/$stream_id_1
# If using two renderers:
kubectl exec -n $namespace -c ms avatar-renderer-b-deployment-0 -- curl -X DELETE -s http://127.0.0.1:8021/streams/$stream_id_2
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X DELETE -s http://127.0.0.1:8020/streams/$stream_id_2