嗯,这个问题很不寻常。我创建了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连接也没问题。
答案 0 :(得分:2)
这很可能是因为 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);
}
&#13;
body {
margin-bottom: 100vh;
}
&#13;
<p>
Scroll down until the <video> 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;
因此,如果您没有设置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);
}
&#13;
body {
margin-bottom: 100vh;
}
&#13;
<p>
Scroll down until the <video> 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;
或者,如果你没有在文档中附加它,它也可以工作(在用户手势之后......)。
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;
现在,我不能在这个答案中说你必须已经初始化了你的画布上下文(甚至可能已经画过它),然后才调用它{{1} } 方法。如果不这样做,将导致Firefox中的NS异常,而IIRC则符合规范。