视频生成解决方案

EasyAnimate是阿里云PAI平台自主研发的DiT的视频生成框架,它提供了完整的高清长视频生成解决方案,包括视频数据预处理、VAE训练、DiT训练、模型推理和模型评测等。本文为您介绍如何在PAI平台集成EasyAnimate并一键完成模型推理、微调及部署的实践流程。

背景信息

本文为您介绍以下两种视频生成的方式:

  • 方式一:使用DSW

    DSW是为算法开发者量身打造的一站式AI开发平台,集成了JupyterLab、WebIDE、Terminal多种云端开发环境,其中,Gallery提供了丰富的案例和解决方案,帮助您快速熟悉研发流程。您可以打开DSW Gallery中的案例教程,实现一键式运行Notebook,完成基于EasyAnimate的视频生成模型的推理和训练任务,也可以进行模型推理和微调等二次开发操作。

  • 方式二:使用快速开始

    快速开始集成了众多AI开源社区中优质的预训练模型,并且基于开源模型支持零代码实现从训练到部署再到推理的全部过程,您可以通过快速开始一键部署EasyAnimate模型并生成视频,享受更快、更高效、更便捷的AI应用体验。

费用说明

方式

费用说明

方式一:使用DSW

如果您的账号为DSWEAS的新用户,可以免费试用对应产品。关于免费试用的额度、领取方式及注意事项等详细信息,请参见新用户免费试用

说明
  • 在本教程中,仅支持使用DSW免费资源类型ecs.gn7i-c8g1.2xlarge

  • 由于免费试用资源存在资源额度限制,因此无法进行模型训练相关操作。

如果您的账号非新用户,使用DSWEAS会产生相应费用。更多计费详情,请参见交互式建模(DSW)计费说明模型在线服务(EAS)计费说明

方式二:使用快速开始

如果您的账号为DLCEAS的新用户,可以免费试用对应产品。关于免费试用的额度、领取方式及注意事项等详细信息,请参见新用户免费试用

说明

由于免费试用资源存在资源额度限制,因此无法进行模型训练相关操作。

如果您的账号非新用户,使用DLCEAS会产生相应费用。更多计费详情,请参见分布式训练(DLC)计费说明模型在线服务(EAS)计费说明

前提条件

方式一:使用DSW

步骤一:创建DSW实例

  1. 进入DSW页面。

    1. 登录PAI控制台

    2. 概览页面选择目标地域。

    3. 在左侧导航栏单击工作空间列表,在工作空间列表页面中单击目标工作空间名称,进入对应工作空间内。

    4. 在工作空间页面的左侧导航栏选择模型开发与训练>交互式建模(DSW),进入DSW页面。

  2. 单击创建实例

  3. 配置实例向导页面,配置以下关键参数,其他参数保持默认即可。

    参数

    说明

    实例名称

    本教程使用的示例值为:AIGC_test_01

    资源规格

    选择GPU规格下的ecs.gn7i-c8g1.2xlarge,或其他A10、GU100规格。

    镜像

    选择官方镜像easyanimate:1.1.5-pytorch2.2.0-gpu-py310-cu118-ubuntu22.04

    数据集(可选)

    单击添加,单击创建数据集,创建OSSNAS数据集。

  4. 单击确定

步骤二:下载EasyAnimate模型

  1. 单击目标DSW实例操作列下的打开,进入DSW实例的开发环境。

  2. Notebook页签的Launcher页面,单击快速开始区域Tool下的DSW Gallery,打开DSW Gallery页面。

  3. DSW Gallery页面中,搜索基于EasyAnimateAI视频生成示例,单击DSW中打开,即可自动将本教程所需的资源和教程文件下载至DSW实例中,并在下载完成后自动打开教程文件。

    image

  4. 下载EasyAnimate相关代码和模型并进行安装。

    在教程文件easyanimate.ipynb中,单击image运行环境安装节点命令,包括定义函数下载代码下载模型。当成功运行一个步骤命令后,再顺次运行下个步骤的命令。

