Вместе с деловым партнером и старым другом в Сиэтле я работаю над новой захватывающей гиго. Это визуализатор 3D-музыки, созданный на HTML5/WebGL с использованием PureMVC, React и Three.js. У нас уже есть надежный, расширяемый клиентский фреймворк и несколько замечательных вещей, происходящих в отрендеренной сцене, которые пользователь может настроить, а затем сохранить.

Теперь мы хотим создать видео, чтобы мы могли загрузить его на YouTube или поделиться им на Facebook.

Наш первоначальный план состоял в том, чтобы отрендерить сохраненный проект на сервере с помощью Node.js в стиле render-farm. Это позволило бы нам гарантировать плавное воспроизведение и отсутствие заиканий из-за неизвестной загрузки клиента и/или его возможностей. Должно быть моментально, верно? Э, нет.

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

Что не так с рендерингом на сервере?

  • Для Three.js существует пакет npm, однако в нем много вызовов document.createElement, поэтому ему нужен DOM. По этой причине пример на странице npm вообще не будет работать в node.js. Я предполагаю, что он предназначен для использования с браузером и не предназначен специально для рендеринга на стороне сервера.
  • Вы легко можете добавить DOM в свой проект с помощью такого пакета, как jsdom, однако вы не сможете сделать больше, чем получить CanvasRenderer. Для WebGLRenderer вам нужна реализация WebGL, которую jsdom не дает.
  • Предполагая, что можно получить WebGLRenderer, вам, скорее всего, потребуется реализовать метод requestAnimationFrame() в зависимости от того, какую библиотеку вы выбрали для добавления своей DOM. Ничего страшного, он просто отвечает за вызов переданного обратного вызова, когда требуется новый кадр. Вы можете просто использовать setInterval() для вызова с желаемой частотой кадров.
  • Есть несколько вариантов внебраузерного WebGL, в том числе:
  • узел-webgl
  • электрон
  • headless-gl (как ни странно, просто gl в npm, но headless-gl в документации и на GitHub).
  • Приведенная выше ссылка на headless-gl ведет прямо к списку причин, по которым вы можете выбрать его, а не node-webgl или электрон. Я был тронут, чтобы выбрать headless-gl.
  • Наконец, вот начало нескольких героических постов в ветке вопросов о том, как заставить Three.js и WebGLRenderer работать в Node.js. Суть в CoffeeScript. Но текстурирование и сглаживание требовали особого внимания после того, как был нарисован базовый PNG куба.

Подождите минуту. Я уверен, что это единственный способ сделать это?

Именно на этом этапе моего исследования я начинаю сомневаться во всех зависимостях и потенциальных хаках, необходимых для этого, и действительно ли это правильный путь(tm). Я не отношусь к проектным зависимостям легкомысленно. Мой небольшой тестовый проект для выяснения этой части имел только следующие зависимости верхнего уровня:

"dependencies": {
  "gl": "^4.0.2",
  "jsdom": "^9.5.0",
  "three": "^0.81.2"
}

Но беглый взгляд на node_modules показывает (…Боже мой…):

Destiny:node_modules cliff$ ls -al |wc -l
187

Ой! Уже сто восемьдесят семь пакетов? Это много независимо поддерживаемых мест, где это может потерпеть неудачу. Много дорог в ад зависимости.

