字节跳动云原生

如何基于火山引擎弹性容器快速部署 MagicAnimate 应用

Image

火山引擎弹性容器实例(VCI)是一种 Serverless 和容器化的计算服务,旨在帮助企业控制云成本、专注于构建应用本身。

来源 | 火山引擎云原生团队

近日,字节跳动和新加坡国立大学联合推出了一款“人体图像动画生成工具”MagicAnimate,它能够根据用户指定的人物图片和动作序列,生成对应的动效视频。简单来说,用户只需提供一张人物照片,再配合骨骼动画引导,就能生成自然的动画视频,如下图所示:

Image

根据相关论文 MagicAnimate: Temporally Consistent Human Image Animation using Diffusion Model 介绍,MagicAnimate 在 TikTok 舞蹈数据集上,生成的视频保真度比最强基线提高了超过 38%。

目前,MagicAnimate 已在 GitHub 正式开源(地址:github.com/magic-research/magic-animate),为了方便更多企业用户体验,本文将按以下步骤,介绍如何通过火山引擎弹性容器实例 VCI 快速拉起 MagicAnimate 应用,部署属于你的 AI 动画生成工具。
  • 构建容器镜像

  • 制作 VCI 容器镜像缓存

  • 通过 VCI 部署 magic-animate 应用

  • 浏览器请求测试效果

什么是 VCI

这一年以来,AIGC 模型在技术和成果上的突破令业界激动无比,但是对于模型开发者和相关企业来说,模型的商业部署应用仍然是首要问题。

火山引擎弹性容器实例(VCI)是一种 Serverless 和容器化的计算服务,它旨在帮助企业控制云成本、专注于构建应用本身——无需购买和管理底层云服务器等基础设施,仅为容器实际运行消耗的资源付费。

面对 AIGC 应用部署场景,VCI 能快速拉起实例,在流量高峰时快速扩充新资源,在流量低谷时进行缩容,保障企业资源完全按需使用,天然适合帮助 AIGC 类应用应对潮汐流量和突发流量请求。

构建容器镜像

首先,我们需要下载模型:
python3from huggingface_hub import snapshot_downloadsnapshot_download(repo_id="runwayml/stable-diffusion-v1-5",local_dir="/root/magic-animate/sdv15")snapshot_download(repo_id="stabilityai/sd-vae-ft-mse",local_dir="/root/magic-animate/vae")snapshot_download(repo_id="zcxu-eric/MagicAnimate",local_dir="/root/magic-animate/MagicAnimate")

将相关模型放到项目的 pretrained_models 目录下,目录结构 Dockerfile 如下所示(此处省略具体镜像制作过程),同时将模型也打包到容器镜像中。

可用镜像地址:paas-cn-beijing.cr.volces.com/aigc/magic-animate:v1
FROM paas-cn-beijing.cr.volces.com/cuda/cuda:11.4.3-devel-ubuntu20.04-torch
LABEL org.opencontainers.image.authors="[email protected]"RUN apt-get update && apt-get install -y git RUN git clone https://github.com/magic-research/magic-animate.git && cd magic-animate && pip3 install -r requirements.txtCOPY demo/gradio_animate.py magic-animate/demo/RUN mkdir -p magic-animate/pretrained_models COPY pretrained_models magic-animate/pretrained_modelsWORKDIR magic-animateCMD ["python3","-m","demo.gradio_animate"]

需要修改的demo/gradio_animate.py如下,制作容器镜像时会将该文件覆盖项目原有的相同名称的文件,达到修改监听地址的目的。

