Невозможно создать RTCIceCandidate из строки-кандидата

#javascript #google-chrome #webrtc

#javascript #google-chrome #webrtc

Вопрос:

Chrome.

Строка-кандидат ICE, созданная на компьютере A (берется непосредственно из атрибута SDP «кандидат»):

 candidate:2999745851 1 udp 2122260223 192.168.X.1 65398 typ host generation 0 ufrag XBYY network-id 2
  

Теперь это передается через сигнализацию, которая будет получена на компьютере B.

компьютер B получил (iceStr):

 candidate:2999745851 1 udp 2122260223 192.168.X.1 65398 typ host generation 0 ufrag XBYY network-id 2
  

и пытается let candidate = new RTCIceCandidate(iceStr)

Это приводит к

Ошибка типа: не удалось создать ‘RTCIceCandidate’: не удается преобразовать в словарь.

Компьютер B делает это для выполнения

 addIceCandidate(candidate) 
  

в объекте RTCPeerConnection.

тем не менее, из-за предыдущей ошибки невозможно продолжить.

Воспроизводимый пример

  <script type="text/javascript">
 let c ='candidate:2445384676 1 udp 2122194687 192.168.1.26 57088 typ host generation 0 ufrag z1J2 network-id 1 network-cost 10';
 let candidate = new RTCIceCandidate(c);
</script>
  

Идеи?

Все официальные примеры кода и документы предписывают отправлять этот самый параметр удаленному узлу. https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/onicecandidate

Тогда возникает некоторая путаница с устареванием (похоже, созданным под капотом другими функциями) и кодировкой JSON, так какая из них это.

Из официальных примеров: https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling

     function handleNewICECandidateMsg(msg) {
  var candidate = new RTCIceCandidate(msg.candidate);

  myPeerConnection.addIceCandidate(candidate)
    .catch(reportError);
}
  

Значение, похоже, также передается напрямую var candidate = new RTCIceCandidate(msg.candidate); , что заканчивается бесполезным упражнением (та же ошибка).

ОБНОВЛЕНИЕ: похоже, что API понимает только ОБЪЕКТ String (что довольно сложно, учитывая, что СОБЫТИЕ содержит примитивный тип!), т. Е. Воспроизводимый образец

     <script type="text/javascript">
 let c = new String('candidate:2445384676 1 udp 2122194687 192.168.1.26 57088 typ host generation 0 ufrag z1J2 network-id 1 network-cost 10');
 let candidate = new RTCIceCandidate(c);
</script>
  

Но даже тогда Chrome выдает исключение

Ошибка типа: не удалось создать ‘RTCIceCandidate’: sdpMid и sdpMLineIndex оба равны нулю.

Похоже, есть и другие «сомнительные» вещи..например, предложение WebRTC содержит символы новой строки, зависящие от платформы.

RTCSessionDescription не может быть создан непосредственно из предложения SDP, возвращаемого из события, поскольку это ПРИМИТИВНЫЙ тип, а RTCSessionDescription() хочет получить ОБЪЕКТ String . Кроме того, примитивный тип не может быть легко преобразован в String, поскольку он содержит новые строки, зависящие от платформы, и, следовательно, простая новая строка (SDP) приводит к искаженному объекту String .

кто-нибудь?

ОБНОВЛЕНИЕ В случае предложения WebRTC в документации не указано, что необходимо предоставить явный объект JSON для RTCSessionDescription, содержащий как тип (строка lame ‘offer’), так и поля SDP. Что неявно вынуждает использовать JSON (неэффективное кодирование) в первую очередь на протяжении всего процесса передачи сигналов. (если бы кто-то не смог самостоятельно восстановить хромые поля, но тогда это повсеместно противоречит принципу черного ящика)

Ответ №1:

Вы пытаетесь использовать только строку-кандидата вместо полного объекта, который также включает свойства sdpMid и sdpMLineIndex, см. https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate

Вы можете создать объект RTCIceCandidate как

 new RTCIceCandidate({
  candidate: 'candidate:2445384676 1 udp 2122194687 192.168.1.26 57088 typ host generation 0 ufrag z1J2 network-id 1 network-cost 10',
  sdpMid: 'something', // don't make it up, you get this in onicecandidate
  sdpMLineIndex: 12345, // don't make it up, you get this in onicecandidate
})
  

или вы вызываете

 pc.addIceCandidate({  
  candidate: 'candidate:2445384676 1 udp 2122194687 192.168.1.26 57088 typ host generation 0 ufrag z1J2 network-id 1 network-cost 10',
  sdpMid: 'something', // don't make it up, you get this in onicecandidate
  sdpMLineIndex: 12345, // don't make it up, you get this in onicecandidate
})
  

То же самое относится к объектам RTCSessionDescription.

Комментарии:

1. Давайте придержим наших лошадей. ТОГДА документация, ПО КРАЙНЕЙ МЕРЕ, сбивает с толку. В нем указано как в образцах, так И в письменной форме: «(Удаленный одноранговый узел, получив кандидата, добавит кандидата в свой пул кандидатов, вызвав addIceCandidate() , передавая строку кандидата, которую вы передали с помощью сервера сигнализации.) » Нигде это даже не предполагает необходимости передачи дополнительных полей. ИЛИ использование toJSON() для того, чтобы эти поля были сериализованы, если бы, например, НЕ предпочитали JSON над BER.

2. Хотя это может сработать, официальные образцы / учебные пособия не выполняют никакой такой «магии» и не используют toJSON() для включения дополнительного поля. Они также не предполагают, что объект JSON должен быть передан в конструктор.

3. developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/… в выделенном разделе указано, что строка должна быть разделена. Нигде не указывается необходимость или где должны быть найдены параметры sdpMid и sdpMLineIndex.

4. ЕСЛИ авторы документов должны подтвердить, что «строка должна быть обменена», они должны, по крайней мере, предложить обмен РЕЗУЛЬТАТОМ JSON.stringify(), который действительно выдает СТРОКУ, содержащую необходимые поля. ИЛИ что требуются дополнительные поля, если разработчики не использовали JSON. ЭТА информация нигде не найдена и не присутствует в примерах кода.

5. руки, полные работы (как и у всех нас), попытаются это сделать, как только мы пройдем текущий запуск реализации.