1、下载代码
git clone https://github.com/Hangz-nju-cuhk/Talking-Face_PC-AVS.git
或者直接download zip
2、安装环境
官方的环境是python3.6和pytorch1.3.0,由于这是2021年的一个代码,按照官方的安装可能会存在有的库用不了的情况,对于这种时间比较久的代码,我们碰到的大多数问题issues中可能都会有答案,我们去找一找。在issues中搜索requirements找到了一个环境相关的回答,可以作为借鉴。
创建一个conda环境
conda create -n pc-avs python==3.8.10
conda activate pc-avs
下载pytorch
pytoch下载地址:PyTorch
根据issues中的环境,选择这个版本
conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 pytorch-cuda=11.7 -c pytorch -c nvidia
安装requirements.txt
pytorch已经安装了,requirements.txt暂时需要这几个
pip install -r requirements.txt
3、模型下载
项目中给出了模型下载地址,但是应该是需要科学上网。
模型下载后解压到./checkpoints/demo中,解压后应该是这样:
4、数据准备
代码在misc目录下给出了demo数据,将mics目录下的所有zip文件解压,得到的目录包含以下文件:
demo.csv是推理时要用到的参数,主要是指明了推理所用到的数据。结构如下:
其中:
misc/Input/517600055 表示要驱动的原图像
1 表示原图像一张
misc/Pose_Source/517600078 表示姿势图像
160 表示160张姿势图像
misc/Audio_Source/681600002.mp3 表示要驱动的音频
misc/Mouth_Source/681600002 表示音频所对应的嘴型图像
363 表示嘴型图像363张
5、推理
linux系统直接可以使用
windows系统:
inference中有些命令cp等是linux中才使用的,稍微改造一下inference.py如下:
import os
import sys
import subprocess
sys.path.append('..')
from options.test_options import TestOptions
import torch
from models import create_model
import data
import util.util as util
from tqdm import tqdm
def video_concat(processed_file_savepath, name, video_names, audio_path):
cmd = ['ffmpeg']
num_inputs = len(video_names)
for video_name in video_names:
cmd += ['-i', os.path.join(processed_file_savepath, video_name + '.mp4')]
cmd += ['-filter_complex', f"hstack=inputs={num_inputs}",
os.path.join(processed_file_savepath, name + '.mp4'), '-loglevel', 'error', '-y']
subprocess.run(cmd, shell=True)
video_add_audio(name, audio_path, processed_file_savepath)
def video_add_audio(name, audio_path, processed_file_savepath):
subprocess.run(['copy', audio_path, processed_file_savepath], shell=True)
cmd = ['ffmpeg', '-i', os.path.join(processed_file_savepath, name + '.mp4'),
'-i', audio_path,
'-q:v', '0',
'-strict', '-2',
os.path.join(processed_file_savepath, 'av' + name + '.mp4'),
'-loglevel', 'error', '-y']
subprocess.run(cmd, shell=True)
def img2video(dst_path, prefix, video_path):
cmd = ['ffmpeg', '-i', os.path.join(video_path, prefix + '%d.jpg'),
'-q:v', '0', os.path.join(dst_path, prefix + '.mp4'), '-loglevel', 'error', '-y']
subprocess.run(cmd, shell=True)
def inference_single_audio(opt, path_label, model):
#
opt.path_label = path_label
dataloader = data.create_dataloader(opt)
processed_file_savepath = dataloader.dataset.get_processed_file_savepath()
idx = 0
if opt.driving_pose:
video_names = ['Input_', 'G_Pose_Driven_', 'Pose_Source_', 'Mouth_Source_']
else:
video_names = ['Input_', 'G_Fix_Pose_', 'Mouth_Source_']
is_mouth_frame = os.path.isdir(dataloader.dataset.mouth_frame_path)
if not is_mouth_frame:
video_names.pop()
save_paths = []
for name in video_names:
save_path = os.path.join(processed_file_savepath, name)
util.mkdir(save_path)
save_paths.append(save_path)
for data_i in tqdm(dataloader):
fake_image_original_pose_a, fake_image_driven_pose_a = model.forward(data_i, mode='inference')
for num in range(len(fake_image_driven_pose_a)):
util.save_torch_img(data_i['input'][num], os.path.join(save_paths[0], video_names[0] + str(idx) + '.jpg'))
if opt.driving_pose:
util.save_torch_img(fake_image_driven_pose_a[num],
os.path.join(save_paths[1], video_names[1] + str(idx) + '.jpg'))
util.save_torch_img(data_i['driving_pose_frames'][num],
os.path.join(save_paths[2], video_names[2] + str(idx) + '.jpg'))
else:
util.save_torch_img(fake_image_original_pose_a[num],
os.path.join(save_paths[1], video_names[1] + str(idx) + '.jpg'))
if is_mouth_frame:
util.save_torch_img(data_i['target'][num],
os.path.join(save_paths[-1], video_names[-1] + str(idx) + '.jpg'))
idx += 1
if opt.gen_video:
for i, video_name in enumerate(video_names):
img2video(processed_file_savepath, video_name, save_paths[i])
video_concat(processed_file_savepath, 'concat', video_names, dataloader.dataset.audio_path)
print('results saved...' + processed_file_savepath)
del dataloader
return
def main():
opt = TestOptions().parse()
opt.isTrain = False
torch.manual_seed(0)
model = create_model(opt).cuda()
model.eval()
with open(opt.meta_path_vox, 'r') as f:
lines = f.read().splitlines()
for clip_idx, path_label in enumerate(lines):
try:
assert len(path_label.split()) == 8, path_label
inference_single_audio(opt, path_label, model)
except Exception as ex:
import traceback
traceback.print_exc()
print(path_label + '\n')
print(str(ex))
if __name__ == '__main__':
main()
在运行前可能会显示缺少lws,pip一下就行
pip install lws
推理使用命令:
set meta_path_vox=./misc/demo.csv
python -u inference.py --name demo --meta_path_vox %meta_path_vox% --dataset_mode voxtest --netG modulate --netA resseaudio --netA_sync ressesync --netD multiscale --netV resnext --netE fan --model av --gpu_ids 0 --clip_len 1 --batchSize 16 --style_dim 2560 --nThreads 4 --input_id_feature --generate_interval 1 --style_feature_loss --use_audio 1 --noise_pose --driving_pose --gen_video --generate_from_audio_only
结果保存在results中: