将HTML画布导出为图像序列

2024-10-01 07:13:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我创建了一个非常天真的页面,它需要三.js场景(尽管这可能是任何非WebGL<canvas>动画)并导出单个图像(或图像序列),然后将其转换为视频。在

我之所以这么做,部分是为了学习Python,同时也是为了能够在三.js然后出口一个巨大的高分辨率丝般光滑的视频对我来说是超级有吸引力的。在过去,我用屏幕捕捉软件来抓取视频,虽然它总是感觉有点笨拙,实时的FPS下降也会在最后的视频中显示出来。在

我目前的流程如下:

Javascript

  • 创建WebGL场景并设置渲染周期
  • 将画布宽度/高度设置为所需的尺寸
  • 使用requestAnimationFrame渲染场景
  • 暂停场景的渲染/更新周期
  • 对canvas元素调用toDataURL(),并检索base64字符串
  • 将请求发送到python脚本,传递base64字符串(以及其他内容,如要保存到的目标目录以及是否捕获了单个图像或序列)

Python:

  • 去掉MIME头内容类型并解码base64字符串
  • 将字符串写入图像文件
  • 如果文件已写入,则打印/返回一个表示成功状态的字符串,否则打印出有问题的错误消息

import base64, cgi, cgitb, datetime, glob, re, os

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,是否可以轻松地设置较低的帧速率?假设出于某种风格原因,我想以每秒15帧的速度更新所有内容,那么唯一的选择是使用setTimeout(callback, 1000 / targetFPS),并理解它将drift over time?在
  • 从上面开始,这个动画有一个变量frame,它在每个更新周期中递增1。然后,该变量用于控制动画的不同部分(例如,旋转立方体,并传递到顶点/片段着色器以操纵颜色和纹理UV坐标)。在

    如果我想模拟15fps之类的东西,我需要将frame增加(60 / 15)而不是正确的?有没有一种更优雅的方式可以轻松地在封顶帧速率之间切换?

  • 最后,,是否有任何技术可以用来提高所渲染图像的质量?(大声想一想,把钱存到两倍大小,然后再减一倍?)在

我真的希望这是有意义的,任何意见或建议将被广泛赞赏。在

源文件:http://cl.ly/3V46120C2d3B0A1o3o25(在Mac/Chrome稳定版上测试,需要WebGL)


Tags: 字符串图像form视频ifos场景print