2015-07-06 2 views
1

Я пытаюсь реализовать webRTC с API, доступными в браузере. Я использую этот учебник в качестве своего гида: https://www.webrtc-experiment.com/docs/WebRTC-PeerConnection.htmlwebRTC audio работает только в одном направлении

Вот что я сейчас делаю. Сначала я получаю аудиоэлемент на странице. У меня также есть переменная audioStream для хранения потока, который я получаю от navigator.webkitGetUserMedia, когда вызывающая кнопка нажата инициирующим пользователем или когда нажатие кнопки ответа получает пользователь-получатель. Затем переменная для сохранения текущего вызова.

var audio = document.querySelector('audio'); 
var audioStream; 
var call = {}; 

Тогда у меня есть следующие настройки:

var iceServers = [ 
    { url: 'stun:stun1.l.google.com:19302' }, 
    { url: 'turn:numb.viagenie.ca', credential: 'muazkh', username: '[email protected]' } 
]; 

var sdpConstraints = { 
    optional: [], 
    mandatory: { 
     OfferToReceiveAudio: true, 
     OfferToReceiveVideo: false 
    } 
}; 

var DtlsSrtpKeyAgreement = { 
    DtlsSrtpKeyAgreement: true 
}; 

На странице загрузки создать новый узел:

var peer = new webkitRTCPeerConnection({ 
    'iceServers': iceServers 
}); 

На событие потока я просто назначить событие на вызов переменная.

peer.onaddstream = function(event){ 
    call = event; 
}; 

На мероприятии, посвященном событию на льду, я отправляю кандидата в суд.

peer.onicecandidate = function(event){ 

    var candidate = event.candidate; 

    if(candidate){ 
     SocketService.emit('message', { 
      'conversation_id': me.conversation_id, 
      'targetUser': to, 
      'candidate': candidate 
     }); 
    } 

    if(typeof candidate == 'undefined'){ 
     send_SDP(); 
    } 

}; 

Как только состояние сбора завершено, я отправляю SDP.

peer.ongatheringchange = function(e){ 

    if(e.currentTarget && e.currentTarget.iceGatheringState === 'complete'){ 

     send_SDP(); 
    } 
}; 

Что делает метод send_SDP это отправить локальное описание пиру.

function send_SDP(){ 
    SocketService.emit('message', { 
     'conversation_id': me.conversation_id, 
     'targetUser': to, 
     'sdp': peer.localDescription 
    }); 
} 

Вот что у меня внутри прослушивателя событий для кнопки CALL. Итак, сначала он получает звук, затем назначает поток текущему одноранговому объекту. Затем он создает новое предложение, оно успешное, локальное описание задано, и как только это будет сделано, он отправит предложение другому партнеру.

getAudio(
    function(stream){ 
     peer.addStream(stream); 
     audioStream = stream; 
     peer.createOffer(function(offerSDP){ 
      peer.setLocalDescription(offerSDP, function(){ 

        SocketService.emit('message', { 
         'conversation_id': me.conversation_id, 
         'targetUser': to, 
         'offerSDP': offerSDP 
        }); 
       }, 
       function(){}); 
      }, 
      function(){}, 
      sdpConstraints 
     ); 
    }, 
    function(err){}); 

На приемном пэре предложение зафиксировано, поэтому оно показывает, какой модал вызывает кто-то. Получающий одноранговый узел затем может нажать кнопку ANSWER. Но здесь я устанавливаю описание сеанса, используя предложение, даже до нажатия кнопки ANSWER.

SocketService.on('message', function(msg){ 
    if(msg.offerSDP){ 
     //show calling modal on the receiving peer 
     var remoteDescription = new RTCSessionDescription(msg.offerSDP); 
     peer.setRemoteDescription(remoteDescription, function(){ 
     createAnswer(msg.offerSDP); 
     }, 
     function(){}); 

    } 
}); 

После установки удаленного описания создается ответ. Сначала, получив аудио, затем добавив поток к локальному одноранговому объекту. Затем описание удаленной сессии создается с помощью offerSDP, это описание удаленного сеанса затем устанавливается на локальный одноранговый объект. После этого создается ответ, локальное описание устанавливается на локальном одноранговом узле, а затем отправляет answerSDP партнеру, который инициировал вызов.

function createAnswer(offerSDP) { 
    getAudio(
     function(stream){ 
      peer.addStream(stream); 
      audioStream = stream; 

      var remoteDescription = new RTCSessionDescription(offerSDP); 
      peer.setRemoteDescription(remoteDescription); 

      peer.createAnswer(function(answerSDP) { 

       peer.setLocalDescription(answerSDP, function(){ 

        SocketService.emit('message', { 
         'conversation_id': me.conversation_id, 
         'targetUser': to, 
         'answerSDP': answerSDP 
        }); 
       }, 
       function(){}); 
      }, function(err){}, sdpConstraints); 

     }, 
     function(err){ 
     } 
    ); 
}; 

Участник, инициировавший вызов, получает answerSDP. После того, как это делает, он создает удаленное описание с помощью answerSDP и использует его, чтобы установить удаленное описание своего локального объект пэра

if(msg.answerSDP){ 

     var remoteDescription = new RTCSessionDescription(msg.answerSDP); 
     peer.setRemoteDescription(remoteDescription, function(){ 
     }, 
     function(){}); 
} 

После этого, я не совсем уверен, что произойдет дальше. Основываясь на том, что я понимаю, событие onicecandidate запускается на собеседника (вызывающего), и он отправляет кандидата в принимающий одноранговый узел.Который затем выполняет следующий код:

if(msg.candidate){ 

    var candidate = msg.candidate.candidate; 
    var sdpMLineIndex = msg.candidate.sdpMLineIndex; 

    peer.addIceCandidate(new RTCIceCandidate({ 
     sdpMLineIndex: sdpMLineIndex, 
     candidate: candidate 
    })); 
} 

Теперь после нажатия кнопки ANSWER нажата, сообщение посылается инициирующей партнеру, что получение экспертной подобран. И он использует поток вызовов в качестве источника для аудио-элемента, как только все метаданные загружаются, он воспроизводит аудио.

SocketService.emit('message', { 
    'answerCall': true, 
    'conversation_id': me.conversation_id, 
    'targetUser': to 
}); 

audio.src = window.URL.createObjectURL(call.stream); 
audio.onloadedmetadata = function(e){ 
    audio.play(); 
} 

Возможно, что-то здесь не так. Вот почему звук только в одну сторону. Только пользователь, инициировавший вызов, может слышать ввод от принимающего пользователя. Звуки, создаваемые инициирующим пользователем, также могут быть услышаны, так что это похоже на то, что вы говорите. Есть идеи?

Если вы знаете какой-либо учебник или книгу, в которой показано, как реализовать webRTC с помощью собственных вызовов API, это также поможет. Заранее спасибо.

+0

Вы используете жесткое кодирование для определенного браузера (Chrome), используя устаревшие API, а не используя [стандарт] (http://w3c.github.io/webrtc-pc). Могу ли я предложить использовать [adapter.js] (https://github.com/webrtc/adapter) кросс-браузерный полиполк? – jib

ответ

1

Самый простой пример, который я могу порекомендовать, - это образец webrtc Peer Connection для базового однорангового соединения.

Что касается эха, вы можете установить audio.muted на аудиоэлемент локального однорангового узла, чтобы предотвратить его воспроизведение и вызвать эхо (пользователю не нужно слышать собственный звук, поэтому вы можете отключить этот элемент).

Смежные вопросы