2015-07-19 1 views
9

У меня есть набор анимаций, которые я могу сделать в Canvas (fabric.js) или WebGL (three.js). Мне нужно записывать их автоматически, на стороне сервера, через скрипт и выводить видеофайл.Лучший способ записи видео ролика Canvas/WebGL в видео?

Анимации включают:

  1. Фотографии
  2. Видео (со звуком)
  3. Другие анимации/эффекты

Я исследовал много в течение последних нескольких месяцев на этом ,

Результаты
1. PhantomJS User + FFmpeg
Run HTML Canvas анимации на обезглавленный браузере (PhantomJS) и запись с FFMPEG. Здесь проблема PhantomJS не поддерживает ни WebGL, ни элемент Video.http://phantomjs.org/supported-web-standards.html

2. Используйте WebSockets для отправки данных обратно на сервер Здесь снова используя DataURL
, нам нужно будет запустить анимацию на браузере (, которые мы не можем, потому что мы должны сделать все, что на сервере) ,

3. Use node-canvas
Это библиотека по TJ Holowaychuk, которая позволяет оказывать HTML Canvas на Node.js. Но у него есть свои ограничения, и я не очень много разбираюсь в этой области. (Если кто-то мог пролить больше света на эту библиотеку)

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

+0

'node-canvas' похоже, для 2d-контекстов. Я нашел пакет «node-webgl», но не смог установить его зависимости. Однако в качестве комментария я должен написать: если вы хотите записать контекст webgl (и использовать его как механизм рендеринга) для вывода видео для себя, 1 на 1, вы можете сделать это на стороне сервера с помощью 'xhr' on локальный сервер. Но если вы хотите вывести видео для каждого подключенного пользователя в Интернете, просто подумайте, что он запрашивает у вашего сервера serverSS одну пару CPU-GPU на посетителя. Я проверял google для «3D-рендеринга на стороне сервера»: сейчас нет ничего серьезного в технологиях 2015 года. – Atrahasis

+0

Также: то, что вы описываете, - это способ использовать webgl как средство рендеринга для себя, поэтому я написал об этом выше. Если вы ищете только способ сделать это на веб-сайте, ваш вопрос будет дублировать http://stackoverflow.com/questions/64291/api-for-server-side-3d-rendering. Но из всех ответов там ничего не приносит ничего ^^ – Atrahasis

+0

@Atrahasis Что делать, если мы хотим только записать Canvas и NOT webGL. Можно ли использовать для этого узел-холст? Поддерживает ли он видео и анимацию? – Abhinav

ответ

1

Я не думаю, что узел холст поддерживает контекст WebGL, так что вы будете должны использовать библиотеку, построенную на 2d графики, и это, конечно, не будет иметь поддержку любых видео кодеков.

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

Раскрытие: Я успешно использовал FFmpeg для кодирования последовательности изображений, созданных извне, но не пробовал метод setInterval() ниже. В дополнение к самим накладкам анимации я не знаю, как будет выполняться экспорт холста в PNG-файлы с 30 FPS.

// assuming "canvas" is asynchronously drawn on some interval 

function saveCanvas(canvas, destFile) { 
    return new Promise((resolve, reject) => { 
    const ext  = path.extname(destFile), 
      encoder = '.png' === ext ? 'pngStream' 
            : 'jpegStream'; 
    let writable = fs.createWriteStream(destFile), 
     readable = canvas[encoder](); 

    writable 
     .on('finish', resolve) 
     .on('error', err => { 
     let msg = `cannot write "${destFile}": ${err.message}`; 
     reject(new Error(msg)); 
     }); 
    readable 
     .on('end', () => writable.end()) 
     .on('error', err => { 
     let msg = `cannot encode "${destFile}": ${err.message}`; 
     reject(new Error(msg)); 
     }); 
    readable.pipe(writable); 
    }); 
} 

const FPS = 30; 

let frame = 0, 
    tasks = [], 
    interval = setInterval(() => tasks.push(
    saveCanvas(canvas, `frame_${frame++}.png`)), 1000/FPS); 

// when animation is done, stop timer 
// and wait for images to be written 
clearInterval(interval); 

Promise.all(tasks).then(encodeVideo); 

function encodeVideo() { 
    // too much code to show here, but basically run FFmpeg 
    // externally with "-i" option containing "frame_%d.png" 
    // and "-r" = FPS. If you want to encode to VP9 + WEBM, 
    // definitely see: http://wiki.webmproject.org/ffmpeg/vp9-encoding-guide 
} 

И затем использовать FFmpeg для кодирования последовательности изображений в видео.
За кодом за encodeVideo() вы можете посмотреть this example.

Edit: Там может быть проблема с canvas.pngStream() написания некорректные кадров при анимации цикла непрерывно рисует на , что один холст - может быть копия холста должна быть создана для каждого кадра? Это, несомненно, создало бы значительное давление на память.

Факс:
2

Вы можете использовать электрон для рендеринга страниц WebGL с опцией «show» браузера, установленным в false и/или использованием xvfb-run для запуска безглавых.