WebRTC从画布卡塞发送流

时间:2018-06-01 07:55:04

标签: javascript canvas stream webrtc

嗯,这个问题很不寻常。我创建了Angular应用程序,通过WebRTC在两个对等方之间进行通信。 该架构很简单2个对等体,它们从摄像机发送视频流并从其他对等体接收流。简单而有效。

现在我想添加一些流处理,以便第一个对等我添加canvas元素,如下所示:

    this.localCameraVideoStream = document.createElement('video');
    this.localCameraVideoStream.srcObject = stream;
    this.localCameraVideoStream.muted = true;
    this.localCameraVideoStream.play();

    this.canvas = document.createElement('canvas');
    this.canvas.width = 1280;
    this.canvas.height = 720;
    this.canvasStream = this.canvas.captureStream();

    this.localVideoElement.nativeElement.srcObject = this.canvasStream;
    this.localVideoElement.nativeElement.muted = true;
    this.localVideoElement.nativeElement.play();
    this.redrawStreamToCanvas();

重绘方法将流从<video>元素绘制到canvas:

 private redrawStreamToCanvas(){
    const ctx = this.canvas.getContext('2d');
    const width = 1280;
    const height = 720;
    const combinedVideoStream = this.localCameraVideoStream;

    function drawVideo() {
      ctx.clearRect(0, 0, width, height);
      ctx.drawImage(combinedVideoStream, 0, 0, width, height);
      requestAnimationFrame(drawVideo);
    }

    requestAnimationFrame(drawVideo);
  }

只是为了清除任何疑问。 localCameraVideoStream是<video>元素,用于以<canvas><video>获取流的方式保存摄像机流。 画布是<canvas> localVideoElement只是.html中的<video>并显示当前的“本地”流。

问题是在本地预览中一切正常。当我将canvasStream发送给其他同行并在某些<video>上显示时,我只会得到一帧并且就是这样。

你知道什么是hapenning?奇怪的是,在预览中没有这个组合rtc连接也没问题。

1 个答案:

答案 0 :(得分:2)

这很可能是因为 Chrome 错误 [功能],一旦获得静音 <video>离开视口。

如果确实如此,这与MediaStream无关,而且只是在绘图到画布操作中发生:

&#13;
&#13;
var ctx = canvas.getContext('2d');
if ((videoin.buffered && !videoin.buffered.length) || videoin.paused) {
  videoin.onloadedmetadata = videoin.onplaying = begin;
} else {
  begin();
}

function begin() {
  videoin.onloadedmetadata = videoin.onplaying = null;
  canvas.width = videoin.videoWidth;
  canvas.height = videoin.videoHeight;
  drawToCanvas();
}

function drawToCanvas() {
  ctx.drawImage(videoin, 0, 0);
  requestAnimationFrame(drawToCanvas);
}
&#13;
body {
  margin-bottom: 100vh;
}
&#13;
<p>
  Scroll down until the &lt;video&gt; element be out.
</p>
<video crossorigin id="videoin" src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" muted autoplay></video>
<canvas id="canvas"></canvas>
&#13;
&#13;
&#13;

因此,如果您没有设置muted属性,那就可以了:

&#13;
&#13;
var ctx = canvas.getContext('2d');
if ((videoin.buffered && !videoin.buffered.length) || videoin.paused) {
  videoin.onloadedmetadata = videoin.onplaying = begin;
} else {
  begin();
}

function begin() {
  videoin.volume = 0; // does the same you'd say?
  videoin.onloadedmetadata = videoin.onplaying = null;
  canvas.width = videoin.videoWidth;
  canvas.height = videoin.videoHeight;
  drawToCanvas();
}

function drawToCanvas() {
  ctx.drawImage(videoin, 0, 0);
  requestAnimationFrame(drawToCanvas);
}
&#13;
body {
  margin-bottom: 100vh;
}
&#13;
<p>
  Scroll down until the &lt;video&gt; element be out.
</p>
<video crossorigin id="videoin" src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" autoplay></video>
<canvas id="canvas"></canvas>
&#13;
&#13;
&#13;

或者,如果你没有在文档中附加它,它也可以工作(在用户手势之后......)。

&#13;
&#13;
var ctx = canvas.getContext('2d');
var videoin = document.createElement('video');
videoin.onloadedmetadata = videoin.onplaying = begin;
videoin.muted = true; // even if 'muted'
videoin.src = 'https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm';

function begin() {
  videoin.onplay = null;
  canvas.width = videoin.videoWidth;
  canvas.height = videoin.videoHeight;
  drawToCanvas();
}

function drawToCanvas() {
  ctx.drawImage(videoin, 0, 0);
  requestAnimationFrame(drawToCanvas);
}
play_btn.onclick = e => {
  videoin.play();
}
&#13;
<button id="play_btn">click to start playing the video</button>
<p>
  This contains only the canvas element
</p>
<canvas id="canvas"></canvas>
&#13;
&#13;
&#13;

现在,我不能在这个答案中说你必须已经初始化了你的画布上下文(甚至可能已经画过它),然后才调用它{{1} } 方法。如果不这样做,将导致Firefox中的NS异常,而IIRC则符合规范。