在 webrtc 中创建和传输自定义媒体流

create and transmit custom mediastream in webrtc

我想使用 canvas 元素作为 webrtc 通信视频部分的 mediastreamsource,任何方向都会有帮助,搜索了网络,没有找到太多讨论这个主题的资源

* 长篇背景故事 *

问题,我不能直接从相机发送视频,这是我在显示之前处理视频(一些图像处理的东西,超出这个问题的范围)的要求的一部分。

之前,在对方的浏览器上,我没有直接使用<video>标签显示视频,而是对一个隐藏的canvas元素做了一些处理,然后将细节复制到另一个canvas(我使用了一个settimeout来继续绘制,这给了illusion of live video)。

现在,客户端希望在传输视频之前完成处理,所以我使用webrtc直接传递音频流(之前音频和视频均通过 webrtc 发送)。对于视频流,我有两个解决方案:

步骤:

  1. 在本地对等端处理视频,在隐藏 canvas 上绘制。简单的部分。

  2. 使用超时重复采集图像数据并传输
    a) 使用 websockets( yes, goes through server),它伴随着可怕的滞后和浏览器的最终崩溃。
    b) 使用 RTCDataChannel,它有更好的性能,但有时会无缘无故地失败。我还有其他几个问题(例如,由于发送 jpeg 而不是 webp,使用了额外的带宽)。

另一个主要问题是因为我正在使用超时:当我切换标签时,另一边的帧率下降。

那么,有什么方法可以使用隐藏的 canvas 作为媒体流源而不是我手动执行它吗?

mozCaptureStreamUntilEnded 将成为 Martin Thompson 正在为 WG 制定的提案的基础,以直接连接到 MediaStream。根据此处的评论,Firefox 中的解决方法是 mozCaptureStreamUntilEnded 来自从 MediaStream 捕获的 canvas 的馈送。一个丑陋的序列,这就是我们允许将 a 直接输出到 MediaStream 的部分原因(以及标准化 captureStream)。

请注意,将 mozCaptureStream(UntilEnded) 馈送到 PeerConnection 有一段时间中断了(部分原因是到目前为止它是非标准的);它已在 Firefox 36 中修复(预计 6 周后在发布频道上发布;下周将进入 Beta 版)。请参见错误 1097224 和错误 1081409

在 Chrome 上,Firefox 会采用令人难以置信的 hacky 方式将视频放入 window,然后截屏 window。我不建议这样做,因为它需要屏幕共享权限,选择 window,等等

Chrome(或 Firefox)的唯一其他选择是将视频帧保存为 JPEG(如您所述)并通过 DataChannel 发送。有效的 Motion-JPEG,但 JS 运行。帧率和质量(和延迟)将受到影响。您可能希望使用不可靠的通道,因为一旦出现错误,您可能会丢弃该帧并只解码下一帧(毕竟是 MJPEG)。另外,如果延迟太高,请减小帧大小!您需要估计端到端延迟;最好的方法是通过数据通道将解码时间反馈给发送方,并让它使用该数据包的接收时间来估计延迟。你更关心延迟的变化而不是绝对值!!

找到了一个可能的解决方案,至少对于 firefox,它正在使用 canvas 并捕获它的流并使用 canvas.captureStream()

传输它
// Find the canvas element to capture
var canvasElt = document.getElementsByTagName("canvas")[0];

// Get the stream
var stream = canvasElt.captureStream(25); // 25 FPS

// Do things to the stream
// E.g. Sent it to another computer using a RTCPeerConnection
//      pc is a RTCPeerConnection created elsewhere
pc.addStream(stream);