Ответ 1
WebRTC не разрешает обнаружение (и не должен).
WebRTC знает, как разговаривать напрямую с другим партнером без сервера сигнализации, но он не знает, как обнаружить другого партнера. Discovery - это неотъемлемая проблема, поэтому я немного озадачен тем, что люди ожидают, что WebRTC решит ее для них.
Подумайте об этом: как вы меня назовете? Как вы собираетесь направить свой компьютер, чтобы начать со мной контакт, а не с миллиардом других людей? По GPS-координатам? адрес электронной почты? Статический IP? ИРЦ? мгновенное сообщение? facebook? номер телефона?
Также, как я узнаю, когда вы позвоните? Будет ли мой компьютер "звонить"? Есть сотни способов решить эту проблему с помощью обычных веб-технологий, поэтому WebRTC будет делать вам плохую услугу, если она продиктована определенным образом. Контекст вашего приложения, скорее всего, будет информировать о лучших способах общения. Возможно, я встречаюсь с вами в каком-то онлайн-форуме или виртуальной комнате в онлайн-игре?
С технической точки зрения, вам не нужен сервер сигнализации с WebRTC, если у вас есть другие способы получить предложение SDP (кусок текста) вашему сверстнику и получить ответ обратной SDP в ответ, это по телефону, IM, irc, электронной почте или перевозчику. Попробуйте это в Chrome или Firefox: https://jsfiddle.net/nnc13tw2 - нажмите "Предложение" (подождите до 20 секунд), отправьте результат своему другу, который вставляет его в одно и то же поле на их конце и нажмите Enter, и попросите их отправить ответ, который вы вставляете в поле ответа, и нажмите Enter. Теперь вы должны быть подключены, и никакой подключающий сервер не был задействован.
Почему работает jsfiddle: он упаковывает всех кандидатов ICE в SDP, что может занять несколько секунд, чтобы дать вам все, что вам нужно за один раз.
Некоторые дополнительные функции, такие как изменение количества видеоисточников в середине вызова и т.д., также требуют сигнализации, но как только звонок был установлен, приложение может использовать свои собственные каналы передачи данных для любых дальнейших потребностей в сигнализации между одноранговыми узлами.
В Stackoverflow теперь требуется включить код для ссылки на jsfiddle, поэтому Я мог бы также включить его здесь (хотя, если вы используете Chrome, используйте скрипку выше, поскольку доступ к фотокамере не работает в фрагментах):
var config = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }]};
var dc, pc = new RTCPeerConnection(config);
pc.onaddstream = e => v2.srcObject = e.stream;
pc.ondatachannel = e => dcInit(dc = e.channel);
v2.onloadedmetadata = e => log("Connected!");
var haveGum = navigator.mediaDevices.getUserMedia({video:true, audio:true})
.then(stream => pc.addStream(v1.srcObject = stream))
.catch(failed);
function dcInit() {
dc.onopen = () => log("Chat!");
dc.onmessage = e => log(e.data);
}
function createOffer() {
button.disabled = true;
dcInit(dc = pc.createDataChannel("chat"));
haveGum.then(() => pc.createOffer()).then(d => pc.setLocalDescription(d)).catch(failed);
pc.onicecandidate = e => {
if (e.candidate) return;
offer.value = pc.localDescription.sdp;
offer.select();
answer.placeholder = "Paste answer here";
};
};
offer.onkeypress = e => {
if (!enterPressed(e) || pc.signalingState != "stable") return;
button.disabled = offer.disabled = true;
var desc = new RTCSessionDescription({ type:"offer", sdp:offer.value });
pc.setRemoteDescription(desc)
.then(() => pc.createAnswer()).then(d => pc.setLocalDescription(d))
.catch(failed);
pc.onicecandidate = e => {
if (e.candidate) return;
answer.focus();
answer.value = pc.localDescription.sdp;
answer.select();
};
};
answer.onkeypress = e => {
if (!enterPressed(e) || pc.signalingState != "have-local-offer") return;
answer.disabled = true;
var desc = new RTCSessionDescription({ type:"answer", sdp:answer.value });
pc.setRemoteDescription(desc).catch(failed);
};
chat.onkeypress = e => {
if (!enterPressed(e)) return;
dc.send(chat.value);
log(chat.value);
chat.value = "";
};
var enterPressed = e => e.keyCode == 13;
var log = msg => div.innerHTML += "<p>" + msg + "</p>";
var failed = e => log(e);
<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><div id="div"></div>
Chat: <input id="chat"></input><br>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>