我正在创建一个使用WebRTC在用户之间建立对等连接的应用程序。当用户加入应用程序时。它们将被放入一个Socket.io房间,只有2个用户可以进入并仅被提示输入音频。当第二个用户连接到同一个URL时。我向服务器发送一个事件,将它们作为第一个用户放在同一个Socket.io房间,并运行所有WebRTC代码,如创建RTCPeerConnection,RTCInceCandidates和RTCSessionDescription实例,具体取决于从服务器向另一个广播的事件。连接同伴,但由于某种原因,我没有让远程用户的音频播放到我能听到的地方,他们可以听到我的声音。
p2p.js文件(负责设置连接的所有代码)
// roomURL.addEventListener('click', function (e) {
// document.execCommand('copy')
// });
// roomURL.addEventListener('copy', function (e) {
// e.preventDefault();
// if (e.clipboardData) {
// e.clipboardData.setData('text/plain', roomURL.textContent);
// }
// });
let isInitializer = false;
let isChannelReady = false;
let isStarted = false;
let pc;
let localStream;
let remoteStream;
/**
* - Create new RTCPeerConnection
* - Listen for events on newly created RTCPeerConnection (onicecandidate, onaddstream, onremovestream)
*/
const pcConfig = {
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
};
const room = 'foo';
const socket = io();
if (room !== '') {
socket.emit('create or join', room);
console.log('Attempted to create or join room ' + room);
}
socket.on('created', function (room) {
isInitializer = true;
console.log('Created room ' + room);
});
socket.on('full', function (room) {
console.log('Room ' + room + ' is full');
});
socket.on('join', function (room) {
console.log('Another peer made a request to join room ' + room);
console.log('This peer is the initiator of room ' + room + '!');
isChannelReady = true;
});
socket.on('joined', function (room) {
console.log('joined: ' + room);
isChannelReady = true;
});
function sendMessage(message) {
socket.emit('message', message);
}
//////////////////////////////////////////////////////////////////////////////////
socket.on('message', function (message) {
if (message === 'got user media') {
start();
console.log('Got user media');
} else if (message.type === 'offer') {
if (!isInitializer && !isStarted) {
start();
}
pc.setRemoteDescription(new RTCSessionDescription(message));
answer();
console.log('Offer')
} else if (message.type === 'answer' && isStarted) {
pc.setRemoteDescription(new RTCSessionDescription(message));
console.log('Answer');
} else if (message.type === 'candidate' && isStarted) {
const candidate = new RTCIceCandidate({
sdpMLineIndex: message.label,
candidate: message.candidate
});
pc.addIceCandidate(candidate);
console.log('Candidate');
}
});
/////////////////////////////////////////////////////////////////////////////////
var localVideo = document.querySelector('#localVideo');
var remoteVideo = document.querySelector('#remoteVideo');
navigator.mediaDevices.getUserMedia({
audio: true, video: false
}).then((stream) => {
localStream = stream;
console.log('My Stream', stream);
localVideo.srcObject = stream;
sendMessage('got user media');
if (isInitializer) {
start();
}
});
//////////////////////////////////////////////////////////////////////////////////
function start() {
if (!isStarted && typeof localStream !== 'undefined' && isChannelReady) {
createPeerConnection();
const tracks = localStream.getTracks();
for (const track of tracks) {
pc.addTrack(track);
}
isStarted = true;
if (isInitializer) {
call();
}
}
}
function createPeerConnection() {
pc = new RTCPeerConnection(null);
pc.onicecandidate = function (e) {
if (e.candidate) {
sendMessage({
type: 'candidate',
label: e.candidate.sdpMLineIndex,
id: e.candidate.sdpMid,
candidate: e.candidate.candidate
});
}
}
pc.ontrack = function (e) {
console.log('Remote track added', e);
remoteStream = e.streams[0];
remoteVideo.srcObject = remoteStream;
}
}
//////////////////////////////////////////////////////////////////////////////////
function call() {
pc.createOffer(null).then((sessionDescription) => {
pc.setLocalDescription(sessionDescription);
sendMessage(sessionDescription);
}).catch(e => console.log(e));
}
function answer() {
pc.createAnswer(null).then((sessionDescription) => {
pc.setLocalDescription(sessionDescription);
sendMessage(sessionDescription);
});
}
index.js(用于侦听Socket.io事件的Express服务器)
const express = require('express');
const path = require('path');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const os = require('os');
app.use(express.static(path.resolve(__dirname, '../public')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../public/index.html'));
});
const port = process.env.PORT || 3000;
server.listen(port, () => {
console.log(('Server listening on port ' + port));
});
io.on('connection', (socket) => {
socket.on('create or join', (room) => {
const clientsRoom = (io.sockets.adapter.rooms[room]);
const roomSize = (clientsRoom ? clientsRoom.length : 0);
if (roomSize === 0) {
console.log('Joined room with no one');
socket.join(room);
console.log(('Room ' + room + ' now has ' + roomSize + ' connected client(s)'));
socket.emit('created', room, socket.id);
} else if (roomSize === 1) {
console.log(('Client ID ' + socket.id + ' created room ' + room));
io.sockets.in(room).emit('join', room);
socket.join(room);
console.log(('Room ' + room + ' now has ' + roomSize + ' connected client(s) and is full'));
socket.emit('joined', room, socket.id);
io.sockets.in(room).emit('ready');
} else {
console.log(('Room ' + room + ' is full'));
socket.emit('full', room);
}
});
socket.on('message', (message) => {
socket.broadcast.emit('message', message);
});
});
答案 0 :(得分:0)
在remoteVideo.play();
之后添加remoteVideo.srcObject = remoteStream;
。
如果仍然不起作用,请尝试:
try {
remoteVideo.srcObject = remoteStream;
} catch(error) {
remoteVideo.src = URL.createObjectURL(remoteStream);
};
remoteVideo.play();