首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过RTC数据通道发送图像数据

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

Stack Overflow用户
提问于 2014-02-06 02:38:11
回答 3查看 9.1K关注 0票数 6

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-02-06 08:13:54

这是我刚才写的一个演示: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,在我的测试中,这听起来是对的。

好消息是,在Chrome31之后,你可以使用基于SCTP的数据通道。请看这里:https://groups.google.com/forum/#!topic/discuss-webrtc/y2A97iCByTU

这意味着不是这样:

代码语言:javascript
复制
window.localPeerConnection = new webkitRTCPeerConnection(servers,
    {optional: [{RtpDataChannels: true}]});

您可以这样做(可能可以删除第二个参数):

代码语言:javascript
复制
window.localPeerConnection = new webkitRTCPeerConnection(servers,
    {optional: []});

我相信你仍然会受到价格限制,但现在是64kbps。我可能把这个数字弄错了。找不到我读到的链接。

SCTP通道的一个好处是,您可以使用可靠的数据连接(TCP)而不是不可靠的(UDP),这样数据就会按顺序发送。我对此不是很肯定。再一次,找不到链接。

现在,正因为如此,你似乎还得把你的数据分块。在Chrome中,你不能同时发送所有内容。不过你可以在Firefox中做到这一点。

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

所以我们能做的就是从canvas.toDataURL()开始把图像数据转换成base64格式。下面是一个如何工作的示例:

代码语言:javascript
复制
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");

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

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

代码语言:javascript
复制
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);
}

它的实现非常简单,基本上只需要使用setInterval。您可以随意调整切片大小和延迟参数。此外,我们还需要设置一个终止符,以了解消息何时结束。我刚刚使用了一个\n字符。

下面是接收器的实现方式。基本上,它会一直跟踪数据,直到它接收到结束符,我刚刚使用了换行符。

代码语言:javascript
复制
function handleMessage(event) {
  if (event.data == "\n") {
    endimage.src = imageData;
    trace("Received all data. Setting image.");
  } else {
    imageData += event.data;
    //trace("Data chunk received");
  }
}

希望这能对你有所帮助。研究它很有趣。不确定这是否是通过WebRTC发送图像的理想解决方案。有一些演示可以做P2P文件传输之类的东西。我想这取决于你的目的。

票数 10
EN

Stack Overflow用户

发布于 2014-08-03 05:43:36

此异常是由于超出会话中约定的带宽限制而导致的。

创建报价答案时,您必须编辑作为PeerConnection一部分的sessionDescription对象,以更改包含以kb/s为单位的最大带宽的b=AS:参数:

代码语言:javascript
复制
var Bandwidth = 5000;
sessionDescription.sdp = sessionDescription.sdp.replace(/b=AS:([0-9]+)/g, 'b=AS:'+Bandwidth+'\r\n');
alert(JSON.stringify(sessionDescription));

默认情况下,该值为30kb/s。

票数 1
EN

Stack Overflow用户

发布于 2015-04-09 02:41:40

这实际上是answer的回答,但我没有足够的名气来评论。因此:当您使用RTP数据通道时,您将在sdp (即b=AS:30)中看到特定于应用的(AS)带宽。默认值为30。您可以将其替换为任意值(1638400可以,但如果您想进一步推动它,您将不得不反复尝试)。

但是,当您初始化SCTP数据通道时,您在sdp中看不到任何AS带宽。这就很好了。你不必担心这个问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21585681

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档