Каковы плюсы и минусы попытки сделать это на стороне клиента?

  • Одно очевидное преимущество заключается в том, что мы не платим нашему облачному провайдеру за циклы процессора, необходимые для рендеринга кадров.
  • Мы беспокоились о потенциальных проблемах с нагрузкой или возможностями клиента, но на самом деле у нашей конкретной целевой аудитории (музыкальные продюсеры), вероятно, в любом случае есть довольно здоровенные машины. И если они могут получить сцену, которой хотят поделиться, работая на своем экране, то почему бы просто не нажать кнопку записи прямо сейчас?
  • Частота кадров, которую мы в настоящее время достигаем на относительно обычном оборудовании (например, на моем MacBook Air 2011 года), составляет около 60 кадров в секунду. В любом случае для видео нам потребуется всего около 30 кадров в секунду, поэтому мы, вероятно, сможем сэкономить несколько циклов, чтобы захватить каждый кадр как изображение. Но можем ли мы превратить эти изображения в фильм?
  • Удивительно, но популярный ffmpeg был переведен на JS и работает в браузере. Однако ветка обсуждения, которую я обнаружил, указывает на то, что она может быть не готова к производству. Хм. По крайней мере, это путь для исследований.
  • Вот другой подход: рендерим на клиенте, отправляем отрендеренные кадры на сервер и создаем там ролик.
  • Создание фильма из последовательности файлов будет гораздо более проторенным путем на стороне сервера, чем рендеринг WebGL. Вероятно, менее сомнительное предложение.
  • В приведенном выше примере разработчик: а) записывает кадры на сервер узла на своем локальном компьютере, б) делает это с помощью синхронных запросов XHR и в) делает эти запросы в цикле рендеринга. Я не думаю, что это возможно через Interwebz, даже учитывая тот факт, что мы будем делать 30 кадров в секунду вместо 60.
  • Я считаю, что концепция по-прежнему верна, если мы 1) запишем кадры в локальное хранилище браузера в качестве буфера в цикле рендеринга, 2) создадим отдельный рабочий веб-процесс, который отправляет эти кадры на сервер, и 3) сохраним сокет open и выгружает кадр за кадром, пока мы не закончим, устраняя накладные расходы, связанные со всеми отдельными запросами XHR.
  • Аудио должно быть уже на сервере, и его тривиально включить при создании видео из изображений.

Хорошо. Я убежден, что стоит попробовать изучить путь рендеринга кадров на стороне клиента с кодированием видео на стороне сервера. Я вернусь к вам в другом посте с тем, что я нашел. А пока, если у вас есть что сказать, пожалуйста, напишите мне в разделе комментариев ниже!

Приложение

В ветке комментариев Dzone был поднят хороший вопрос: не беспокоюсь ли я, что буду обменивать циклы ЦП на пропускную способность в счетах от нашего облачного провайдера, переходя к сборке изображений на стороне сервера с рендерингом на стороне клиента. Для нас это было бы проблемой, если бы мы остались с нашим первоначальным предполагаемым поставщиком AWS. Однако после недавнего отличного опыта работы с облачной платформой Google мы изучили ее и обнаружили, что они предлагают бесплатный входящий трафик.

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

Примечание автора.Эта статья является частью серии, в которой мой партнер и я пробуем разработку нашего продукта «на открытом воздухе».

Это диаметрально противоположно моему типичному подходу «работы скунса», заключающемуся в том, чтобы месяцами сидеть взаперти в бессмысленных попытках сохранить в секрете то, что в конечном итоге все равно станет достоянием гласности. Мы не строим ничего революционного, изменяющего парадигму или строящего империю. Просто что-то классное, что служит нише, которую мы знаем и заинтересованы в помощи. Это визуализатор 3D-музыки, созданный на HTML5/WebGL с использованием Three.js, PureMVC, React и Node.js. Когда мы закончим, вы сможете создать классное видео для своей аудиодорожки и загрузить его на YouTube.

Преимущество ведения блога об этом в том, что у нас есть возможность передать некоторые из наших мыслительных процессов, когда мы преодолеваем препятствия и выбоины, разбросанные по нашему пути. Избавление от этих мыслей, пока они еще свежи в памяти, может направить кого-то другого на тот же путь. Если мы потерпим неудачу из-за этих решений, возможно, это поможет вам избежать собственного дымящегося кратера. В любом случае, позже мы будем заняты погоней за разными белками в каком-нибудь другом парке.

The next article in this series is: Creating Video on the Server in Node.js
This article has been reblogged at the following sites:
DZone: https://bit.ly/threejs-rendering-client-or-server