步骤三:推理模型

  1. 单击image运行模型推理>UI启动节点的命令,进行模型推理。

  2. 单击生成的链接,进入WebUI界面。

    image

  3. WebUI界面选择预训练模型路径,其它参数按需配置即可。

    image

    (可选)如果您希望使用图生视频功能,可以在Image to Video区域上传对应图片,用于生成视频。

    image

  4. 单击Generate(生成),等待一段时间后,即可在右侧查看或下载生成的视频。

    image

步骤四:微调LoRA

EasyAnimate提供了丰富的模型训练方式,包括DiT模型的训练(LoRA微调和基模型的全量微调)和VAE的训练。关于Gallery中内置的LoRA微调部分,更多信息,请参见EasyAnimate

准备数据

单击image执行模型训练>数据准备节点的命令,即可下载示例数据,用于模型训练。您也可以按照如下格式要求自行准备数据文件。

文件数据格式如下。

project/
├── datasets/
│   ├── internal_datasets/
│       ├── videos/
│       │   ├── 00000001.mp4
│       │   ├── 00000002.mp4
│       │   └── .....
│       └── json_of_internal_datasets.json

其中,JSON文件数据格式和参数说明如下。

[
    {
      "file_path": "videos/00000001.mp4",
      "text": "A group of young men in suits and sunglasses are walking down a city street.",
      "type": "video"
    },
    {
      "file_path": "videos/00000002.mp4",
      "text": "A notepad with a drawing of a woman on it.",
      "type": "video"
    }
    .....
]

参数

说明

file_path

视频/图片数据的存放位置(相对路径)。

text

数据的文本描述。

type

视频为video,图片为image

启动训练

  1. (可选)如果您使用自行准备的数据文件进行微调,需要将对应的训练脚本中的DATASET_NAMEDATASET_META_NAME设置为训练数据所在目录及训练文件地址。

    export DATASET_NAME=“” # 训练数据所在目录
    export DATASET_META_NAME=“datasets/Minimalism/metadata_add_width_height.json” # 训练文件地址
  2. 单击image执行启动训练>LoRA训练节点的命令。

  3. 训练完成后,单击image执行LoRA模型推理节点的命令,将训练好的模型移动至EasyAnimate/models/Personalized_Model文件夹。

  4. 单击生成的链接,进入WebUI界面,选择训练好的LoRA模型生成视频。

    image

方式二:使用快速开始

快速开始作为PAI的产品组件,集成了众多AI开源社区中优质的预训练模型,并且基于开源模型支持零代码实现从训练到部署再到推理的全部过程。您可以直接部署模型并使用,也可以根据实际需求微调训练模型后部署使用。

