在实际开发中,因为原始项目https://github.com/OpenTalker/SadTalker暂时不提供api调用方式运行,所以有了这个文章。

SadTalker 是一个使用静态人物图片与音频文件自动合成人物说话的视频动画开源模型。它从音频中生成 3DMM(3D Morphable Model,三维可变形模型)运动系数,包括头部姿势和表情等信息,通过对音频特征的分析和学习,将其转化为人物头部与面部的运动参数,并映射到面部渲染器的三维关键点空间,以生成最终的视频。该模型支持中英文在内的多种语言,根据自己的需求进行参数定制和调整,获得符合自己期望的视频动画效果。在内容创作、智能交互、情感分析和表达等诸多领域有着广泛的应用。
首先调用 init_path 函数对模型做初始化操作,model_sad_talker_path 参数为模型的 checkpoints 路径,第二个参数为模型配置路径,size 参数为控制程序在进行面部渲染时生成图像的大小,preprocess 参数为用户选择的预处理方法调整输入图像的尺寸、内容或边界。接下来构造了三个模型对象:Audio2Coeff 为将音频转换成系数的对象,CropAndExtract 为裁剪并提取特征的对象,AnimateFromCoeff 为从系数生成动画的对象,cuda 参数表示指定使用 CUDA 支持的 GPU 进行处理。
from utils.sad_talker.src.utils.init_path import init_path
from utils.sad_talker.src.test_audio2coeff import Audio2Coeff
from utils.sad_talker.src.utils.preprocess import CropAndExtract
from utils.sad_talker.src.facerender.animate import AnimateFromCoeff
path = init_path(
model_sad_talker_path,
os.path.join(os.path.split(sys.argv[0])[0], config_dir),
size,
None,
preprocess
)
audio_to_coeff = Audio2Coeff(path, 'cuda')
preprocess_model = CropAndExtract(path, 'cuda')
animate_from_coeff = AnimateFromCoeff(path, 'cuda')
接下来调用 preprocess_model 对象的 generate 方法来对图片提取 3DMM 运动系数, pic_path 参数为图片素材的存放路径, frame_dir 参数为处理帧的存放路径,preprocess 参数为调整输入图像的尺寸、内容或边界的预处理参数,source_image_flag=True 标记是否使用源图像, pic_size=size 为指定图片的尺寸大小。
first_coeff_path, crop_pic_path, crop_info = preprocess_model.generate(
pic_path,
frame_dir,
preprocess,
source_image_flag=True,
pic_size=size
)
再然后是调用 audio_to_coeff 对象的 generate 方法来对音频数据进行处理,其中 get_data 方法用于获取音频数据,该方法的 first_coeff_path 参数为初始系数路径, audio_path 参数为传入的音频文件存放路径,device 参数为设备类型,可以是 CPU 或 CUDA 支持的 GPU, still 参数用于控制生成视频时头部运动的幅度。audio_to_coeff 对象的 generate 方法的 save_dir 参数指定了保存结果的路径, pose_style 参数允许用户根据需求选择不同的姿势风格参与到程序的处理或生成任务中。
coeff_path = audio_to_coeff.generate(
get_data(first_coeff_path, audio_path, device, None, still),
save_dir,
pose_style,
None
)
接下来调用 animate_from_coeff 对象的 generate 方法来生成视频动画。其中 get_facerender_data 方法用于获取面部渲染数据,coeff_path 参数为前面生成的系数路径,crop_pic_path 参数为裁剪后图片路径,first_coeff_path 参数为初始系数路径,audio_path 参数为音频文件路径, batch_size 参数为批处理大小,expression_scale 参数为表情缩放比例, still_mode 参数指定人物头部运动幅度,preprocess 参数限制图像的尺寸、内容或边界,size 参数为渲染结果尺寸。animate_from_coeff 对象的 generate 方法的第二个参数 save_dir 指定保存结果的目录,pic_path 参数为输入图片素材的路径,crop_info 参数为裁剪图片的信息, enhancer 参数为增强器, background_enhancer 参数为背景增强器。
result = animate_from_coeff.generate(
get_facerender_data(
coeff_path,
crop_pic_path,
first_coeff_path,
audio_path,
batch_size,
None,
None,
None,
expression_scale=expression_scale,
still_mode=still,
preprocess=preprocess,
size=size
),
save_dir,
pic_path,
crop_info,
enhancer='gfpgan',
background_enhancer=background_enhancer,
preprocess=preprocess,
img_size=size
)
基于对SadTalker原有扩展和前面api教程的理解,重新编写api代码。
在SadTalker扩展目录的./scripts创建api.py
代码如下:
from fastapi import FastAPI, Body
from modules.api.models import *
from modules.api import api
import gradio as gr
import base64, os, uuid
from src.gradio_demo import SadTalker
# models = [
# "None",
# "u2net",
# "u2netp",
# "u2net_human_seg",
# "u2net_cloth_seg",
# "silueta",
# ]
def encode_base64(file):
encoded = base64.b64encode(open(file, 'rb').read())
return encoded
def sadtalker_api(_: gr.Blocks, app: FastAPI):
@app.post("/sadtalker")
def sadtalker_gen(
image: str = Body("", title='input image'),
audio: str = Body("", title='input audio'),
size: int = Body(256, title='input video size'),
batch_size: int = Body(2, title='batch size'),
preprocess: str = Body("crop", title='preprocess mode : crop extcrop resize full extfull'),
still_mode: bool = Body(False, title='still mode : no still mode,work with proprocess full'),
exp_scale: float = Body(1.0, title='expression scale : float,default 1.0,0.0 - 3.0'),
use_enhancer: bool = Body(False, title='use enhancer'),
):
# input_image = api.decode_base64_to_image(input_image)
input_image = base64.b64decode(image)
audio_data = base64.b64decode(audio)
file_image = str(uuid.uuid4()) + ".png"
print( "file_image", file_image)
file_audio = str(uuid.uuid4()) + ".wav"
print( "file_audio", file_audio)
with open(file_image, "wb") as fh:
fh.write(input_image)
with open(file_audio, "wb") as fh:
fh.write(audio_data)
print("write data to file")
image_path = os.path.join(os.path.abspath('.'), file_image)
audio_path = os.path.join(os.path.abspath('.'), file_audio)
sad_talker = SadTalker(checkpoint_path="extensions/SadTalker/checkpoints",
config_path="extensions/SadTalker/src/config", lazy_load=True)
path = sad_talker.test(image_path, audio_path, result_dir="outputs/SadTalker",size=size,
batch_size=batch_size,preprocess=preprocess,use_enhancer=use_enhancer,
still_mode=still_mode,exp_scale=exp_scale)
return {"video": encode_base64(path.replace("./", ""))}
# return {"video": "1111111"}
try:
import modules.script_callbacks as script_callbacks
script_callbacks.on_app_started(sadtalker_api)
except:
pass
完成以后重启webui启用api
现在可以使用api调用了
Paragoger衍生者AI训练营。发布者:arnehuo,转载请注明出处:https://www.shxcj.com/archives/9978