我正在尝试通过Data Channel
发送图像数据,但它无效。
刚刚从ctx.getImageData
获取数据时,我会在另一端收到字符串"[Object ImageData]"
。仅将数据片段转换为blob会导致错误:Uncaught NetworkError: Failed to execute 'send' on 'RTCDataChannel': Could not send data
。尝试将其转换为ArrayBuffer
时出现同样的错误。我该怎么做?
答案 0 :(得分: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}]});
你可以这样做(可能会删除第二个参数):
window.localPeerConnection = new webkitRTCPeerConnection(servers,
{optional: []});
我相信你仍然会受到限制,但现在是64kbps
。我可能错了这个号码。找不到我从中读取的链接。
关于SCTP通道的一个好处是,您可以使用可靠的数据连接(TCP)而不是不可靠(UDP),并且数据按顺序发送。我对此并不积极。再一次,找不到链接。
现在,正因为如此,你似乎仍然需要将数据分块。您无法在Chrome中同时发送所有内容。你可以在Firefox中做到这一点。
您需要知道的第二件事是Chrome目前不支持blob
数据。至少在常规Chrome 32中。这意味着如果我们想要使用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文件传输和演示的演示。我想这取决于你的目的。
答案 1 :(得分:1)
此异常是由超出会话中约定的带宽限制引起的。
创建商品的答案时,您必须编辑属于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。
答案 2 :(得分:1)
这实际上是对斯威夫特答案的评论,但我没有足够的声誉来评论。因此:当您使用RTP数据通道时,您将在sdp中看到应用程序特定(AS)带宽(即b = AS:30)。 30是默认值。您可以使用任意值替换它(1638400可以使用,但是如果您想进一步推动它,则必须进行试验和错误)。
但是,初始化SCTP数据通道时,您的sdp中将看不到任何AS带宽。这很好。你不必担心它。