Yes you can, in modern browsers, but you'll loose every audio stream (Actually you can save it too), and I think that the mp4 requirement is not here yet and you should not wait for it (damn royalties) only webm or ogv export is currently available.
You can use a MediaRecorder and the canvas.captureStream()
method.
var mediaRecorder = new MediaRecorder(canvas.captureStream(30));
Here is an example code (which will only work on latests FF and chrome !).
var startRecording = function(){
// make something happen on the canvas
var stopCanvas = initCanvasDrawing();
// really, that's it..
var recorder = new MediaRecorder(canvas.captureStream(30))
var chunks = [];
recorder.ondataavailable = function(e){
if(e.data.size){
chunks.push(e.data)
}
};
recorder.onstop = function(){
var blob = new Blob(chunks);
var url = URL.createObjectURL(blob);
unrelatedDOMStuff(url);
stopCanvas();
};
recorder.start();
setTimeout(function(){recorder.stop()}, 5000);
}
// the rest of the code is just for the demo
var unrelatedDOMStuff = function(url){
rec.style.display = canvas.style.display = 'none';
var vid = document.createElement('video');
vid.src = url
vid.controls = true;
document.body.appendChild(vid);
vid.play();
var a = document.createElement('a');
a.innerHTML = 'you can also get it here';
a.download = 'awesomeCanvasVid.webm';
a.href = url;
document.body.appendChild(a);
}
var initCanvasDrawing = function() {
var ctx = canvas.getContext('2d');
var objects = [];
ctx.fillStyle = 'ivory';
// taken from https://stackoverflow.com/a/23486828/3702797
for (var i = 0; i < 100; i++) {
objects.push({
angle: Math.random() * 360,
x: 100 + (Math.random() * canvas.width / 2),
y: 100 + (Math.random() * canvas.height / 2),
radius: 10 + (Math.random() * 40),
speed: 1 + Math.random() * 20
});
}
var stop = false;
var draw = function() {
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var n = 0; n < 100; n++) {
var entity = objects[n],
velY = Math.cos(entity.angle * Math.PI / 180) * entity.speed,
velX = Math.sin(entity.angle * Math.PI / 180) * entity.speed;
entity.x += velX;
entity.y -= velY;
ctx.drawImage(img, entity.x, entity.y, entity.radius, entity.radius);
entity.angle++;
}
if (!stop) {
requestAnimationFrame(draw);
}
}
var img = new Image();
img.onload = draw;
img.crossOrigin = 'anonymous';
img.src = "https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png";
return function() {
stop = true;
};
}
startRecording();
#rec{ width:2em; height:2em; border-radius:50%; background-color:red; position: absolute; top: 0; left: 0;}
a{display: block;}
video{border:1px solid green;}
<canvas id="canvas" width="500" height="250"></canvas>
<div id="rec"></div>
Note that since webm video format doesn't support transparency, every transparent pixels will be set to opaque black.