WebRTC отправка потока из джемов на холсте - PullRequest
0 голосов
/ 01 июня 2018

Ну, проблема очень необычная.Я создаю приложение 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>элемент на холст:

 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 - это <canvas> localVideoElement - это просто <video> в .html, который отображает текущий «локальный» поток.

Проблема заключается в том, что в локальном предварительном просмотре все работает правильно.Когда я посылаю canvasStream другому партнеру и показываю его на каком-то <video>, я получаю только один кадр, вот и все.

Вы знаете, что происходит?Странно, что в предпросмотре все в порядке, и без этой комбинации rtc-соединение также нормально.

1 Ответ

0 голосов
/ 02 июня 2018

Это, скорее всего, из-за ошибки [функция] Chrome , из-за которой отключается <video>, как только они выходят из области просмотра.

Если это действительно так, это не имеет ничего общего с MediaStream, и уже происходит в операции рисование на холст :

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);
}
body {
  margin-bottom: 100vh;
}
<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>

Так что, если вы не установите свойство muted, оно будет работать:

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);
}
body {
  margin-bottom: 100vh;
}
<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>

Или даже, если вы не добавили его в документ, это также сработало бы (после пользовательского жеста ..).

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();
}
<button id="play_btn">click to start playing the video</button>
<p>
  This contains only the canvas element
</p>
<canvas id="canvas"></canvas>

Теперь я не могу не сказать в этом ответе, что вы должны уже инициализировали свой контекст холста (и даже, возможно, имеетеуже нарисовано на нем) перед вызовом метода captureStream.Невыполнение этого требования приведет к исключению NS в Firefox, и IIRC соответствует спецификациям.

...