Заранее спасибо.
Я следую руководству по реализации webrt c с официальной страницы:
https://webrtc.org/
И у меня проблемы с двусторонней связью. На одном устройстве p c у меня есть видеокамера, а на другом только микрофон.
Мне удается получить видеокамеру, но я не могу получить событие .ontrack на устройстве p c, которое отправляет видеокамеру и он должен получать только аудио, когда я добавляю трек на компьютер, который отправляет аудио, но не запускает событие .ontrack на удаленном компьютере.
Соединение установлено правильно, здесь вставьте соединение и код
МОЙ КОД один локальный хост / видео. php другой localhsot / видео. php? cliente = 1
<?php
/**
* Created by PhpStorm.
* User: Jesús
* Date: 16/03/2020
* Time: 13:16
*/
?>
<video id="localVideo" autoplay <?= !isset($_GET['cliente']) ? 'muted' : '' ?> playsinline controls="false" style="width: 600px; height: 320px;"></video>
<?php
if(!isset($_GET['cliente'])) {
?>
<button onclick="makeCallAdmin()">enviar llamada</button>
<?php
}
?>
<script src="../app/js/lib/socket.io.js"></script>
<script>
let cliente = <?= isset($_GET['cliente']) ? 'true' : 'false' ?>;
let tipo = cliente ? 'client' : 'admin';
var ipSocket = 'SCOCKETADDRESS';
// var ipSocket = 'https://192.168.125.175:3001';
var idgrupo = '5ed44424c2df0470d689.4f6370fbe1ac319e5dc1d7417822d28a';
var socket = io(ipSocket, {
query: "grupo=" + idgrupo + "&tipo=" + tipo
});
const iceConfiguration = {
iceServers: [
{
urls: 'stun:stun.l.google.com:19302?transport=udp'
},
{
urls: 'turns:turnserver',
username: 'prueba',
credential: '123456'
}
],
}
const offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
// let peerConnection, remoteStream, videoElement;
let peerConnection;
let fuerzaConectar;
async function getConnectedDevices(type) {
const devices = await navigator.mediaDevices.enumerateDevices();
return await devices.filter(device => device.kind === type)
}
// Open camera with at least minWidth and minHeight capabilities
async function openCamera(cameraId, audioid) {
let constraints;
if(!cameraId) {
constraints = {
'audio': {'echoCancellation': true}
}
}else{
constraints = {
'audio': {'echoCancellation': true},
'video': {
'deviceId': cameraId
}
}
}
// constraints = {'video': true, 'audio': true};
return await navigator.mediaDevices.getUserMedia(constraints);
}
async function playVideoFromCamera(peerConnection, type, fuerza) {
if(type == null)
type = 'videoinput';
if(fuerza == null)
fuerza = false;
try {
const cameras = await getConnectedDevices(type);
if (cameras && cameras.length > 0) {
let stream;
if(fuerza) //si solo ha encontrado el audio enviamos solo audio
stream = await openCamera(false, cameras[0].deviceId);
else //si ha encontrado camara enviamos camara y audio
stream = await openCamera(cameras[0].deviceId, false);
stream.getTracks().forEach(track => {
peerConnection.addTrack(track, stream);
});
}else{
if(!fuerza)
await playVideoFromCamera(peerConnection, 'audioinput', true);
else
console.log('no hay input');
}
} catch(error) {
console.error('Error opening video camera.', error);
}
}
async function makeCallAdmin() {
fuerzaConectar = (fuerzaConectar == null | !fuerzaConectar) ? true : false;
if(typeof peerConnection == 'object') {
peerConnection.close();
peerConnection = null;
const videoElement = document.querySelector('video#localVideo');
videoElement.srcObject = null;
if(cliente)
socket.off('videoconferenciaRecibeCliente');
else
socket.off('videoconferenciaRecibeAdmin');
}
peerConnection = new RTCPeerConnection(iceConfiguration);
const remoteStream = new MediaStream();
// Listen for local ICE candidates on the local RTCPeerConnection
// peerConnection.removeEventListener('icecandidate', iceCandidate);
// peerConnection.addEventListener('icecandidate', iceCandidate);
peerConnection.onicecandidate = e => iceCandidate(e);
// Listen for connectionstatechange on the local RTCPeerConnection
// peerConnection.removeEventListener('iceconnectionstatechange', iceconnectionstatechange);
peerConnection.oniceconnectionstatechange = e => iceconnectionstatechange(e, peerConnection);
// peerConnection.removeEventListener('track', track);
// peerConnection.addEventListener('track', trackEv);
peerConnection.ontrack = e => trackEv(e, remoteStream);
socket.on('videoconferenciaRecibeAdmin', data => videoconferenciaRecibeAdmin(data, peerConnection));
const offer = await peerConnection.createOffer(offerOptions);
await peerConnection.setLocalDescription(offer);
socket.emit('videoconferenciaAdmin', {'tipo':'remoteDescription','offer': offer});
}
async function makeCallCliente()
{
fuerzaConectar = (fuerzaConectar == null | !fuerzaConectar) ? true : false;
if(typeof peerConnection == 'object') {
peerConnection.close();
peerConnection = null;
const videoElement = document.querySelector('video#localVideo');
videoElement.srcObject = null;
if(cliente)
socket.off('videoconferenciaRecibeCliente');
else
socket.off('videoconferenciaRecibeAdmin');
}
peerConnection = await new RTCPeerConnection(iceConfiguration);
const remoteStream = await new MediaStream();
// Listen for local ICE candidates on the local RTCPeerConnection
// peerConnection.removeEventListener('icecandidate', iceCandidate);
// peerConnection.addEventListener('icecandidate', iceCandidate);
peerConnection.onicecandidate = e => iceCandidate(e);
// Listen for connectionstatechange on the local RTCPeerConnection
// peerConnection.removeEventListener('iceconnectionstatechange', iceconnectionstatechange);
peerConnection.oniceconnectionstatechange = e => iceconnectionstatechange(e, peerConnection);
// peerConnection.removeEventListener('track', track);
// peerConnection.addEventListener('track', trackEv);
peerConnection.ontrack = e => trackEv(e, remoteStream);
socket.on('videoconferenciaRecibeCliente', data => videoconferenciaRecibeCliente(data, peerConnection, ));
}
async function videoconferenciaRecibeCliente(data, peerConnection)
{
switch(data.tipo) {
case 'remoteDescription':
if (data.offer) {
console.log(data.offer);
await peerConnection.setRemoteDescription(new RTCSessionDescription(data.offer));
const answer = await peerConnection.createAnswer(offerOptions);
await peerConnection.setLocalDescription(answer);
await socket.emit('videoconferenciaCliente', {'tipo':'remoteDescription','answer': answer});
console.log('recibida conexion cliente');
console.log(peerConnection);
}
break;
case 'icecandidate':
if (data.icecandidate) {
try {
await peerConnection.addIceCandidate(data.icecandidate);
console.log('creado ice candidate cliente');
console.log(data.icecandidate);
} catch (e) {
console.error('Error adding received ice candidate', e);
}
}
break;
}
}
async function videoconferenciaRecibeAdmin(data, peerConnection)
{
switch(data.tipo) {
case 'remoteDescription':
if (data.answer) {
console.log(data.answer);
const remoteDesc = new RTCSessionDescription(data.answer);
await peerConnection.setRemoteDescription(remoteDesc);
console.log('recibida conexion admin');
console.log(peerConnection);
}
break;
case 'icecandidate':
if (data.icecandidate) {
try {
await peerConnection.addIceCandidate(data.icecandidate);
console.log('creado ice candidate admin');
console.log(data.icecandidate);
} catch (e) {
console.error('Error adding received ice candidate', e);
}
}
break;
}
}
async function iceCandidate(event)
{
let el_evento = cliente ? 'videoconferenciaCliente' : 'videoconferenciaAdmin';
if (event.candidate) {
socket.emit(el_evento, {'tipo':'icecandidate','icecandidate': event.candidate});
}
}
async function iceconnectionstatechange(event, peerConnection)
{
console.log(peerConnection.iceConnectionState);
switch(peerConnection.iceConnectionState) {
case 'connected':
console.log('CONECTADO');
await enviarLLamada(peerConnection);
switch(true) {
case fuerzaConectar && cliente:
// makeCallCliente();
break;
case fuerzaConectar && !cliente:
makeCallAdmin();
break;
}
break;
case 'disconnected':
console.log('DESconectado');
await peerConnection.close();
peerConnection = null;
const videoElement = document.querySelector('video#localVideo');
videoElement.srcObject = null;
if(cliente)
await socket.off('videoconferenciaRecibeCliente');
else
await socket.off('videoconferenciaRecibeAdmin');
break;
}
}
async function trackEv(event, remoteStream)
{
const videoElement = document.querySelector('video#localVideo');
if(videoElement.srcObject == null)
videoElement.srcObject = remoteStream;
console.log('entra a TRACK');
await remoteStream.addTrack(event.track, remoteStream);
// videoElement.play();
}
async function enviarLLamada(peerConnection)
{
await playVideoFromCamera(peerConnection);
}
document.addEventListener("DOMContentLoaded", function(event) {
if(cliente)
makeCallCliente();
// else
// makeCallAdmin();
});
</script>