我认为 node-canvas 不支持 webgl 上下文,因此您必须使用围绕 2d 绘图构建的库,并且它肯定不支持任何视频编解码器。
如果您可以使用节点画布使动画正常工作,则可以以适合您的内容的速率抓取动画帧,如下所示:
披露:我已经成功地使用 FFmpeg 对一系列外部生成的图像进行编码,但还没有尝试过下面的 setInterval() 方法。除了动画开销本身之外,我不知道以 30 FPS 的速度将画布导出为 PNG 文件会如何执行。
// 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()
可以看这个例子。
编辑:当动画循环不断地在那个画布上绘制时,写入不正确的帧可能会出现问题canvas.pngStream()
——也许每帧都需要创建一个画布的副本?这肯定会造成巨大的记忆压力。