让TA说话 - 图片、动画、语音相结合

如何让图片开口说话,或者让视频里的人换一段话?在抖音上有很多大神做的视频非常秀,能让美国总统说中文,嘴形都是对应的,音色也是对应的。还有一些软件,上传一个图片就能让人物说话,比如这个:D-ID。我调研的这块并不多,sd wed UI有SadTalker,我仅仅调研了两类,一种是通过一张图构建一个数字人形象,然后对口型,再加上一些动作幅度,比如眨眼睛和点头等;另一种就是对口型。

CSDN传视频真是太阴间了,都扭曲了。因为怕版权纠纷,我就不放修改后的影视作品了。并且我不想出境,所以我就不放自己的录制的视频了。Wav2Lip+GFPGAN的效果很好,达到了商用级别。很容易上手,十几分钟就能跑起代码,你们自己去试试吧。

SadTalker

stable diffusion有一个插件SadTalker,输入一个图片和一段音频,可以让图中人物说起话来,并且有一定的动作幅度。SadTalker的界面如下:

我们来测试一下SadTalker的能力,我们首先生成一场人物图,我这里使用的模型是majic,如图:

SadTalker仅仅只是对头部做处理,预处理选择“裁剪”,就是只保留头部,勾选GFPGAN面部赠强,效果如下,我们可以看到嘴形基本都对应上了,但是脸前后有一定的变形。(csdn视频扭曲)

(csdn视频扭曲)

如果预处理选择“完整”,就是头部处理结束之后,再拼接到整个图像中,可以看到头部基本就是和上面的一样。效果很差,拼接部分的马尾辫都对应不上,只有头部在动身体不动,非常诡异。(csdn视频扭曲)

(csdn视频扭曲)

SadTalker安装

sd web UI以插件的方式安装SadTalker,使用秋叶大神的整合包的话,只需要在版本管理这里安装新扩展,搜SadTalker就有。也可以在启动之后,从UI中的“扩展”这里,输入githup网址安装。安装之后需要下载模型,在sd目录extensions\SadTalker\scripts下面有download_models.sh,windows不能直接运行sh,可以记事本打开这个文件,然后从里面一一下载并放到对应的目录。这些文件都是从git下载的,挂科学上网下载速度会比较快,不然会等很久。

AnimateDiff+wav2lip

之前介绍了AnimateDiff生成动画,我们在之前AnimateDiff的基础之上让动画开口说话,之前AnimateDiff的内容在我之前的博客中。这里使用到的技术是wav2lip,它俗称对口型模型,通过名字也能看出就是把声音应用到嘴唇上。git网址:https://github.com/Rudrabha/Wav2Lip

git上也有模型的链接,下载后放到对应的目录即可。这里建议用conda做一个虚拟镜像,后面的GFPGAN也用这个环境就行。

有了之前AnimateDiff生成的动画之后,我们还需要准备一段音频,这里我们可以自己录制,也可以去找一个在线的文字转语音工具,比如这个:文字转语音-在线AI转换官网

注意,我们AnimateDiff生成动画时候选择输出格式为mp4,并且参数配置闭环这里选择A,也就是尽量保证第一帧和最后一帧一样。因为声音和动画的长度一般是不对应的,语音较长时wav2lip会重复使用动画,如果动画闭环的话,看起来会流畅些,我这里设置的是16帧,有些卡顿。由于这份代码不带脸部增强,所以脸有些模糊。

动画斗地主

上面的SadTalker使用了GFPGAN,我们也使用这个方法做脸部增强,代码和模型直接从githup上下载就行:
https://github.com/TencentARC/GFPGAN/tree/master

GFPGAN的输入输出是图片,所以这里还需要视频拆帧,然后一张图一张图的送到GFPGAN,最后再组合起来,我用ChatGPT写了拆帧的脚本,和组合的脚本,拆帧脚本输入是MP4视频如下:

def extract_frames(video_path, output_folder):
    # Open the video file
    vidcap = cv2.VideoCapture(video_path)
    fps = vidcap.get(cv2.CAP_PROP_FPS)
    print(f"Video frame rate: {fps} fps")
    success, image = vidcap.read()
    count = 0

    # Iterate through video frames
    while success:
        # Save frame as JPEG file
        frame_path = os.path.join(output_folder, f"frame_{count}.jpg")
        cv2.imwrite(frame_path, image)
        success, image = vidcap.read()
        count += 1

再合并为视频比较麻烦,大家可以自己写脚本,需要输入的东西有之前的wav音频、图片帧、和帧率fps,帧率就是上个脚本打印的数值,一定要注意我这个代码中加载图片的时候是错误的,我懒得修改了就用的屏蔽的那一行,我用ChatGPT写的脚本如下:

def combine_audio_video(audio_path, frames_folder, fps, output_path):
    # Load audio file
    audio = AudioFileClip(audio_path)
    # Load frames
    frame_files = sorted(os.listdir(frames_folder)) #注意这里排序是错误的,需要修改
    # frame_files = [f"frame_{count}.jpg" for count in range(30)]
    frames = [ImageClip(os.path.join(frames_folder, f)).set_duration(1/fps)
              for f in frame_files]

    # Combine audio and frames into video
    video = concatenate_videoclips(frames, method="compose")
    video = video.set_audio(audio)

    # Write video to output file
    video.write_videofile(output_path, fps=fps)

这是增强之后效果,脸部看着好多了:

漫画增强

我这里还用AnimateDiff做了一个真人风格的动画,由于时间太长,我就用了8帧的帧率,太卡顿了,然后使用wav2lip,不使用GFPGAN的效果如下:

人斗地主

使用GFPGAN脸部增强之后,效果如下:

真人增强

wav2lip+GFPGAN的效果是很好的,上面都是AnimateDiff的劣质视频做的,效果不好
 

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值