如何将画布动画保存为 gif 或 webm?
Posted
技术标签:
【中文标题】如何将画布动画保存为 gif 或 webm?【英文标题】:How to save canvas animation as gif or webm? 【发布时间】:2018-11-13 20:29:51 【问题描述】:我已经编写了这个函数来捕获 GIF 的每一帧,但是输出非常滞后并且在数据增加时崩溃。有什么建议吗?
代码:
function createGifFromPng(list, framerate, fileName, gifScale)
gifshot.createGIF(
'images': list,
'gifWidth': wWidth * gifScale,
'gifHeight': wHeight * gifScale,
'interval': 1 / framerate,
, function(obj)
if (!obj.error)
var image = obj.image;
var a = document.createElement('a');
document.body.append(a);
a.download = fileName;
a.href = image;
a.click();
a.remove();
);
/////////////////////////////////////////////////////////////////////////
function getGifFromCanvas(renderer, sprite, fileName, gifScale, framesCount, framerate)
var listImgs = [];
var saving = false;
var interval = setInterval(function()
renderer.extract.canvas(sprite).toBlob(function(b)
if (listImgs.length >= framesCount)
clearInterval(interval);
if (!saving)
createGifFromPng(listImgs, framerate, fileName,gifScale);
saving = true;
else
listImgs.push(URL.createObjectURL(b));
, 'image/gif');
, 1000 / framerate);
【问题讨论】:
【参考方案1】:在现代浏览器中,您可以结合使用 MediaRecorder API 和 htmlCanvasElement.captureStream 方法。
MediaRecorder API 将能够在视频或音频媒体文件中即时对 MediaStream 进行编码,从而比抓取静止图像时所需的内存少得多。
const ctx = canvas.getContext('2d');
var x = 0;
anim();
startRecording();
function startRecording()
const chunks = []; // here we will store our recorded media chunks (Blobs)
const stream = canvas.captureStream(); // grab our canvas MediaStream
const rec = new MediaRecorder(stream); // init the recorder
// every time the recorder has new data, we will store it in our array
rec.ondataavailable = e => chunks.push(e.data);
// only when the recorder stops, we construct a complete Blob from all the chunks
rec.onstop = e => exportVid(new Blob(chunks, type: 'video/webm'));
rec.start();
setTimeout(()=>rec.stop(), 3000); // stop recording in 3s
function exportVid(blob)
const vid = document.createElement('video');
vid.src = URL.createObjectURL(blob);
vid.controls = true;
document.body.appendChild(vid);
const a = document.createElement('a');
a.download = 'myvid.webm';
a.href = vid.src;
a.textContent = 'download the video';
document.body.appendChild(a);
function anim()
x = (x + 1) % canvas.width;
ctx.fillStyle = 'white';
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = 'black';
ctx.fillRect(x - 20, 0, 40, 40);
requestAnimationFrame(anim);
<canvas id="canvas"></canvas>
【讨论】:
我认为部分原因是性能会随着 Blob 数量的增加而下降,因此在您可以执行此代码之前存储它们可能不可行。 @TheJim01 我可能应该解释一下 MediaRecorder 对视频进行动态编码,因此它不会保存静止图像,而我们存储的chunks
确实是 final 媒体文件,即已经编码为 webm,或者说不同,不是静止图像。您只将最终视频的数据保留在内存中。
嗨,我正在尝试使用此代码,但出现如下错误:canvas.captureStream 不是函数
@UmeshPatadiya 来自哪个浏览器?微软的仍然不支持这种方法。
我在 Windows 上使用 chrome。我的项目是 Angular 6。【参考方案2】:
您也可以使用https://github.com/spite/ccapture.js/ 捕捉到 gif 或视频。
【讨论】:
以上是关于如何将画布动画保存为 gif 或 webm?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 中从 JPEG 创建动画 GIF(开发)