我正在尝试通过Data Channel发送图像数据,但它不工作。当我刚从ctx.getImageData获取数据时,我在另一端收到一个字符串"[Object ImageData]"。仅将数据块转换为blob会导致错误:Uncaught NetworkError: Failed to execute 'send' on 'RTCDataChannel': Could not send data。在尝试将其转换为ArrayBuffer时,我得到了相同的错误。我该怎么做呢?
发布于 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。
这意味着不是这样:
window.localPeerConnection = new webkitRTCPeerConnection(servers,
{optional: [{RtpDataChannels: true}]});您可以这样做(可能可以删除第二个参数):
window.localPeerConnection = new webkitRTCPeerConnection(servers,
{optional: []});我相信你仍然会受到价格限制,但现在是64kbps。我可能把这个数字弄错了。找不到我读到的链接。
SCTP通道的一个好处是,您可以使用可靠的数据连接(TCP)而不是不可靠的(UDP),这样数据就会按顺序发送。我对此不是很肯定。再一次,找不到链接。
现在,正因为如此,你似乎还得把你的数据分块。在Chrome中,你不能同时发送所有内容。不过你可以在Firefox中做到这一点。
你需要知道的第二件事是Chrome目前不支持blob数据。至少在普通的Chrome32中是这样。这意味着如果我们想使用Chrome,我们必须以文本的形式发送数据。
所以我们能做的就是从canvas.toDataURL()开始把图像数据转换成base64格式。下面是一个如何工作的示例:
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字符串:
下面是我在上面的演示中使用的数据分块的实现:
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字符。
下面是接收器的实现方式。基本上,它会一直跟踪数据,直到它接收到结束符,我刚刚使用了换行符。
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文件传输之类的东西。我想这取决于你的目的。
发布于 2014-08-03 05:43:36
此异常是由于超出会话中约定的带宽限制而导致的。
创建报价答案时,您必须编辑作为PeerConnection一部分的sessionDescription对象,以更改包含以kb/s为单位的最大带宽的b=AS:参数:
var Bandwidth = 5000;
sessionDescription.sdp = sessionDescription.sdp.replace(/b=AS:([0-9]+)/g, 'b=AS:'+Bandwidth+'\r\n');
alert(JSON.stringify(sessionDescription));默认情况下,该值为30kb/s。
发布于 2015-04-09 02:41:40
这实际上是answer的回答,但我没有足够的名气来评论。因此:当您使用RTP数据通道时,您将在sdp (即b=AS:30)中看到特定于应用的(AS)带宽。默认值为30。您可以将其替换为任意值(1638400可以,但如果您想进一步推动它,您将不得不反复尝试)。
但是,当您初始化SCTP数据通道时,您在sdp中看不到任何AS带宽。这就很好了。你不必担心这个问题。
https://stackoverflow.com/questions/21585681
复制相似问题