<canvas> 后取回视频格式

Get back video format after <canvas>

有没有办法从网络摄像头 (getUserMedia) 获取视频,将其传递给 canvas,对该视频制作一些效果并返回视频格式(例如 mp4)?

我正在寻找一种仅在客户端完成的方法。而且它应该是一个实时过程。

是的,你可以,在 modern browsers, but you'll loose every audio stream (),我认为 mp4 要求还没有出现,你不应该等待 (该死的版税) 目前只有 webm 或 ogv 导出可用。

您可以使用 MediaRecorder and the canvas.captureStream() 方法。

var mediaRecorder = new MediaRecorder(canvas.captureStream(30));

这是一个示例代码(仅适用于最新的 FF 和 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 
  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>

请注意,由于 webm 视频格式不支持透明度,每个透明像素将被设置为不透明的黑色。