Экспорт HTML-холста в виде последовательности изображений

Я создалочень наивный страница, которая займет сцену Three.js (хотя это может быть любой не WebGL<canvas> анимация) и экспортирует отдельные изображения (или последовательности изображений) для последующего преобразования в видео.

Я делаю это отчасти как способ изучения Python, но идея супер-быстрого прототипирования чего-то в Three.js и последующего экспорта большого гладкого шелковистого видео с высоким разрешением мне очень привлекательна. В прошлом я использовал программное обеспечение для захвата экрана, чтобы захватывать видео, хотя это всегда казалось немного неуклюжим, и падение FPS в реальном времени просвечивало и в финальном видео.

Процесс, который у меня сейчас есть, выглядит следующим образом:

Javascript:

Создайте сцену WebGL и настройте цикл рендеринга.Установите ширину / высоту холста на желаемые размерыРендеринг сцены с использованиемrequestAnimationFrameПриостановить цикл рендеринга / обновления сценыВызовtoDataURL() на элементе canvas и получить строку base64POST-запрос к сценарию 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 и отобразите возвращенное сообщениеВозобновить / обновить цикл рендеринга(Повторите процесс столько раз, сколько нужно)

Это то, что я всегда запускаю локально, чтобы не было риска конфликтующих записей или чего-то в этом роде.

Я сделал несколько быстрых тестов, и, кажется, это работает по большей части, хотя и немного медленно.

Я упускаю что-то совершенно очевидное в том, как это делается? Как это можно улучшить? (Особенно на стороне питона вещей ..)Неэффективно ли делать отдельный вызов ajax для каждого изображения? Одним из преимуществ является то, что я могу просто остановить / закрыть вкладку в любое время, и она сохранит все изображения до этого момента. Будет ли какая-то польза от хранения всех этих строк base64 и отправки их в самом конце?КакrequestAnimationFrame ограничит цикл обновления до 60 кадров в секунду, возможно ли легко установить более низкую частоту кадров? Допустим, по какой-то стилистической причине я хотел бы обновить все со скоростью 15 кадров в секунду, будет ли единственный вариант использоватьsetTimeout(callback, 1000 / targetFPS) с пониманием того, что это будетс течением времени?

Исходя из вышесказанного, эта анимация имеет переменнуюframe который увеличивается на1 каждый цикл обновления. Этот var затем используется для управления различными частями анимации (например, вращением куба и передачей в вершинные / фрагментные шейдеры для манипулирования цветами и текстурными UV-координатами).

Если бы я хотел имитировать что-то вроде 15 кадров в секунду, я был бы прав в необходимости увеличенияframe по(60 / 15) вместо? Есть ли более элегантный способ легко переключаться между ограниченными частотами кадров?

в заключениеЕсть ли какие-либо методы, которые могли бы быть приняты для улучшения качества визуализируемых изображений? (Размышляя вслух, экономя в двойном размере, а затем уменьшая их?)

Я действительно надеюсь, что это имеет смысл, любая идея или совет будут высоко оценены.

Исходные файлы: http://cl.ly/3V46120C2d3B0A1o3o25 (Проверено на Mac / Chrome стабильной, требуется WebGL)

Ответы на вопрос(1)

Ваш ответ на вопрос