场景一:直接部署模型

  1. 进入快速开始页面。

    1. 登录PAI控制台

    2. 在左侧导航栏单击工作空间列表,在工作空间列表页面单击目标工作空间名称,进入对应工作空间。

    3. 在左侧导航栏单击快速开始,进入快速开始页面。

  2. 在快速开始页面,搜索EasyAnimate 高清长视频生成,然后单击部署,配置相关参数。

    EasyAnimate目前仅支持使用bf16进行推理,请选择A10及其以上的显卡。

    image

  3. 单击部署,在弹出的计费提醒对话框中,单击确定,页面将自动跳转到服务详情页面。

    状态变为运行中时,表示模型部署成功。

  4. 模型部署完成后,您可以使用WebUIAPI两种方式调用服务来生成视频。

    WebUI方式

    1. 服务详情页面,单击查看WEB应用

      image

    2. WebUI界面选择预训练的模型路径,其它参数按需配置即可。

      image

    3. 单击Generate(生成),等待一段时间后,即可在右侧查看或下载生成的视频。

      image

    API方式

    1. 服务详情页面的资源详情区域,单击查看调用信息,获取调用服务所需的信息。

      image

    2. 通过接口更新Transformer模型,可在DSW实例或本地Python环境中执行。

      如果已经在WebUI中选择模型,则无需发送请求重复调用。如遇请求超时,请在EAS日志中确认模型已加载完毕。加载完成,日志中将提示Update diffusion transformer done

      Python请求示例如下。

      import json
      import requests
      
      
      def post_diffusion_transformer(diffusion_transformer_path, url='http://127.0.0.1:7860', token=None):
          datas = json.dumps({
              "diffusion_transformer_path": diffusion_transformer_path
          })
          head = {
              'Authorization': token
          }
          r = requests.post(f'{url}/easyanimate/update_diffusion_transformer', data=datas, headers=head, timeout=15000)
          data = r.content.decode('utf-8')
          return data
      
      def post_update_edition(edition, url='http://0.0.0.0:7860',token=None):
          head = {
              'Authorization': token
          }
      
          datas = json.dumps({
              "edition": edition
          })
          r = requests.post(f'{url}/easyanimate/update_edition', data=datas, headers=head)
          data = r.content.decode('utf-8')
          return data
        
      if __name__ == '__main__':
          url = '<eas-service-url>'
          token = '<eas-service-token>'
      
          # -------------------------- #
          #  Step 1: update edition
          # -------------------------- #
          edition = "v3"
          outputs = post_update_edition(edition,url = url,token=token)
          print('Output update edition: ', outputs)
      
          # -------------------------- #
          #  Step 2: update edition
          # -------------------------- #
          # 默认路径 (二选一)
          diffusion_transformer_path = "/mnt/models/Diffusion_Transformer/EasyAnimateV3-XL-2-InP-512x512"
          # diffusion_transformer_path = "/mnt/models/Diffusion_Transformer/EasyAnimateV3-XL-2-InP-768x768"
          outputs = post_diffusion_transformer(diffusion_transformer_path, url = url, token=token)
          print('Output update edition: ', outputs)

      其中:

      • <eas-service-url>:替换为步骤a中查询到的服务访问地址。

      • <eas-service-token>:替换为步骤a中查询到的服务Token。

    3. 调用服务,生成视频或图片。

    • 服务输入参数说明

      参数名

      说明

      类型

      默认值

      prompt_textbox

      用户输入的正向提示词。

      string

      必填。无默认值

      negative_prompt_textbox

      用户输入的负向提示词。

      string

      "The video is not of a high quality, it has a low resolution, and the audio quality is not clear. Strange motion trajectory, a poor composition and deformed video, low resolution, duplicate and ugly, strange body structure, long and strange neck, bad teeth, bad eyes, bad limbs, bad hands, rotating camera, blurry camera, shaking camera. Deformation, low-resolution, blurry, ugly, distortion."

      sample_step_slider

      用户输入的步数。

      int

      30

      cfg_scale_slider

      引导系数。

      int

      6

      sampler_dropdown

      采样器类型。

      取值包括:Eluer、EluerA、DPM++、PNDM、DDIM

      string

      Eluer

      width_slider

      生成视频宽度。

      int

      672

      height_slider

      生成视频高度。

      int

      384

      length_slider

      生成视频帧数。

      int

      144

      is_image

      是否是图片。

      bool

      FALSE

      lora_alpha_slider

      LoRA模型参数的权重。

      float

      0.55

      seed_textbox

      随机种子。

      int

      43

      lora_model_path

      额外的LoRA模型路径。

      若有,则会在请求时带上lora。在当次请求后移除。

      string

      none

      base_model_path

      需要更新的transformer模型路径。

      string

      none

      motion_module_path

      需要更新的motion_module模型路径。

      string

      none

      generation_method

      生成类型。包括:Video Generation,Image Generation

      string

      none

    • Python请求示例

      服务返回base64_encoding,为base64结果。

      您可以在/mnt/workspace/demos/easyanimate/目录中查看生成结果。

      import base64
      import json
      import sys
      import time
      from datetime import datetime
      from io import BytesIO
      
      import cv2
      import requests
      import base64
      
      def post_infer(generation_method, length_slider, url='http://127.0.0.1:7860',token=None):
          head = {
              'Authorization': token
          }
      
          datas = json.dumps({
              "base_model_path": "none",
              "motion_module_path": "none",
              "lora_model_path": "none", 
              "lora_alpha_slider": 0.55, 
              "prompt_textbox": "This video shows Mount saint helens, washington - the stunning scenery of a rocky mountains during golden hours - wide shot. A soaring drone footage captures the majestic beauty of a coastal cliff, its red and yellow stratified rock faces rich in color and against the vibrant turquoise of the sea.", 
              "negative_prompt_textbox": "Strange motion trajectory, a poor composition and deformed video, worst quality, normal quality, low quality, low resolution, duplicate and ugly, strange body structure, long and strange neck, bad teeth, bad eyes, bad limbs, bad hands, rotating camera, blurry camera, shaking camera", 
              "sampler_dropdown": "Euler", 
              "sample_step_slider": 30, 
              "width_slider": 672, 
              "height_slider": 384, 
              "generation_method": "Video Generation",
              "length_slider": length_slider,
              "cfg_scale_slider": 6,
              "seed_textbox": 43,
          })
          r = requests.post(f'{url}/easyanimate/infer_forward', data=datas, headers=head, timeout=1500)
          data = r.content.decode('utf-8')
          return data
      
      
      if __name__ == '__main__':
          # initiate time
          now_date    = datetime.now()
          time_start  = time.time()  
          
          url = '<eas-service-url>'
          token = '<eas-service-token>'
      
          # -------------------------- #
          #  Step 3: infer
          # -------------------------- #
          # "Video Generation" and "Image Generation"
          generation_method = "Video Generation"
          length_slider = 72
          outputs = post_infer(generation_method, length_slider, url = url, token=token)
          
          # Get decoded data
          outputs = json.loads(outputs)
          base64_encoding = outputs["base64_encoding"]
          decoded_data = base64.b64decode(base64_encoding)
      
          is_image = True if generation_method == "Image Generation" else False
          if is_image or length_slider == 1:
              file_path = "1.png"
          else:
              file_path = "1.mp4"
          with open(file_path, "wb") as file:
              file.write(decoded_data)
              
          # End of record time
          # The calculated time difference is the execution time of the program, expressed in seconds / s
          time_end = time.time()  
          time_sum = (time_end - time_start) % 60 
          print('# --------------------------------------------------------- #')
          print(f'#   Total expenditure: {time_sum}s')
          print('# --------------------------------------------------------- #')

      其中:

      • <eas-service-url>:替换为步骤a中查询到的服务访问地址。

      • <eas-service-token>:替换为步骤a中查询到的服务Token。