# Copyright 2023 ByteDance and/or its affiliates.## Copyright (2023) MagicAnimate Authors## ByteDance, its affiliates and licensors retain all intellectual# property and proprietary rights in and to this material, related# documentation and any modifications thereto. Any use, reproduction,# disclosure or distribution of this material and related documentation# without an express license agreement from ByteDance or# its affiliates is strictly prohibited.import argparseimport imageioimport numpy as npimport gradio as grfrom PIL import Image
from demo.animate import MagicAnimate
animator = MagicAnimate()
def animate(reference_image, motion_sequence_state, seed, steps, guidance_scale): return animator(reference_image, motion_sequence_state, seed, steps, guidance_scale)
with gr.Blocks() as demo:
gr.HTML( """ <div style="display: flex; justify-content: center; align-items: center; text-align: center;"> <a href="https://github.com/magic-research/magic-animate" style="margin-right: 20px; text-decoration: none; display: flex; align-items: center;"> </a> <div> <h1 >MagicAnimate: Temporally Consistent Human Image Animation using Diffusion Model</h1> <h5 style="margin: 0;">If you like our project, please give us a star ✨ on Github for the latest update.</h5> <div style="display: flex; justify-content: center; align-items: center; text-align: center;> <a href="https://arxiv.org/abs/2311.16498"><img src="https://img.shields.io/badge/Arxiv-2311.16498-red"></a> <a href='https://showlab.github.io/magicanimate'><img src='https://img.shields.io/badge/Project_Page-MagicAnimate-green' alt='Project Page'></a> <a href='https://github.com/magic-research/magic-animate'><img src='https://img.shields.io/badge/Github-Code-blue'></a> </div> </div> </div> """) animation = gr.Video(format="mp4", label="Animation Results", autoplay=True) with gr.Row(): reference_image = gr.Image(label="Reference Image") motion_sequence = gr.Video(format="mp4", label="Motion Sequence") with gr.Column(): random_seed = gr.Textbox(label="Random seed", value=1, info="default: -1") sampling_steps = gr.Textbox(label="Sampling steps", value=25, info="default: 25") guidance_scale = gr.Textbox(label="Guidance scale", value=7.5, info="default: 7.5") submit = gr.Button("Animate")
def read_video(video): reader = imageio.get_reader(video) fps = reader.get_meta_data()['fps'] return video def read_image(image, size=512): return np.array(Image.fromarray(image).resize((size, size))) # when user uploads a new video motion_sequence.upload( read_video, motion_sequence, motion_sequence ) # when `first_frame` is updated reference_image.upload( read_image, reference_image, reference_image ) # when the `submit` button is clicked submit.click( animate, [reference_image, motion_sequence, random_seed, sampling_steps, guidance_scale], animation )
# Examples gr.Markdown("## Examples") gr.Examples( examples=[ ["inputs/applications/source_image/monalisa.png", "inputs/applications/driving/densepose/running.mp4"], ["inputs/applications/source_image/demo4.png", "inputs/applications/driving/densepose/demo4.mp4"], ["inputs/applications/source_image/0002.png", "inputs/applications/driving/densepose/demo4.mp4"], ["inputs/applications/source_image/dalle2.jpeg", "inputs/applications/driving/densepose/running2.mp4"], ["inputs/applications/source_image/dalle8.jpeg", "inputs/applications/driving/densepose/dancing2.mp4"], ["inputs/applications/source_image/multi1_source.png", "inputs/applications/driving/densepose/multi_dancing.mp4"], ], inputs=[reference_image, motion_sequence], outputs=animation, )

demo.launch(server_name='0.0.0.0')#修改监听地址,默认为127.0.0.1

制作 VCI 容器镜像缓存

与传统应用相比,AIGC 类应用具有容器镜像大的明显特征,通常在 10GB 以上。在不加速的情况下,10 GB 以上容器镜像的拉取用时较久,再加上在弹性场景,拉取镜像是非常频繁的操作,这会大幅延长 GPU 资源不可用时间,造成 GPU 资源浪费。

火山引擎提供镜像加速方案,可以将镜像拉取用时从分钟级降低到秒级,帮助用户大幅提升效率(详见《AIGC 推理加速:火山引擎镜像加速实践》)。这里我们直接使用加速效果最好的镜像缓存方案。

通过火山引擎控制台,我们可以非常快速地制作容器镜像缓存,极大提升镜像拉取速度。

Image

通过 VCI 部署 magic-animate 应用

