Удаленное видео с обеих сторон не будет отображаться - PullRequest
0 голосов
/ 12 января 2019

В настоящее время используется Chrome 70, Firefox 64 и Safari 12.

Удаленное видео от другого пользователя не отображается с обеих сторон, и я не совсем уверен, в чем может быть проблема.

Нет ошибок, возникающих в любом браузере, который не помогает при отладке кода.

Я использую внутренний инструмент отладки WebRTC в chrome (chrome: // webrtc-internals), и в нем было отправлено или получено ноль пакетов.

В инструменте есть параметр, который называется googCandidatePair, но он не отображается вообще во время вызова. enter image description here

Событие ICEgatheringstatechange инициирует и сообщает, что оно завершено, но только когда хост является пользователем chrome.

Я также пытался использовать

pc.oniceconnectionstatechange = () => console.log(pc.iceConnectionState);

для проверки изменений состояния ДВС, но это не срабатывает вообще.

Одна причина, по которой я думаю, что она может работать неправильно, может быть связана с тем, как RTCPeerconnection был настроен, как показано на этом рисунке, размер пула кандидатов на Ice равен 0, но он никогда не указывался в самом коде. enter image description here

Ниже приведены 2 рисунка, где первое - это когда хост является хромом, а другое - получателем. enter image description here enter image description here

Код выглядит следующим образом:

'use strict';

var configuration = {
  iceServers: [
    {
      urls: 'stun:stun.l.google.com:19302'
    }
  ]
};
var pc = new RTCPeerConnection(configuration);

// Define action buttons.
const callButton = document.getElementById('callButton');
const hangupButton = document.getElementById('hangupButton');

/////////////////////////////////////////////

window.room = prompt('Enter room name:');

var socket = io.connect();

if (room !== '') {
  console.log('Message from client: Asking to join room ' + room);
  socket.emit('create or join', room);
}

socket.on('created', function(room) {
  console.log('Created room ' + room);
  startVideo();
});

socket.on('full', function(room) {
  console.log('Message from client: Room ' + room + ' is full :^(');
});

socket.on('joined', function(room) {
  console.log('joined: ' + room);
  startVideo();
  callButton.disabled = true;
});

socket.on('log', function(array) {
  console.log.apply(console, array);
});

////////////////////////////////////////////////

async function sendMessage(message) {
  console.log('Client sending message: ', message);
  await socket.emit('message', message);
}

// This client receives a message
socket.on('message', message => {
  if (message.sdp) {
    pc.setRemoteDescription(new RTCSessionDescription(message.sdp))
      .then(function() {
        if (pc.setRemoteDescription.type === 'offer') {
          pc.setLocalDescription(pc.createAnswer())
            .then(function() {
              sendMessage({ sdp: pc.localDescription });
            })
            .catch(function(err) {
              console.log(err.name + ': ' + err.message);
            });
        }
      })
      .catch(error => console.error(error));
  } else if (message.candidate) {
    pc.addIceCandidate(new RTCIceCandidate(message.candidate))
      .then(() => {
        console.log('Candidates received');
      })
      .catch(error => console.error(error));
  }
});

pc.onicecandidate = event => {
  if (event.candidate) {
    sendMessage({ candidate: event.candidate });
  }
};

pc.ontrack = event => {
  if (remoteVideo.srcObject !== event.streams[0]) {
    remoteVideo.srcObject = event.streams[0];
    console.log('Got remote stream');
  }
};

////////////////////////////////////////////////////

const localVideo = document.querySelector('#localVideo');
const remoteVideo = document.querySelector('#remoteVideo');

// Set up initial action buttons status: disable call and hangup.
callButton.disabled = true;
hangupButton.disabled = true;

// Add click event handlers for buttons.
callButton.addEventListener('click', callStart);
hangupButton.addEventListener('click', hangupCall);

function startVideo() {
  navigator.mediaDevices
    .getUserMedia({
      audio: true,
      video: true
    })
    .then(function(stream) {
      localVideo.srcObject = stream;
      stream.getTracks().forEach(track => pc.addTrack(track, stream));
    })
    .catch(function(err) {
      console.log('getUserMedia() error: ' + err.name);
    });
  callButton.disabled = false;
}

async function callStart() {
  callButton.disabled = true;
  hangupButton.disabled = false;

  console.log('Sending offer to peer');
  await pc
    .setLocalDescription(await pc.createOffer())
    .then(() => {
      sendMessage({ sdp: pc.localDescription });
    })
    .catch(err => {
      console.log(err.name + ': ' + err.message);
    });
}

/////////////////////////////////////////////////////////

function hangupCall() {
  pc.close();
  pc = null;
  callButton.disabled = false;
  hangupButton.disabled = true;
  console.log('Call Ended');
}

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Если у кого-то могут возникнуть проблемы с удаленным видео, которое не отображается, я обнаружил, что это произошло потому, что сообщение не было передано вторым оператором IF, который проверял, предлагается ли message.type ===, и не смог создать Таким образом, он не может отправить свое локальное описание другому пользователю. Но разделив сообщение в начале на sdp и кандидата, это как-то работает.

socket.on('message', async ({ sdp, candidate }) => {
  if (sdp) {
    await pc.setRemoteDescription(new RTCSessionDescription(sdp));
    if (sdp.type === 'offer') {
      await pc
        .setLocalDescription(await pc.createAnswer())
        .then(function() {
          sendMessage({ sdp: pc.localDescription });
        })
        .catch(function(err) {
          console.log(err.name + ': ' + err.message);
        });
    }
  } else if (candidate) {
    await pc
      .addIceCandidate(new RTCIceCandidate(candidate))
      .then(() => {
        console.log('Candidates received');
      })
      .catch(error => console.error(error));
  }
});
0 голосов
/ 13 января 2019

Вы смешиваете свои стили обещаний, и у вас есть ошибка здесь:

          pc.setLocalDescription(pc.createAnswer()) // bug!
            .then(function() {

Приведенное выше описание устанавливает локальное описание для объекта обещания. Либо выберите async / await на всем протяжении:

          await pc.setLocalDescription(await pc.createAnswer());

... или .then() цепи:

          pc.createAnswer()
            .then(answer => pc.setLocalDescription(answer))
            .then(function() {

Если вы выберете последнее, не забудьте вернуть все обещания .

Вот обработчик сообщений, сделанный исключительно с async / await:

// This client receives a message
socket.on('message', async message => {
  try {
    if (message.sdp) {
      await pc.setRemoteDescription(message.sdp);
      if (pc.setRemoteDescription.type === 'offer') {
        await pc.setLocalDescription(await pc.createAnswer());
        sendMessage({sdp: pc.localDescription});
      }
    } else if (message.candidate) {
      await pc.addIceCandidate(message.candidate);
      console.log('Candidates received');
    }
  } catch (err) {
    console.log(err.name + ': ' + err.message);
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...