通过RTC数据通道发送图像数据

Mar*_*S95 6 javascript canvas webrtc

我试图通过a发送图像数据Data Channel,但它无法正常工作.刚从中获取数据时ctx.getImageData,我会"[Object ImageData]"在另一侧收到一个字符串.仅将数据块转换为blob会导致错误:Uncaught NetworkError: Failed to execute 'send' on 'RTCDataChannel': Could not send data.尝试将其转换为时,我得到了同样的错误ArrayBuffer.我该怎么做?

Goh*_*n67 10

这是我刚刚写的一个演示:http://richard.to/projects/datachannel-demo/

请注意,我正在使用本地频道,我只是显示图像而不是渲染到画布上.这应该很容易做到.实际与远程设备通信时可能会遇到问题.我还没有测试过.它也只适用于Chrome.但是应该直截了当地在Firefox中工作.


这一点有点棘手,因为WebRTC的内容在不断变化.更不用说Firefox和Chrome的工作方式略有不同.

我将专注于Chrome,因为您收到的错误消息似乎与Chrome有关Uncaught NetworkError: Failed to execute 'send' on 'RTCDataChannel': Could not send data.此处描述了此问题:https://groups.google.com/forum/#!topic/discuss-webrtc/U927CZaCdKU

这是由于RTP data channel利率有限.我给你提到的链接3 KB/sec,在我的测试中听起来是正确的.

好消息是,在Chrome 31之后,您可以使用基于SCTP的数据通道.请参阅此处:https://groups.google.com/forum/#!topic/discuss-webrtc/y2A97iCByTU.

这意味着代替:

window.localPeerConnection = new webkitRTCPeerConnection(servers,
    {optional: [{RtpDataChannels: true}]});
Run Code Online (Sandbox Code Playgroud)

你可以做这样的事情(可能会删除第二个参数):

window.localPeerConnection = new webkitRTCPeerConnection(servers,
    {optional: []});
Run Code Online (Sandbox Code Playgroud)

我相信你仍然会受到限制,但现在确实如此64kbps.我可能错了这个号码.找不到我从中读取的链接.

关于SCTP通道的一个好处是,您可以使用可靠的数据连接(TCP)而不是不可靠(UDP),并且数据按顺序发送.我对此并不积极.再一次,找不到链接.

现在,正因为如此,似乎你仍然需要将数据分块.您无法在Chrome中同时发送所有内容.你可以在Firefox中做到这一点.

您需要知道的第二件事blob是Chrome目前不支持数据.至少在常规Chrome 32中.这意味着如果我们想要使用Chrome,我们必须以文本形式发送数据.

所以我们能做的就是从base64开始转换我们的图像数据canvas.toDataURL().这是一个如何工作的例子:

var canvas = document.createElement('canvas');
canvas.width = startimage.width;
canvas.height = startimage.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(startimage, 0, 0, startimage.width, startimage.height);
var data = canvas.toDataURL("image/jpeg");
Run Code Online (Sandbox Code Playgroud)

现在我们有了数据,我们只需要打破bas64字符串:

这是我在上面的演示中使用的分块数据的实现:

function sendData() {
  trace("Sending data");
  sendButton.disabled = true;
  var canvas = document.createElement('canvas');
  canvas.width = startimage.width;
  canvas.height = startimage.height;
  var ctx = canvas.getContext('2d');
  ctx.drawImage(startimage, 0, 0, startimage.width, startimage.height);

  var delay = 10;
  var charSlice = 10000;
  var terminator = "\n";
  var data = canvas.toDataURL("image/jpeg");
  var dataSent = 0;
  var intervalID = 0;

  intervalID = setInterval(function(){
    var slideEndIndex = dataSent + charSlice;
    if (slideEndIndex > data.length) {
      slideEndIndex = data.length;
    }
    sendChannel.send(data.slice(dataSent, slideEndIndex));
    dataSent = slideEndIndex;
    if (dataSent + 1 >= data.length) {
      trace("All data chunks sent.");
      sendChannel.send("\n");
      clearInterval(intervalID);
    }
  }, delay);
}
Run Code Online (Sandbox Code Playgroud)

实现非常简单,基本上只是使用setInterval.你可以搞乱切片大小和延迟参数.我们还需要设置一个终结符来知道消息何时完成.我只是用了一个\n角色.

以下是接收器的实现方式.基本上跟踪数据,直到它收到终结者字符,我刚刚使用换行符.

function handleMessage(event) {
  if (event.data == "\n") {
    endimage.src = imageData;
    trace("Received all data. Setting image.");
  } else {
    imageData += event.data;
    //trace("Data chunk received");
  }
}
Run Code Online (Sandbox Code Playgroud)

希望这个对你有帮助.研究它很有趣.不确定这是否是通过WebRTC发送图像的理想解决方案.那里有一些做P2P文件传输和演示的演示.我想这取决于你的目的.