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

技术

picture.image

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

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

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

picture.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 类应用应对潮汐流量和突发流量请求。

构建容器镜像

首先,我们需要下载模型:


                          
python3
                          
from huggingface_hub import snapshot_download
                          
snapshot_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="xxx@bytedance.com"
                          
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.txt
                          
COPY demo/gradio_animate.py magic-animate/demo/
                          
RUN mkdir -p magic-animate/pretrained_models 
                          
COPY pretrained_models magic-animate/pretrained_models
                          
WORKDIR magic-animate
                          
CMD ["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 argparse
                          
import imageio
                          
import numpy as np
                          
import gradio as gr
                          
from 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 推理加速:火山引擎镜像加速实践》)。这里我们直接使用加速效果最好的 镜像缓存方案

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

picture.image

通过 VCI 部署 magic-animate 应用

使用 YAML 方式部署


                          
apiVersion: apps/v1
                          
kind: Deployment
                          
metadata:
                          
  name: magic-animate
                          
  namespace: default
                          
spec:
                          
  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: v1
                          
kind: Service
                          
metadata:
                          
  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: default
                          
spec:
                          
  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 界面。

picture.image

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

picture.image

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

小结

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

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

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

picture.image

扫码咨询

  • END -

相关链接

[1] 火山引擎: www.volcengine.com

[2] 火山引擎 VKE: www.volcengine.com/product/vke

[3] 如何在火山引擎云上部署 Stable Diffusion

[4] 如何在火山引擎云上部署 Langchain-ChatGLM

[5] AIGC 推理加速:火山引擎镜像加速实践

火山引擎云原生团队

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

picture.image

picture.image

picture.image

87
0
0
0
关于作者
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论