Удаленный поток видео не отображается вообще - PullRequest
0 голосов
/ 02 декабря 2018

Я пытался заставить удаленный видеопоток отображаться с помощью .ontrack, который находится под функцией однорангового соединения в моем коде.До сих пор .ontrack срабатывает только на стороне вызывающего, а на вызываемом - даже при вызове функции.

Журнал, проверяющий, будет ли при запуске .ontrack указано «Got Remote Stream», но только насторона вызывающего абонента, которая могла бы быть проблемой здесь, но я не уверен, почему другая сторона не пошла бы в оператор IF, который содержит .ontrack, когда у него нет события.stream [0], для которого проверяется оператор.

Я добавил журналы консоли от Caller и Callee ниже.На изображениях не показано, что через некоторое время кандидаты будут показывать ноль, но оба пользователя все еще будут подключены.

main.js

'use strict';

var isInitiator;
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);
  isInitiator = true;
  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', async function(message) {
  try {
    if (message.type === 'offer') {
      await pc.setRemoteDescription(new RTCSessionDescription(message));
      await pc
        .setLocalDescription(await pc.createAnswer())
        .then(function() {
          sendMessage(pc.localDescription);
        })
        .catch(function(err) {
          console.log(err.name + ': ' + err.message);
        });
      createPeerConnection();
    } else if (message.type === 'answer') {
      await pc.setRemoteDescription(new RTCSessionDescription(message));
    } else if (message.type === 'candidate') {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
});

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

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() {
  createPeerConnection();
  callButton.disabled = true;
  hangupButton.disabled = false;
  if (isInitiator) {
    console.log('Sending offer to peer');
    await pc
      .setLocalDescription(await pc.createOffer())
      .then(function() {
        sendMessage(pc.localDescription);
      })
      .catch(function(err) {
        console.log(err.name + ': ' + err.message);
      });
  }
}

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

function createPeerConnection() {
  try {
    pc.ontrack = event => {
      if (remoteVideo.srcObject !== event.streams[0]) {
        remoteVideo.srcObject = event.streams[0];
        console.log('Got remote stream');
      }
    };
    pc.onicecandidate = ({ candidate }) => sendMessage({ candidate });
    console.log('Created RTCPeerConnnection');
  } catch (e) {
    console.log('Failed to create PeerConnection, exception: ' + e.message);
    alert('Cannot create RTCPeerConnection object.');
    return;
  }
}

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

index.js

'use strict';

var express = require('express');
var app = (module.exports.app = express());
var path = require('path');

var server = require('http').createServer(app);
var io = require('socket.io')(server);
const PORT_NO = process.env.APP_PORT || 3000;
server.listen(PORT_NO);

app.get('/', function(request, response) {
  response.sendFile(path.resolve('./index.html'));
});

app.use(express.static('.'));
io.on('connection', socket => {
  function log() {
    const array = ['Message from server:'];
    for (let i = 0; i < arguments.length; i++) {
      array.push(arguments[i]);
    }
    socket.emit('log', array);
  }

  socket.on('message', message => {
    log('Got message:', message);
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', room => {
    var clientsInRoom = io.sockets.adapter.rooms[room];
    var numClients = clientsInRoom
      ? Object.keys(clientsInRoom.sockets).length
      : 0;

    // max two clients
    if (numClients === 2) {
      socket.emit('full', room);
      return;
    }

    log('Room ' + room + ' now has ' + (numClients + 1) + ' client(s)');

    if (numClients === 0) {
      socket.join(room);
      log('Client ID ' + socket.id + ' created room ' + room);
      socket.emit('created', room, socket.id);
    } else {
      log('Client ID ' + socket.id + ' joined room ' + room);
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room, socket.id);
      io.sockets.in(room).emit('ready');
    }
  });
});

Callee side (in Safari)

Caller side (in Firefox)

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Вы пропускаете вызов на createPeerConnection() на стороне ответчика, что означает, что ответчик не настроен должным образом, чтобы сигнализировать кандидатам ICE или инициировать событие отслеживания.

Вы вызываете его только с startCall(), так что это будет работать только в том случае, если вы нажмете кнопку вызова на обоих концах почти в одно и то же время.

createPeerConnection() - это неправильное название.Вместо этого просто инициализируйте pc с его обратными вызовами ontrack и onicecandidate при загрузке страницы.

Все еще не работает?

Остальной код, связанный с WebRTC, который вы показываетес нами все в порядке - за исключением того, что вы дважды вызываете getUserMedia на стороне отвечающего, что является избыточным, но не должно быть проблемой.

Я подозреваю ошибку в логике вашего сервера.Например, вы не показываете нам, как излучение 'create or join' превращается в сообщение 'created' или 'joined'.Вы также пытаетесь предугадать, какая сторона в обмене предложением / ответом какая, что нормально, за исключением того, что у вас есть нерабочая кнопка Call на стороне отвечающего.Большинство демонстраций просто позволяют тому, кто нажмет кнопку первым, быть предложителем, хотя это может создать блики.Просто к вашему сведению.

Это двусторонний вызов.В каком направлении удаленное видео не работает?

Кроме того, у вас есть двусторонний вызов, отправка видео в обоих направлениях, но вы не упомянули , remoteVideo, которого вы не видите.

В качестве рабочего примера посмотрите мою демонстрацию двусторонней вкладки .Откройте его в двух смежных окнах в одном и том же браузере и нажмите кнопку Call в одном из них для подключения.Вы должны увидеть (одинаковое) видео, отправляемое в обе стороны.Он опирается на localSocket взлом с использованием localStorage.

0 голосов
/ 03 декабря 2018

Пусть столяру будет инициатор.

Я предполагаю, что 'created' произойдет раньше 'joined'?Т.е. одна сторона создает комнату до того, как к ней присоединится вторая сторона?

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

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

socket.on('joined', function(room) {
  console.log('joined: ' + room);
  isInitiator = true; // <-- begin negotiating once 2nd party arrives.
  startVideo();
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...