【发布时间】:2012-02-12 14:29:08
【问题描述】:
我创建了一个非常天真的页面,它将采用 Three.js 场景(尽管这可能是任何非 WebGL <canvas> 动画)并将单个图像(或图像序列)导出到然后转换成视频。
我这样做部分是为了学习 Python,但能够在 Three.js 中快速制作原型然后导出大量高分辨率丝滑视频的想法对我来说非常有吸引力。过去我使用屏幕捕捉软件来抓取视频,尽管它总是感觉有点笨拙,并且 FPS 的实时下降也会在最终视频中显示出来。
我目前的流程如下:
Javascript:
- 创建 WebGL 场景并设置渲染周期
- 将画布宽度/高度设置为所需尺寸
- 使用
requestAnimationFrame渲染场景 - 暂停场景的渲染/更新周期
- 在 canvas 元素上调用
toDataURL()并检索 base64 字符串 - 向 python 脚本发送 POST 请求,传递 base64 字符串(以及其他内容,例如要保存到的目标目录以及是否正在捕获单个图像或序列)
Python:
- 剥离 MIME 标头内容类型并解码 base64 字符串
- 将字符串写入图像文件
- 如果文件被写入,则打印/返回一个表示成功状态的字符串,否则打印出有问题的错误消息
cgitb.enable()
#cgitb.enable(display=0, logdir='/tmp')
print "Content-type: text/html"
print
def main():
form = cgi.FieldStorage()
saveLocation = "../httpdocs/export/"
# POST variables
dataURL = form['dataURL'].value
captureSequence = form['captureSequence'].value
folderName = saveLocation + form['folderName'].value
saveImage(dataURL, captureSequence, saveLocation, folderName)
def saveImage(dataURL, captureSequence, saveLocation, folderName):
# strip out MIME content-type (e.g. "data:image/png;base64,")
dataURL = dataURL[dataURL.index(','):]
decodedString = base64.decodestring(dataURL)
if captureSequence == 'true':
# based off http://www.akeric.com/blog/?p=632
currentImages = glob.glob(folderName + "/*.jpg")
# TODO: perhaps filenames shouldnt start at %08d+1 but rather %08d+0?
numList = [0]
if not os.path.exists(folderName):
os.makedirs(folderName)
for img in currentImages:
i = os.path.splitext(img)[0]
try:
num = re.findall('[0-9]+$', i)[0]
numList.append(int(num))
except IndexError:
pass
numList = sorted(numList)
newNum = numList[-1] + 1
saveName = folderName + '/%08d.jpg' % newNum
else:
if not os.path.exists(saveLocation):
os.makedirs(saveLocation)
saveName = saveLocation + datetime.datetime.now().isoformat().replace(':', '.') + '.jpg'
# TODO; rather than returning a simple string, consider returning an object?
try:
output = open(saveName, 'w')
output.write(decodedString)
output.close()
print 'true'
except Exception, e:
print e
if __name__ == '__main__':
main()
Javascript:
- 从 Python 脚本接收响应并显示返回的消息
- 恢复/更新渲染周期
- (根据需要对尽可能多的帧重复该过程)
这是我总是在本地运行的东西,所以不会有写入冲突或类似情况的风险。
我已经进行了一些快速测试,它似乎在大多数情况下都有效,虽然有点慢。
- 在执行此操作的过程中,我是否遗漏了一些完全明显的东西?如何改进? (尤其是在 python 方面..)
- 对每个图像进行单独的 ajax 调用是否效率低下?一个优点是我可以随时停止/关闭选项卡,它会保存所有图像直到那时。存储所有这些 base64 字符串并在最后发送它们有什么好处吗?
-
requestAnimationFrame将更新周期限制为 60fps,是否可以轻松设置较低的帧率?假设出于某种风格上的原因,我想以 15fps 的速度更新所有内容,唯一的选择是使用setTimeout(callback, 1000 / targetFPS)并理解它会 drift over time? -
根据上述情况,此动画有一个 var
frame,每个更新周期都会增加1。然后这个 var 用于控制动画的不同部分(例如,旋转立方体,并传递给顶点/片段着色器以操纵颜色和纹理 UV 坐标)。如果我想模拟 15 fps 之类的东西,我需要将
frame增加(60 / 15)是否正确?有没有更优雅的方式可以轻松地在上限帧率之间切换? - 最后,有没有什么技术可以用来提高渲染图像的质量? (大声思考,以两倍大小保存然后缩小它们?)
我真的希望这是有道理的,任何见解或建议都会受到高度赞赏。
源文件: http://cl.ly/3V46120C2d3B0A1o3o25(在 Mac/Chrome 稳定版上测试,需要 WebGL)
【问题讨论】:
-
不确定你的其他问题,但这是how to throttle requestAnimationFrame上的一个很好的答案
标签: javascript python html three.js