var canvases = Array.prototype.slice.call(document.querySelectorAll('canvas')),
recordingStream,
current = 0,
chunks = [],
recorder,
switchInterval;
function startRecording() {
// first gather both canvases streams & extract the videoTracks
let streams = canvases.map((c) => {
return c.captureStream(30)
});
let tracks = streams.map((s) => {
return s.getVideoTracks()[0]
});
// create a new MediaStream with both tracks in it
// we don't use addTrack because of https://bugzilla.mozilla.org/show_bug.cgi?id=1296531
recordingStream = 'MediaStream' in window && new MediaStream(tracks) || new webkitMediaStream(tracks);
// init the MediaRecorder
recorder = new MediaRecorder(recordingStream);
recorder.ondataavailable = saveChunks;
recorder.onstop = exportVideo;
recorder.onerror = (e) => {
console.log(e.name)
};
recorder.start();
stopRec.disabled = false;
// switch the canvas to be recorder every 200ms
switchInterval = setInterval(switchStream, 200);
}
// switch mute one of the tracks, then the other
function switchStream() {
current = +!current;
var tracks = recordingStream.getVideoTracks();
tracks[current].enabled = true;
// commented because it seems FF doesn't support canvasTrack's method yet
// doesn't work in chrome even when there anyway
// tracks[current].requestFrame();
tracks[+!current].enabled = false;
}
function saveChunks(evt) {
// store our video's chunks
if (evt.data.size > 0) {
chunks.push(evt.data);
}
}
stopRec.onclick = function stopRecording() {
if (recorder.state !== 'recording') {
this.disabled = true;
return;
}
// stop everything
recorder.stop(); // this will trigger exportVideo
clearInterval(switchInterval);
stopCanvasAnim();
a.style.display = b.style.display = 'none';
this.parentNode.innerHTML = "";
}
function exportVideo() {
// we've got everything
vid.src = URL.createObjectURL(new Blob(chunks));
}
var stopCanvasAnim = (function initCanvasDrawing() {
// some fancy drawings
var aCtx = canvases[0].getContext('2d'),
bCtx = canvases[1].getContext('2d');
var objects = [],
w = canvases[0].width,
h = canvases[0].height;
aCtx.fillStyle = bCtx.fillStyle = 'ivory';
for (var i = 0; i < 100; i++) {
objects.push({
angle: Math.random() * 360,
x: 100 + (Math.random() * w / 2),
y: 100 + (Math.random() * h / 2),
radius: 10 + (Math.random() * 40),
speed: 1 + Math.random() * 20
});
}
var stop = false;
var draw = function() {
aCtx.fillRect(0, 0, w, h);
bCtx.fillRect(0, 0, w, h);
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;
aCtx.drawImage(imgA, entity.x, entity.y, entity.radius, entity.radius);
bCtx.drawImage(imgB, entity.x, entity.y, entity.radius, entity.radius);
entity.angle++;
}
if (!stop) {
requestAnimationFrame(draw);
}
}
var imgA = new Image();
var imgB = new Image();
imgA.onload = function() {
draw();
startRecording();
};
imgA.crossOrigin = imgB.crossOrigin = 'anonymous';
imgA.src = "https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png";
imgB.src = "https://dl.dropboxusercontent.com/s/rumlhyme6s5f8pt/ABC.png";
return function() {
stop = true;
};
})();
<p>
<button id="stopRec" disabled>stop recording</button>
</p>
<canvas id="a"></canvas>
<canvas id="b"></canvas>
<video id="vid" controls></video>