我的公司正致力于视觉效果,我们通过浏览器为我们的客户设置内部镜头回放。为此,我们需要将视频文件上传到FTP服务器。
我想将图片序列转换为mp4
,并在渲染完成后直接上传此文件。
为此,我使用:
我已经在我的本地计算机上实现了这一点,我只是链接os.system('command')
。
在识别出程序因较长的图像序列冻结很长时间后,我改变了脚本以使用os.system
链产生一个线程。
但是在Render Farm Server上,这个脚本实际上并不起作用。
RenderFarm服务器运行Python 2.5
有一些代码示例:
class CopraUpload(threading.Thread):
# initializing Thread
# via super constructor
def __init__(self):
threading.Thread.__init__(self)
# return the size of the
# created mp4 file
#
# @return: the file size in byte
def _getFileSize(self):
# creates a random id for organising
# the server upload used as flag
#
# @return: a hash
def _getHash(self):
self.fileLoc = str(self.outputfileName + '.mp4')
self.fileLoc = os.path.normpath(self.fileLoc)
return str(os.path.getsize(self.fileLoc))
# integrates the "missing" data for the xml file
# generated post render from the mp4 file
def _setPreviewDataToXML(self):
self.xmlFile = str(self.outputfileName + '_copraUpload.xml')
self.xmlFile = os.path.normpath(self.xmlFile)
ett = ET.parse(self.xmlFile)
root = ett.getroot()
for child in root.getiterator('preview_size'):
child.text = self._getFileSize()
for child in root.getiterator('preview_md5hash'):
child.text = self._getHash()
ett.write(self.xmlFile)
# create a connection to a ftp server
# and copies the mp4 file and the xml file
# on the server
def _uploadToCopra(self):
os.system(self.uploadCommand)
#process = Popen(self.uploadCommand)
# the main function of the program
# called via start from a Thread Object
def run(self):
# the command which will be send to the commando shell
# for further adjustments see ffmpeg help with ffmpeg.exe -h
FinalCommand = self.ffmpegLocation + " -r "+ self.framerate + " -i " + self.inputPath + " -an -strict experimental -s hd720 -vcodec libx264 -preset slow -profile:v baseline -level 31 -refs 1 -maxrate 6M -bufsize 10M -vb 6M -threads 0 -g 8 -r " + self.framerate + " " + self.outputfileName + ".mp4 -y"
FinalCommandList = FinalCommand.split(" ")
# calling the program
print "Start ffmpeg convertion"
outInfo = os.path.normpath("C:\\Users\\sarender\\Desktop\\stdoutFFMPEG.txt")
outError = os.path.normpath("C:\\Users\\sarender\\Desktop\\stderrFFMPEG.txt")
stdoutFile = open(outInfo,"w")
stderrFile = open(outError,"w")
handle = subp.check_all(FinalCommandList,stdout = stdoutFile,stderr = stderrFile)
handle.communicate()
stdoutFile.close()
stderrFile.close()
print "Convertion from ffmpeg done"
# fill the xml file with the missing data
# - preview file size
# - preview md5hash
self._setPreviewDataToXML()
self._uploadToCopra()
print "---------------------------------->FINISHED------------------------------------------------------>"
# Creates a callable Thread for the Copra Upload.
# start is calling the run method which will start the Uploading
和主要开始:
if "$(RenderSet.writenode)" == "PREVIEW":
print "---------------------------------->Initializing Script------------------------------------------------------>"
process = CopraUpload()
process.start()
会发生什么:
脚本在渲染后开始,ffmpeg
转换图像序列并创建mp4
。但在那之后就停止了。它不会打印"Conversion from ffmpeg complet"
。只需停止剧本。
它实际上应该用ffmpeg
创建线程转换并等到它完成。它应该在xml文件中写入一些东西并将它们上传到服务器。
我错过了什么吗?一个帖子中的subprocess
是不是要走的路?但我需要一个Thread,因为我无法使渲染管理服务器死锁。
答案 0 :(得分:0)
我的猜测是命令失败并在handle.communicate()
中引发异常。确保捕获所有异常并将其记录在某处,因为线程无法传递异常。
此外,你不应该使用FinalCommand.split(" ")
- 如果文件名包含空格,这将以奇怪(和不可预测)的方式失败。创建一个列表,而不是将该列表传递给subp
:
FinalCommand = [
self.ffmpegLocation,
"-r", self.framerate,
"-i", self.inputPath,
"-an",
"-strict experimental",
...
]
更具可读性。