使用 YAML 方式部署
apiVersion: apps/v1kind: Deploymentmetadata:  name: magic-animate  namespace: defaultspec:  progressDeadlineSeconds: 600  replicas: 1  revisionHistoryLimit: 10  selector:    matchLabels:      app: magic-animate  strategy:    rollingUpdate:      maxSurge: 25%      maxUnavailable: 25%    type: RollingUpdate  template:    metadata:      annotations:        vci.vke.volcengine.com/preferred-instance-types: vci.ini2.26c-243gi        vke.volcengine.com/burst-to-vci: enforce      creationTimestamp: null      labels:        app: magic-animate    spec:      containers:      - image: paas-cn-beijing.cr.volces.com/aigc/magic-animate:v1        imagePullPolicy: IfNotPresent        name: app        resources:          limits:            nvidia.com/gpu: "1"        terminationMessagePath: /dev/termination-log        terminationMessagePolicy: File      dnsPolicy: ClusterFirst      nodeSelector:        kubernetes.io/hostname: vci-node1-cn-beijing-b      restartPolicy: Always      schedulerName: default-scheduler      securityContext: {}      terminationGracePeriodSeconds: 30
创建服务供请求访问
apiVersion: v1kind: Servicemetadata:  annotations:    service.beta.kubernetes.io/volcengine-loadbalancer-address-type: PUBLIC    service.beta.kubernetes.io/volcengine-loadbalancer-bandwidth: "10"    service.beta.kubernetes.io/volcengine-loadbalancer-eip-billing-type: "3"    service.beta.kubernetes.io/volcengine-loadbalancer-health-check-flag: "off"    service.beta.kubernetes.io/volcengine-loadbalancer-ip-version: ipv4    service.beta.kubernetes.io/volcengine-loadbalancer-isp-type: BGP    service.beta.kubernetes.io/volcengine-loadbalancer-name: magic-animate-lb    service.beta.kubernetes.io/volcengine-loadbalancer-pass-through: "true"    service.beta.kubernetes.io/volcengine-loadbalancer-scheduler: wrr    service.beta.kubernetes.io/volcengine-loadbalancer-spec: small_1    service.beta.kubernetes.io/volcengine-loadbalancer-subnet-id: subnet-mjn0iia7j6yo5smt1a9fcz5v  name: magic-animate-svc  namespace: defaultspec:  allocateLoadBalancerNodePorts: true  externalTrafficPolicy: Local  internalTrafficPolicy: Cluster  ipFamilies:  - IPv4  ipFamilyPolicy: SingleStack  ports:  - port: 80    protocol: TCP    targetPort: 7860  selector:    app: magic-animate  sessionAffinity: None  type: LoadBalancer

浏览器请求测试效果

我们使用步骤三中创建服务获取到的公网 IP,浏览器访问 http://${公网ip} 就可以请求到我们的 Web 界面。

Image

我们选择原始图片和 Motion Sequence,等待生成视频。视频生成完成后点击播放查看效果。

Image

至此基于火山引擎弹性容器部署 magic-animate 应用已经完成。

小结

回望 2023 年,大模型和 AIGC 已经开始进行初期的商业化探索,慢慢脱虚向实,走向产业落地。到 2024 年,这一趋势势必将进一步加速。

根据 Gartner 对于未来生成式 AI 的预测,到 2026 年,超过 80% 的企业都会接入生成式 AI 或大模型。而这种变化不会局限在单一技术,也会反映在企业架构之上。

面对这一趋势,火山引擎云原生团队依托字节跳动云原生技术实践和企业服务经验,正在不断迭代和创新解决方案,以提供更高稳定性和更弹性的云原生 AI 基建,帮助企业不断降低 AI 技术开发和应用的门槛。

Image

扫码咨询

- END -
相关链接
[1] 火山引擎: www.volcengine.com
[2] 火山引擎 VKE: www.volcengine.com/product/vke
[3] 如何在火山引擎云上部署 Stable Diffusion
[4] 如何在火山引擎云上部署 Langchain-ChatGLM 
[5] AIGC 推理加速:火山引擎镜像加速实践
火山引擎云原生团队

火山引擎云原生团队主要负责火山引擎公有云及私有化场景中 PaaS 类产品体系的构建,结合字节跳动多年的云原生技术栈经验和最佳实践沉淀,帮助企业加速数字化转型和创新。产品包括容器服务、镜像仓库、分布式云原生平台、函数服务、服务网格、持续交付、可观测服务等。

Image
Image

Image