虚拟人项目系统软件结构框架图
如下:
源代码由三部分组成:
1)paddle 引擎以及papache2下载安装部署说明。安装需要LINUX操作系统。 paddle 引擎 安装的根目录为/home/PaddleGAN
2)python 语言接口程序,需要运行在 python3.8及以上 版本。
本接口代码又两个程序组成,分别是住程序run.py 和守护程序run2.py都需要部署在 /var/www/html/ 目录下.
- PHP语言开发的前台操作界面程序。本界面源码文件/var/www/html/index.php 中。需要 PHP服务程序支持。本项目使用了apache2作为php服务,apache2根目录是/var/www/html/
具体文档如下:
一. paddle 引擎以及papache2下载安装部署说明:
#####################################################################
第一步 Paddle 引擎安装过程说明。
docker pull paddlepaddle/paddle:2.4.1-gpu-cuda11.7-cudnn8.4-trt8.4
apt-get install -y vim 安装文本编辑工具VIM
安装git 工具 用来下载代码
apt-get update -y 先跟新apt, 将来用APT 安装git.
apt-get upgrade -y
apt install git
========================================
下载代码
git clone https://gitee.com/paddlepaddle/PaddleGAN.git
cd PaddleGAN
git checkout develop
# 安装所需安装包
pip install -r requirements.txt
==========================================
执行功能,用来测试安装。 确保
export PYTHONPATH=$PYTHONPATH:/home/PaddleGAN && python /home/PaddleGAN/applications/tools/wav2lip.py –face /home/paddle/input/picture.jpeg –audio /home/paddle/system/temp.wav –outfile /home/paddle/output/output2.mp4
=================================================
错误 提示:ImportError: libGL.so.1: cannot open shared object file: No such file or directory
解决:apt install libgl1-mesa-glx
========================================
ImportError: libgthread-2.0.so.0: cannot open shared object file: No such file or directory解决方法
apt-get install libglib2.0-dev 解决
=======================================
OSError: cannot load library ‘libsndfile.so’: libsndfile.so: cannot open shared object file: No such file or directory
apt install libsndfile1
=====================================================
/bin/sh: 1: ffmpeg: not found
sudo apt install ffmpeg
#####################################################################
第二步 安装 文字转语言 tts
pip install paddlespeech
安装 nltk , 找到 nltk.data 路径
pip install nltk
# python
>>> import nltk
>>> nltk.data.path
wget -P data https://paddlespeech.bj.bcebos.com/Parakeet/tools/nltk_data.tar.gz
tar zxvf data/nltk_data.tar.gz
功能测试
paddlespeech tts –am fastspeech2_aishell3 –voc hifigan_aishell3 –input “你好,欢迎使用百度 飞桨深度学习框架!” –spk_id 167 –output /home/paddle/output/temp2.wav
paddlespeech tts –am fastspeech2_aishell3 –voc hifigan_aishell3 –input “/home/paddle/input/msg.txt” –spk_id 167 –output /home/paddle/temp.wav
安装 C++ 编译环境
sudo apt install build-essential
conda update conda //好像没有跟新这个。
# 安装 develop 版本
pip install paddlepaddle==0.0.0 -f https://www.paddlepaddle.org.cn/whl/linux/cpu-mkl/develop.html
pip install paddlespeech //这次会安装成功
再次 功能测试
paddlespeech tts –am fastspeech2_aishell3 –voc hifigan_aishell3 –input “你好0307,锄禾日当午000,汗滴禾下土品牌,谁知盘中餐,粒粒皆辛苦!” –spk_id 1 –output /home/paddle/input/test.wav
////下面是其他可能用的到的安装命令。
安装命令:
pip install scikit-image
(skimage即是Scikit-Image。基于python脚本语言开发的数字图片处理包,直接pip安装就可以)
这是由于环境中缺少了tqdm进度条的安装包,需要使用conda或者pip命令进行安装。
三、解决方案
安装命令如下:
pip install tqdm
=======================
OSError: cannot load library ‘libsndfile.so
解决方案
apt install libsndfile1
///////////////////////////////////////
关闭防火墙命令:
ufw disable
安装SFTP 命令
apt install vsftpd
查看状态
# service vsftpd status
启动
service vsftpd start
/////////////////////////////////////////
[nltk_data] ror loading 报错卡死问题
import nltk
nltk.data.path 找到 nltk_data 目录把包拷贝进去就OK了
#####################################################################
第三步 安装apache////////////////////////////////////////////////////////////
sudo apt-get update
sudo apt-get install apache2
apt install vim
修改它的监听端口
sudo vim /etc/apache2/ports.conf
修改它的主机端口
sudo vim /etc/apache2/sites-available/000-default.conf
(3)apache2 的几个简单命令:启动、停止、重启、状态
sudo /etc/init.d/apache2 start | stop | restart | status ]
service apache2 start stop | restart | status ]
(4)重启apache2 并查看状态
sudo /etc/init.d/apache2 start
sudo /etc/init.d/apache2 status
————————————————
安装PHP服务程序/////////////////////////////////////////////////////////////
php -v 查看版本号。检查php是否安装
sudo apt-get install php
vim /etc/apache2/apache2.conf
末尾添加:
AddType application/x-httpd-php .php .htm .html
Aapache2 安装完毕
- 有python 语言接口程序
a.主程序源代码,文件名run.py
import os
# 使用os.system()
os.system(“export PYTHONPATH=$PYTHONPATH:/home/PaddleGAN “)
import argparse
import paddle
from ppgan.apps.first_order_predictor import FirstOrderPredictor
parser = argparse.ArgumentParser()
parser.add_argument(“–config”, default=None, help=”path to config”)
parser.add_argument(“–weight_path”,
default=None,
help=”path to checkpoint to restore”)
parser.add_argument(“–source_image”, type=str, help=”path to source image”)
parser.add_argument(“–driving_video”, type=str, help=”path to driving video”)
parser.add_argument(“–output”, default=’output’, help=”path to output”)
parser.add_argument(“–filename”,
default=’result.mp4′,
help=”filename to output”)
parser.add_argument(“–relative”,
dest=”relative”,
action=”store_true”,
default=”relative”,# 添加
help=”use relative or absolute keypoint coordinates”)
parser.add_argument(
“–adapt_scale”,
dest=”adapt_scale”,
action=”store_true”,
default=”adapt_scale”, #添加
help=”adapt movement scale based on convex hull of keypoints”)
parser.add_argument(
“–find_best_frame”,
dest=”find_best_frame”,
action=”store_true”,
help=
“Generate from the frame that is the most alligned with source. (Only for faces, requires face_aligment lib)”
)
parser.add_argument(“–best_frame”,
dest=”best_frame”,
type=int,
default=None,
help=”Set frame to start from.”)
parser.add_argument(“–cpu”, dest=”cpu”, action=”store_true”, help=”cpu mode.”)
parser.add_argument(“–ratio”,
dest=”ratio”,
type=float,
default=0.4,
help=”margin ratio”)
parser.add_argument(
“–face_detector”,
dest=”face_detector”,
type=str,
default=’sfd’,
help=”face detector to be used, can choose s3fd or blazeface”)
parser.add_argument(“–multi_person”,
dest=”multi_person”,
action=”store_true”,
default=False,
help=”whether there is only one person in the image or not”)
parser.add_argument(“–image_size”,
dest=”image_size”,
type=int,
default=256,
help=”size of image”)
parser.add_argument(“–batch_size”,
dest=”batch_size”,
type=int,
default=1,
help=”Batch size for fom model”)
parser.add_argument(
“–face_enhancement”,
dest=”face_enhancement”,
action=”store_true”,
help=”use face enhance for face”)
parser.add_argument(
“–mobile_net”,
dest=”mobile_net”,
action=”store_true”,
help=”use mobile_net for fom”)
parser.set_defaults(relative=True)
parser.set_defaults(adapt_scale=True)
#parser.set_defaults(relative=False)
#parser.set_defaults(face_enhancement=False)
parser.set_defaults(mobile_net=False)
############################################################################
from ppgan.apps.wav2lip_predictor import Wav2LipPredictor
parser2 = argparse.ArgumentParser(
description=
‘Inference code to lip-sync videos in the wild using Wav2Lip models’)
parser2.add_argument(‘–checkpoint_path’,
type=str,
help=’Name of saved checkpoint to load weights from’,
default=None)
parser2.add_argument(
‘–audio’,
type=str,
help=’Filepath of video/audio file to use as raw audio source’,
required=False , # required=True,
default=’/var/www/html/system/inputwav.wav’)#修改0308
parser2.add_argument(‘–face’,
type=str,
help=’Filepath of video/image that contains faces to use’,
required=False, #required=True,
default=’/var/www/html/system/result.mp4′)#修改0308
parser2.add_argument(‘–outfile’,
type=str,
help=’Video path to save result. See default for an e.g.’,
default=’results/result_voice.mp4′)
parser2.add_argument(
‘–static’,
type=bool,
help=’If True, then use only first video frame for inference’,
default=False)
parser2.add_argument(
‘–fps’,
type=float,
help=’Can be specified only if input is a static image (default: 25)’,
default=25.,
required=False)
parser2.add_argument(
‘–pads’,
nargs=’+’,
type=int,
default=[0, 10, 0, 0],
help=
‘Padding (top, bottom, left, right). Please adjust to include chin at least’
)
parser2.add_argument(‘–face_det_batch_size’,
type=int,
help=’Batch size for face detection’,
default=16)
parser2.add_argument(‘–wav2lip_batch_size’,
type=int,
help=’Batch size for Wav2Lip model(s)’,
default=128)
parser2.add_argument(
‘–resize_factor’,
default=1,
type=int,
help=
‘Reduce the resolution by this factor. Sometimes, best results are obtained at 480p or 720p’
)
parser2.add_argument(
‘–crop’,
nargs=’+’,
type=int,
default=[0, -1, 0, -1],
help=
‘Crop video to a smaller region (top, bottom, left, right). Applied after resize_factor and rotate arg. ‘
‘Useful if multiple face present. -1 implies the value will be auto-inferred based on height, width’
)
parser2.add_argument(
‘–box’,
nargs=’+’,
type=int,
default=[-1, -1, -1, -1],
help=
‘Specify a constant bounding box for the face. Use only as a last resort if the face is not detected.’
‘Also, might work only if the face is not moving around much. Syntax: (top, bottom, left, right).’
)
parser2.add_argument(
‘–rotate’,
default=False,
action=’store_true’,
help=
‘Sometimes videos taken from a phone can be flipped 90deg. If true, will flip video right by 90deg.’
‘Use if you get a flipped result, despite feeding a normal looking video’)
parser2.add_argument(
‘–nosmooth’,
default=False,
action=’store_true’,
help=’Prevent smoothing face detections over a short temporal window’)
parser2.add_argument(“–cpu”, dest=”cpu”, action=”store_true”, help=”cpu mode.”)
parser2.add_argument(
“–face_detector”,
dest=”face_detector”,
type=str,
default=’sfd’,
help=”face detector to be used, can choose s3fd or blazeface”)
parser2.add_argument(
“–face_enhancement”,
dest=”face_enhancement”,
action=”store_true”,
help=”use face enhance for face”)
parser2.set_defaults(face_enhancement=False)
############################################################################
import time
import os
n = 100
sum = 0
counter = 1
err1 = 0
err2 = 0
err3 = 0
fig1_data_old=”
fig2_data_old=”
fig3_data_old=”
str_data1=”
str_data2=”
str_data3=”
load_spk_id=”
print (‘Start : %s v0308===========================’ % time.ctime() )
if __name__ == “__main__”:
while True : #主循环
print (‘Start : %s ver 0308 :19’ % time.ctime() )
time.sleep( 5 )
#第一步,生成语音
#检查标志文件
with open(“/var/www/html/system/fig1.txt”, ‘r’, encoding=”utf-8″) as f:
str_data1 = f.read()
f.close()
if str_data1 != fig1_data_old:
fig1_data_old=str_data1 #执行控制
print(‘文件不是空的,读取内容’)
read_file = “/var/www/html/input/msg.txt”
with open(read_file, ‘r’, encoding=”utf-8″) as f:
fig1_data_old=str_data = f.read()
f.close()
with open(“/var/www/html/system/fig1b.txt”, ‘r’, encoding=”utf-8″) as f:
str_data_gender = f.read() #读取性别数据
f.close()
if str_data_gender==”female”:
load_spk_id=1
if str_data_gender==”male”:
load_spk_id=167
from paddlespeech.cli.tts.infer import TTSExecutor
tts = TTSExecutor()
tts(text=str_data, output=”/var/www/html/output1/outwav.wav”,
am=”fastspeech2_aishell3″,
voc=”hifigan_aishell3″,
lang=”zh”,
spk_id=load_spk_id
)
#第二步,生成视频
#检查标志文件fig2
with open(“/var/www/html/system/fig2.txt”, ‘r’, encoding=”utf-8″) as f:
str_data2 = f.read()
f.close()
if str_data2 != fig2_data_old:
fig2_data_old=str_data2 #执行控制
from PIL import Image
filename = r’/var/www/html/input/picture.jpeg’
img = Image.open(filename)
imgSize = img.size #图片的长和宽 图片觉得不能超限,不然第三步会崩溃
print (imgSize)
maxSize = max(imgSize) #图片的长边
minSize = min(imgSize) #图片的短边
print(maxSize, minSize)
if maxSize <=480 and minSize <= 480 :
args = parser.parse_args()
paddle.set_device(‘cpu’)
#面部表情迁移
#err2=os.system(“export PYTHONPATH=$PYTHONPATH:/home/PaddleGAN && python -u /home/PaddleGAN/applications/tools/first-order-demo.py –driving_video /var/www/html/system/driving_video.mp4 –source_image /var/www/html/input/picture.jpeg –ratio 0.4 –relative –adapt_scale –output /var/www/html/system/”)
predictor = FirstOrderPredictor(output=”/var/www/html/output2/”,
filename=args.filename,
weight_path=args.weight_path,
config=args.config,
relative=args.relative,
adapt_scale=args.adapt_scale,
find_best_frame=args.find_best_frame,
best_frame=args.best_frame,
ratio=args.ratio,
face_detector=args.face_detector,
multi_person=args.multi_person,
image_size=args.image_size,
batch_size=args.batch_size,
face_enhancement=args.face_enhancement,
mobile_net=args.mobile_net)
predictor.run(“/var/www/html/input/picture.jpeg”, “/var/www/html/system/driving_video.mp4” )
#第三步,生成视频
#检查标志文件fig3
with open(“/var/www/html/system/fig3.txt”, ‘r’, encoding=”utf-8″) as f:
str_data3 = f.read()
f.close()
if str_data3 != fig3_data_old:
fig3_data_old=str_data3 #执行控制
#err3=os.system(“export PYTHONPATH=$PYTHONPATH:/home/PaddleGAN && python /home/PaddleGAN/applications/tools/wav2lip.py –face /var/www/html/system/result.mp4 –audio /var/www/html/system/inputwav.wav –outfile /var/www/html/output/output.mp4”)
args = parser2.parse_args()
#if args.cpu:
paddle.set_device(‘cpu’)
predictor = Wav2LipPredictor( checkpoint_path = args.checkpoint_path,
static = args.static,
fps = args.fps,
pads = args.pads,
face_det_batch_size = args.face_det_batch_size,
wav2lip_batch_size = args.wav2lip_batch_size,
resize_factor = args.resize_factor,
crop = args.crop,
box = args.box,
rotate = args.rotate,
nosmooth = args.nosmooth,
face_detector = args.face_detector,
face_enhancement = args.face_enhancement)
predictor.run(“/var/www/html/output2/result.mp4”, “/var/www/html/output1/outwav.wav”, “/var/www/html/output3/output.mp4”)
b.守护程序源代码 run2.py
def mainwork():
from PIL import Image
import time
import os
n = 100
sum = 0
counter = 1
err1 = 0
err2 = 0
err3 = 0
fig1_data_old = 0
fig2_data_old = 0
fig3_data_old = 0
str_data1 = 0
str_data2 = 0
str_data3 = 0
os.system(“export PYTHONPATH=$PYTHONPATH:/home/PaddleGAN && python /var/www/html/run.py”)
三、PHP语言开发的前台操作界面程序, 文件为:index.php
#!/usr/bin/env python
#encoding: utf-8
#description: 一个守护进程的简单包装类, 具备常用的start|stop|restart|status功能, 使用方便
# 需要改造为守护进程的程序只需要重写基类的run函数就可以了
#date: 2015-10-29
#usage: 启动: python daemon_class.py start
# 关闭: python daemon_class.py stop
# 状态: python daemon_class.py status
# 重启: python daemon_class.py restart
# 查看: ps -axj | grep daemon_class
import atexit, os, sys, time, signal
class CDaemon:
”’
a generic daemon class.
usage: subclass the CDaemon class and override the run() method
stderr 表示错误日志文件绝对路径, 收集启动过程中的错误日志
verbose 表示将启动运行过程中的异常错误信息打印到终端,便于调试,建议非调试模式下关闭, 默认为1, 表示开启
save_path 表示守护进程pid文件的绝对路径
”’
def __init__(self, save_path, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull, home_dir=’.’, umask=22, verbose=1):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = save_path #pid文件绝对路径
self.home_dir = home_dir
self.verbose = verbose #调试开关
self.umask = umask
self.daemon_alive = True
def daemonize(self):
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError as e:
sys.stderr.write(‘fork #1 failed: %d (%s)\n’ % (e.errno, e.strerror))
sys.exit(1)
os.chdir(self.home_dir)
os.setsid()
os.umask(self.umask)
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError as e:
sys.stderr.write(‘fork #2 failed: %d (%s)\n’ % (e.errno, e.strerror))
sys.exit(1)
sys.stdout.flush()
sys.stderr.flush()
si = open(self.stdin, ‘r’)
so = open(self.stdout, ‘a+’)
if self.stderr:
se = open(self.stderr, ‘a+’)
else:
se = so
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
def sig_handler(signum, frame):
self.daemon_alive = False
signal.signal(signal.SIGTERM, sig_handler)
signal.signal(signal.SIGINT, sig_handler)
if self.verbose >= 1:
print(“daemon process started …”)
atexit.register(self.del_pid)
pid = str(os.getpid())
open(self.pidfile, ‘w+’).write(‘%s\n’ % pid)
def get_pid(self):
try:
pf = open(self.pidfile, ‘r’)
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
except SystemExit:
pid = None
return pid
def del_pid(self):
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
def start(self, *args, **kwargs):
if self.verbose >= 1:
print( ‘ready to starting ……’)
#check for a pid file to see if the daemon already runs
pid = self.get_pid()
if pid:
msg = ‘pid file %s already exists, is it already running?\n’
sys.stderr.write(msg % self.pidfile)
sys.exit(1)
#start the daemon
self.daemonize()
self.run(*args, **kwargs)
def stop(self):
if self.verbose >= 1:
print (‘stopping …’)
pid = self.get_pid()
if not pid:
msg = ‘pid file [%s] does not exist. Not running?\n’ % self.pidfile
sys.stderr.write(msg)
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
return
#try to kill the daemon process
try:
i = 0
while 1:
os.kill(pid, signal.SIGTERM)
time.sleep(0.1)
i = i + 1
if i % 10 == 0:
os.kill(pid, signal.SIGHUP)
except OSError as err:
err = str(err)
if err.find(‘No such process’) > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print (“str err”)
sys.exit(1)
if self.verbose >= 1:
print (‘Stopped!’)
def restart(self, *args, **kwargs):
self.stop()
self.start(*args, **kwargs)
def is_running(self):
pid = self.get_pid()
#print(pid)
return pid and os.path.exists(‘/proc/%d’ % pid)
def run(self, *args, **kwargs):
‘NOTE: override the method in subclass’
print (‘base class run()’)
class ClientDaemon(CDaemon):
def __init__(self, name, save_path, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull, home_dir=’.’, umask=22, verbose=1):
CDaemon.__init__(self, save_path, stdin, stdout, stderr, home_dir, umask, verbose)
self.name = name #派生守护进程类的名称
def run(self, output_fn, **kwargs):
fd = open(output_fn, ‘w’)
while True:
line = time.ctime() + ‘\n’
fd.write(line)
fd.flush()
time.sleep(1)
mainwork()
fd.close()
if __name__ == ‘__main__’:
help_msg = ‘Usage: python %s <start|stop|restart|status>’ % sys.argv[0]
if len(sys.argv) != 2:
print (help_msg)
sys.exit(1)
p_name = ‘clientd’ #守护进程名称
pid_fn = ‘/tmp/daemon_class.pid’ #守护进程pid文件的绝对路径
log_fn = ‘/tmp/daemon_class.log’ #守护进程日志文件的绝对路径
err_fn = ‘/tmp/daemon_class.err.log’ #守护进程启动过程中的错误日志,内部出错能从这里看到
cD = ClientDaemon(p_name, pid_fn, stderr=err_fn, verbose=1)
if sys.argv[1] == ‘start’:
cD.start(log_fn)
elif sys.argv[1] == ‘stop’:
cD.stop()
elif sys.argv[1] == ‘restart’:
cD.restart(log_fn)
elif sys.argv[1] == ‘status’:
alive = cD.is_running()
if alive:
print (‘process [%s] is running ……’) % cD.get_pid()
else:
print (‘daemon process [%s] stopped’) %cD.name
else:
print (‘invalid argument!’)
print (help_msg)
##################################################################################################
<!DOCTYPE HTML>
<html>
<head>
<meta charset=”utf-8″>
<title>虚拟人 接口界面</title>
<style>
.error {color: #FF0000;}
</style>
</head>
<body>
<h2>虚拟人 接口界面</h2>
<p><span class=”error”> </span></p>
<?php // 第一步的程序===
// 定义变量并默认设置为空值
$nameErr = $emailErr = $genderErr = $websiteErr = “”;
$name = $email = $gender = $comment = $website = “”;
if ($_SERVER[“REQUEST_METHOD”] == “POST”)
{
if (!empty($_POST[“submit1”]))
{
if (empty($_POST[“comment”]))
{
$comment = “”;
}
else
{
$comment = test_input($_POST[“comment”]);
$str = $_POST[“comment”];
// $str=$_GET[text];//此处可以使用POST/GET text可以自定
$save = $str.”\n”;
unlink(“input/msg.txt”);
file_put_contents(“input/msg.txt”,$comment); //txt.txt可以自定文件名
unlink(“system/fig1.txt”);
$uniqid = md5(uniqid(microtime(true),true));//随机字符串 标志
file_put_contents(“system/fig1.txt”,$uniqid); //fig1.txt 第一步操作标志,给run
echo “语音内容为:”. $comment ;
}
if (empty($_POST[“gender”]))
{
$genderErr = “性别是必需的”;
}
else
{
$gender = test_input($_POST[“gender”]);
unlink(“system/fig1b.txt”);
file_put_contents(“system/fig1b.txt”,$gender); //fig1.txt 第一步操作标志,给run
}
}
else if (!empty($_POST[“submit2”]))
{
;
}else if (!empty($_POST[“submit3”]))
{
// pcntl_exec( “/bin/bash” , array(“whoami”));
// pcntl_exec(‘bash /var/www/html/run1.sh’);
unlink(“system/fig3.txt”);
$uniqid = md5(uniqid(microtime(true),true));//随机字符串 标志
file_put_contents(“system/fig3.txt”,$uniqid,FILE_APPEND ); //fig3.txt 第三步操作标志,给run
}
}
function test_input($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<!–第一步的图表 –>
<form enctype=”multipart/form-data” method=”post” action=”<?php echo htmlspecialchars($_SERVER[“PHP_SELF”]);?>”>
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
<br>
请输入话语内容: <br>
<textarea name=”comment” rows=”5″ cols=”40″><?php echo $comment;?></textarea>
<br><br>
请选择虚拟人的性别:
<input type=”radio” name=”gender” <?php if (isset($gender) && $gender==”1″) echo “checked”;?> value=”female”>女
<input type=”radio” name=”gender” <?php if (isset($gender) && $gender==”167″) echo “checked”;?> value=”male”>男
<span class=”error”><?php echo $genderErr;?></span>
<br><br>
<input type=”submit” name=”submit1″ value=”第1步:生成虚拟人:语音”> <br>
<?php // 结果列表
$down=’file_dowm.php’;
$path=’output1/’;
$url=$_SERVER[‘REQUEST_URI’];//访问此页面所需的 URI
if (isset($_GET[‘dir’])) {//判断是否存在目录
$path=$path.$_GET[‘dir’].’/’;
}else{
$url=$url.’?dir=’;
}
$fh=opendir($path);
$data=array();
while (($row=readdir($fh))!==false) {
if ($row==’.’ || $row==’..’) {
continue;
}
$row=iconv(“gb2312”, “utf-8″,$row);
$data[]=$row;
}
?>
<table border=”1″>
<tr>
<td>生成结果文件</td>
<td>操作</td>
</tr>
<?php foreach ($data as $v) { ?>
<tr>
<td><?php echo $v; ?></td>
<td>
<?php if(is_dir($path.$v)){ ?>
<a href=”<?php echo%20$url.’/’.$v;%20?>”>打开</a>
<a href=”<?php echo%20$down.’?’.’id1′.’=’.$v%20?>”>下载</a>
<?php }else{ ?>
<a href=”<?php echo%20$path.$v;%20?>”>查看</a>
<a href=”<?php echo%20$down.’?’.’id1′.’=’.$path.$v%20?>”>下载</a>
<?php } ?>
</td>
</tr>
<?php } ?>
</table>
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
</form>
<br>
请上传虚拟人外貌照片(注:必须是五官清晰的正面人物照片。 照片格式为.JPG 或.JPEG。<br>
照片尺寸需小宽480像素 * 高480像素照片文件必须小于80KB) <br>
<br>
<?php //第二步 的程序
$uptypes=array(‘image/jpg’,’image/jpeg’);
$addtime=date(“Ym”,time());
$testdir=”./input/”;
if(file_exists($testdir)):
else:
mkdir($testdir,0777);
endif;
$max_file_size=2097152; //上传文件大小限制, 单位BYTE
$destination_folder=$testdir; //上传文件路径
$imgpreview=1; //是否生成预览图(1为生成,其他为不生成);
$imgpreviewsize=1/2; //缩略图比例
?>
<?php
if ($_SERVER[‘REQUEST_METHOD’] == ‘POST’)
{
if (!empty($_POST[“submit2”]))
{
$file = $_FILES[“upfile”];
$filename=$file[“tmp_name”];
$image_size=getimagesize($filename);
$width = $image_size[0];
$height = $image_size[1];
if (!is_uploaded_file($file[“tmp_name”]))
//是否存在文件
{
echo “图片不存在!”;
// exit;
}
// $file = $_FILES[“upfile”];
else if($max_file_size < $file[“size”])
//检查文件大小
{
echo “文件太大!”;
// exit;
}
else if(!in_array($file[“type”], $uptypes))
//检查文件类型
{
echo “文件类型不符!”.$file[“type”];
// exit;
}
else if($width > 480)
{
echo’错误 :图片宽长度超过限制 480′;
}
else if($height > 480)
{
echo’错误 :图片高长度超过限制 480′;
}
else if( $file[“size”] >80*1024 )
{
echo”错误 :图片文件大小超过 80kb”;
}else{
$pinfo=pathinfo($file[“name”]);
$ftype=$pinfo[‘extension’];
$destination =$destination_folder.”picture”.”.”.$ftype; //组合出路径和文件名
if (file_exists($destination) && $overwrite != true)
{
// echo “同名文件已经存在了”;
unlink(destination); //删除一存在的文件
// exit;
}
if(!move_uploaded_file ($filename, $destination))
{
// echo “移动文件出错”;
// exit;
}
$pinfo=pathinfo($destination);
$fname=$pinfo[“basename”];
echo ” <font color=red>已经成功上传</font><br>文件名: <font color=blue>”.$destination_folder.$fname.”</font><br>”;
echo ” 宽度:”.$image_size[0];
echo ” 长度:”.$image_size[1];
echo “<br> 大小:”.$file[“size”].” bytes”;
if($imgpreview==1)
{;
echo “<br>图片预览:<br>”;
echo “<img src=\””.$destination.”\” width=”.($image_size[0]*$imgpreviewsize).” height=”.($image_size[1]*$imgpreviewsize);
echo ” title=\”图片预览:\r文件名:”.$destination.”\r上传时间:\”>”;
}
////图片上传成功后 上传操作标志 2
unlink(“system/fig2.txt”); //删除文件
$uniqid = md5(uniqid(microtime(true),true));//随机字符串 标志
file_put_contents(“system/fig2.txt”,$uniqid); //fig2.txt 第二步操作标志,给run
}
}
}
?>
<!– 第二步的图表 –>
<form enctype=”multipart/form-data” method=”post” action=”<?php echo htmlspecialchars($_SERVER[“PHP_SELF”]);?>”>
选择上传图片:
<input name=”upfile” type=”file”> <br>
<input type=”submit” name=”submit2″ value=”第2步:生成虚拟人:视频”> <br>
<?php // 结果列表
$down=’file_dowm.php’;
$path=’output2/’;
$url=$_SERVER[‘REQUEST_URI’];//访问此页面所需的 URI
if (isset($_GET[‘dir’])) {//判断是否存在目录
$path=$path.$_GET[‘dir’].’/’;
}else{
$url=$url.’?dir=’;
}
$fh=opendir($path);
$data=array();
while (($row=readdir($fh))!==false) {
if ($row==’.’ || $row==’..’) {
continue;
}
$row=iconv(“gb2312”, “utf-8″,$row);
$data[]=$row;
}
?>
<table border=”1″>
<tr>
<td>生成结果文件</td>
<td>操作</td>
</tr>
<?php foreach ($data as $v) { ?>
<tr>
<td><?php echo $v; ?></td>
<td>
<?php if(is_dir($path.$v)){ ?>
<a href=”<?php echo%20$url.’/’.$v;%20?>”>打开</a>
<a href=”<?php echo%20$down.’?’.’id1′.’=’.$v%20?>”>下载</a>
<?php }else{ ?>
<a href=”<?php echo%20$path.$v;%20?>”>查看</a>
<a href=”<?php echo%20$down.’?’.’id1′.’=’.$path.$v%20?>”>下载</a>
<?php } ?>
</td>
</tr>
<?php } ?>
</table>
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
</form>
<!– 第三步的程序 无 –>
<!– 第三步的图表 –>
<form enctype=”multipart/form-data” method=”post” action=”<?php echo htmlspecialchars($_SERVER[“PHP_SELF”]);?>”>
将第一步生成的音频与第二步生成的视频合成,生成最终的虚拟人。<br>
提交前请确保第一和第二步生成了您想要的效果。<br>
合成可能花费数分钟的时间,请耐心等待。<br>
<br><br>
<input type=”submit” name=”submit3″ value=”第3步:生成成虚拟人:视频+语音”> <br>
<?php // 结果列表
$down=’file_dowm.php’;
$path=’output3/’;
$url=$_SERVER[‘REQUEST_URI’];//访问此页面所需的 URI
if (isset($_GET[‘dir’])) {//判断是否存在目录
$path=$path.$_GET[‘dir’].’/’;
}else{
$url=$url.’?dir=’;
}
$fh=opendir($path);
$data=array();
while (($row=readdir($fh))!==false) {
if ($row==’.’ || $row==’..’) {
continue;
}
$row=iconv(“gb2312”, “utf-8″,$row);
$data[]=$row;
}
?>
<table border=”1″>
<tr>
<td>生成结果文件</td>
<td>操作</td>
</tr>
<?php foreach ($data as $v) { ?>
<tr>
<td><?php echo $v; ?></td>
<td>
<?php if(is_dir($path.$v)){ ?>
<a href=”<?php echo%20$url.’/’.$v;%20?>”>打开</a>
<a href=”<?php echo%20$down.’?’.’id1′.’=’.$v%20?>”>下载</a>
<?php }else{ ?>
<a href=”<?php echo%20$path.$v;%20?>”>查看</a>
<a href=”<?php echo%20$down.’?’.’id1′.’=’.$path.$v%20?>”>下载</a>
<?php } ?>
</td>
</tr>
<?php } ?>
</table>
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
</form>
</body>
</html>
本文为原创文章,转载请注明出处!