场景二:微调训练后部署模型

  1. 进入快速开始页面。

    1. 登录PAI控制台

    2. 在左侧导航栏单击工作空间列表,在工作空间列表页面单击目标工作空间名称,进入对应工作空间内。

    3. 在左侧导航栏单击快速开始,进入快速开始页面。

  2. 在快速开始页面,搜索EasyAnimate 高清长视频生成,单击卡片,进入模型详情页面。

  3. 单击右上角的微调训练,根据业务需求完成训练输出配置、超参数配置等。其中,超参数详情请参见附录:微调模型超参数说明

    EasyAnimate目前仅支持使用bf16进行推理,请选择A10及其以上的显卡。如果使用图片进行LoRA训练,需要最低GPU显存为20 GB。如果您使用更大的batch_size、num_train_epochs使用视频数据进行微调,训练需要消耗更大的显存。

    image

  4. 单击训练,在弹出的计费提醒对话框中,单击确定,页面将自动跳转到服务详情页面。

    任务状态变为成功时,代表模型训练成功。

  5. 单击右上角的部署

    状态变为运行中时,代表模型部署成功。

  6. 服务详情页面,单击查看WEB应用

    image

  7. WebUI界面,选择训练完成的LoRA模型进行视频生成。

    image

附录:微调模型超参数说明

参数名称

类型

含义

learning_rate

float

学习率。

adam_weight_decay

float

Adam优化器的权重衰减值。

adam_epsilon

float

Adam优化器的epsilon值。

num_train_epochs

int

训练总轮数。

checkpointing_steps

int

保存模型的间隔步数。

train_batch_size

int

训练采样的批大小。

vae_mini_batch

int

训练vae的切片大小。

image_sample_size

int

训练图片分辨率。

video_sample_size

int

训练视频分辨率。

video_sample_stride

int

训练视频采样间隔。

video_sample_n_frames

int

训练视频采样帧数。

rank

int

LoRA rank。

network_alpha

int

LoRA nework_alpha。

gradient_accumulation_steps

int

梯度累计步数。

dataloader_num_workers

int

数据加载的子进程数。