- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我一直在阅读 this article用于信号解决方案。作者提到了在建立连接时使用 RTCDataChannel 发送信号。
Using RTCDataChannel for signaling
A signaling service is required to initiate a WebRTC session.
However, once a connection has been established between two peers, RTCDataChannel could, in theory, take over as the signaling channel. This might reduce latency for signaling — since messages fly direct — and help reduce signaling server bandwidth and processing costs. We don't have a demo, but watch this space!
既然连接已经建立,为什么还需要信号?
最佳答案
每一方最初都声明要发送哪些音频和/或视频轨道,以便可以打开正确数量的端口,并可以确定对双方都适用的分辨率和格式。需要一个信令 channel 来将生成的 SDP 提议/答案以及每个端口的细流 ICE 候选者发送到另一端。
连接后,如果您不理会此设置 - 基本上永远不会向连接添加轨道、删除任何轨道或显着更改轨道属性 - 那么您将不再需要信令服务器。
但是,如果您确实更改了这些内容中的任何一项,则需要重新协商,这就像它听起来的那样:与第一轮非常相似的信号 channel 上的另一轮。 p>
添加轨道的原因可能是第二个摄像头、另一个视频源(可能来自另一个参与者),或者可能是屏幕共享,诸如此类。
这篇文章是正确的,可以使用数据通道。这是 a demo ! (目前仅限 Firefox。)
这篇文章关于需要信号服务的说法是错误的——前提是你有另一种发现方式——正如这个演示所证明的那样。
初始连接仅用于聊天,但任何一方都可以推送以将视频添加到混音中。重新协商是通过数据通道完成的(因为没有信令服务器!)
fiddle 使用说明:
Offer
按钮并复制报价。addTrack
!)addTrack
,另一端应该会显示视频。addTrack
,您应该可以双向播放视频。var dc = null, sc = null, pc = new mozRTCPeerConnection(), live = false;
pc.onaddstream = e => v2.mozSrcObject = e.stream;
pc.ondatachannel = e => dc? scInit(sc = e.channel) : dcInit(dc = e.channel);
v2.onloadedmetadata = e => { log("Face time!"); };
function addTrack() {
navigator.mediaDevices.getUserMedia({video:true, audio:true})
.then(stream => pc.addStream(v1.mozSrcObject = stream));
}
pc.onnegotiationneeded = e => {
pc.createOffer().then(d => pc.setLocalDescription(d)).then(() => {
if (live) sc.send(JSON.stringify({ "sdp": pc.localDescription }));
}).catch(failed);
};
function scInit() {
sc.onmessage = e => {
var msg = JSON.parse(e.data);
if (msg.sdp) {
var desc = new mozRTCSessionDescription(JSON.parse(e.data).sdp);
if (desc.type == "offer") {
pc.setRemoteDescription(desc).then(() => pc.createAnswer())
.then(answer => pc.setLocalDescription(answer)).then(() => {
sc.send(JSON.stringify({ "sdp": pc.localDescription }));
}).catch(failed);
} else {
pc.setRemoteDescription(desc).catch(failed);
}
} else if (msg.candidate) {
pc.addIceCandidate(new mozRTCIceCandidate(msg.candidate)).catch(failed);
}
};
}
function dcInit() {
dc.onopen = () => { live = true; log("Chat!"); };
dc.onmessage = e => log(e.data);
}
function createOffer() {
button.disabled = true;
dcInit(dc = pc.createDataChannel("chat"));
scInit(sc = pc.createDataChannel("signaling"));
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(failed);
pc.onicecandidate = e => {
if (e.candidate) return;
if (!live) {
offer.value = pc.localDescription.sdp;
offer.select();
answer.placeholder = "Paste answer here";
} else {
sc.send(JSON.stringify({ "candidate": e.candidate }));
}
};
};
offer.onkeypress = e => {
if (e.keyCode != 13 || pc.signalingState != "stable") return;
button.disabled = offer.disabled = true;
var obj = { type:"offer", sdp:offer.value };
pc.setRemoteDescription(new mozRTCSessionDescription(obj))
.then(() => pc.createAnswer()).then(d => pc.setLocalDescription(d))
.catch(failed);
pc.onicecandidate = e => {
if (e.candidate) return;
if (!live) {
answer.focus();
answer.value = pc.localDescription.sdp;
answer.select();
} else {
sc.send(JSON.stringify({ "candidate": e.candidate }));
}
};
};
answer.onkeypress = e => {
if (e.keyCode != 13 || pc.signalingState != "have-local-offer") return;
answer.disabled = true;
var obj = { type:"answer", sdp:answer.value };
pc.setRemoteDescription(new mozRTCSessionDescription(obj)).catch(failed);
};
chat.onkeypress = e => {
if (e.keyCode != 13) return;
dc.send(chat.value);
log(chat.value);
chat.value = "";
};
var log = msg => div.innerHTML += "<p>" + msg + "</p>";
var failed = e => log(e.name + ": " + e.message + " line " + e.lineNumber);
<video id="v1" height="120" width="160" autoplay muted></video>
<video id="v2" height="120" width="160" autoplay></video><br>
<button id="button" onclick="createOffer()">Offer:</button>
<textarea id="offer" placeholder="Paste offer here"></textarea><br>
Answer: <textarea id="answer"></textarea><br>
<button id="button" onclick="addTrack()">AddTrack</button>
<div id="div"></div><br>
Chat: <input id="chat"></input><br>
关于javascript - RTCDataChannel 信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30016613/
我正在尝试学习 WebRTC 。我复制了一些代码,我得到了这个错误: 未能在“RTCDataChannel”上执行“发送”:RTCDataChannel.readyState 不是“打开” 任何人都可
我开了一个 RTCDataChannel ,并且默认情况下它似乎处于不可靠模式。 我想将它配置为可靠以保证数据包传送,但是 RTCDataChannelInit配置似乎没有这个设置。 dictiona
我正在尝试关注 this example创建数据 channel 。 对于我使用 websockets 的信号,它的行为如下: User A joins User B joins User B ask
我一直在阅读 this article用于信号解决方案。作者提到了在建立连接时使用 RTCDataChannel 发送信号。 Using RTCDataChannel for signaling A
我在使用 RTCDataChannel 时遇到了一个奇怪的问题。 我正在对 WebRTC 进行一些研究,并且我已经在进行 WebRTC 音频/视频聊天。现在我想使用 RTCDataChannel 添加
我已通过 RTC 数据通道连接了两个用户。这可行,但我想监视它生成的流量,例如 1Mbit/s。有办法得到这个吗? 其动机是一个用户创建内容,而另一方则镜像此内容,一种远程支持应用程序。该用例要求内容
Mozilla MDN声明单个 RTCPeerConnection 可以处理“理论上”65,534 个数据通道,但声明该限制将因浏览器而异。我无法找到有关 Chrome 中允许的最大 RTCDataC
我正在使用 RTCDataChannel。但是我通过 channel 发送的消息在另一个对等端没有收到。 代码如下: let audioConstraint : RTCPair = R
我正在尝试用 C++ 创建一个简单的 webrtc 服务器,所以我可以在浏览器和服务器之间传输数据(不需要点对点),我只需要 RTCdatachannel,不涉及媒体或音频。 我试过这个例子: htt
首先,我只是明白它不会是纯粹的 p2p 功能,它根本不是套接字,出于安全和 DDOS 目的。 但是我很难弄清楚提供、回答、SDP、ICE、STUN 等内容。似乎有很多抽象和要求。 这是否意味着总是需要
我正在尝试通过 WebRTC 分块发送文件,我想知道是否可以创建一个回调函数,以便在 RTCDataChannel.send() 完成发送文件的每个 block 后调用文件。 RTCDataChann
我正在尝试通过 RTCDataConnection 将字符串从一个浏览器窗口传递到另一个浏览器窗口。 有很多这种工作的例子,比如这里的一个: https://gitlab.com/lesmana/we
我遵循了有关 WebRTC 的整个教程并实现了一个简单的 p2p 聊天。我的信令服务器在 localhost:9090 上工作。当我尝试发送消息时,我收到: RTCDataChannel.readyS
我正在尝试关注 this example by Dan Ristic用于 RTCDataChannel 浏览器与 Google 的 p2p 通信 Channel API用于发信号。它似乎默默地失败了
我正在尝试使用 WebRTC's adapter.js 通过 RTCPeerConnection 和 RTCDataChannel 发送文本,但出现以下错误: Uncaught InvalidStat
我正在尝试实现 RTCDataChannel (webRTC)。 它在 Firefox 中运行良好,但在 chrome 中运行不佳。 Chrome 和 Firefox 都是最新版本。 Chrome 中
我是一名优秀的程序员,十分优秀!