使用 peerjs socket.io nodeJS 进行视频通话有时才有效
Posted
技术标签:
【中文标题】使用 peerjs socket.io nodeJS 进行视频通话有时才有效【英文标题】:Video call with peerjs socket.io nodeJS only works sometimes 【发布时间】:2021-10-19 19:05:32 【问题描述】:我需要帮助才能在 php 平台内设置一个简单的视频通话网络应用程序。但我有几个问题。我遵循了几个教程来实现这一点,但我仍然无法做到。
我需要实现什么?我需要在 wordpress 的 php 页面设置的单独“房间”中为 2 个摄像头(用户)分别设置几个视频通话(甚至同时)。
例子:
在“www.mywebsite.com/interviews/my_specific_name_room/”中,视频通话中只有 2 个用户。 在“www.mywebsite.com/visits/my_other_specific_name_room/”中,视频通话中只有 2 个用户。 等等。 我已经做了什么?我有一个带有 apache php mysql 和 nodejs 的 VPS。视频通话在 https 协议下工作。我遵循的教程让我设置“https://www.mywebsite.com:3030/”并进行视频通话。
但是我的问题是什么?问题是有时视频通话有效,有时无效。我不知道为什么。当我从笔记本电脑和手机访问“https://www.mywebsite.com:3030/”时,视频通话几乎总是在这些设备之间进行。即使我同一个城市的朋友访问“https://www.mywebsite.com:3030/”并且我也这样做,视频通话也能正常工作。但是对于城里的其他朋友,以及我国家其他地方的每一位朋友,视频通话永远不会奏效。我们只看我们自己的视频。真的我不知道为什么。我尝试了一些解决方案,但我不太了解 nodeJS。
我的服务器代码:
const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();
const options =
key: fs.readFileSync('/etc/letsencrypt/live/mywebsite.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/mywebsite.com/fullchain.pem'),
requestCert: false,
rejectUnauthorized: false
;
const server = https.createServer(options, app).listen(3030, function ()
console.log("Servidor iniciado en el puerto 3030");
);
const ExpressPeerServer = require('peer');
const peerServer = ExpressPeerServer(server,
debug: true
);
app.use('/peerjs', peerServer);
app.get('/', (req, res) =>
res.sendFile(__dirname + '/www/index.html');
);
const io = require('socket.io')(server,
serveClient: false,
// below are engine.IO options
origins: '*:*',
transports: ['polling'],
pingInterval: 10000,
pingTimeout: 5000,
cookie: false
);
io.on('connection', socket =>
socket.on('the-interview', (data) =>
socket.join(data.room);
socket.to(data.room).broadcast.emit('user-connected', data.id)
console.log(data.id)
)
)
我的代码来自 www/index.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interviews Mywebsite</title>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/MaterialDesign-Webfont/5.6.55/css/materialdesignicons.min.css">
<style>
#videogrid
width: 100%;
display: grid;
#videowrap
max-width: 100%;
#losvideos
overflow: hidden;
position: relative;
padding-top: 56.25%;
max-width: 900px;
video
width: 100%;
height: 100%;
#conttu
position: absolute;
top: 0;
left: 0;
width: 100%;
transition: all 0.5s ease;
#contyo
position: absolute;
bottom: 10px;
right: 10px;
width: 200px;
cursor: pointer;
transition: all 0.5s ease;
.watermark
position: absolute;
top: 10px;
left: 40px;
z-index: 1;
opacity: 0.3;
transform: scale3d(1.3, 1.3, 1.3);
.menu
position: absolute;
height: 120px;
bottom: -120px;
transition: all 0.7s ease;
background-color: rgba(0, 0, 0, 0.5);
width: 60%;
left: 50%;
margin-left: -30%;
border-radius: 70px 70px 0 0;
z-index: 1;
display: grid;
align-items: center;
grid-auto-flow: column;
justify-content: center;
gap: 30px;
#losvideos:hover .menu
bottom: 0px;
transition: all 0.7s ease;
.menu .icono
width: 80px;
height: 80px;
background-color: #5d59b5;
border-radius: 100%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
.menu .icono:hover
background-color: #383485;
.menu .icono:active
background-color: #24206d;
.menu .icono i
font-size: 50px;
color: #fff;
.menu #nofull
display: none;
.tooltip
position: relative;
display: inline-block;
.tooltip .tooltiptext
visibility: hidden;
width: 120px;
background-color: #fff;
color: #900;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 110%;
left: 50%;
margin-left: -65px;
opacity: 0;
transition: opacity 0.3s;
.tooltip .tooltiptext::after
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #fff transparent transparent transparent;
.tooltip:hover .tooltiptext
visibility: visible;
opacity: 1;
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="https://unpkg.com/peerjs@1.3.1/dist/peerjs.min.js"></script>
</head>
<body>
<h2>Interviews Mywebsite</h2>
<div id="videogrid">
<div id="videowrap">
<div id="losvideos">
<div class="watermark">
<img src="logo.svg" >
</div>
<div id="conttu">
<video id="video_other" autoplay></video>
</div>
<div id="contyo">
<video id="my_video" autoplay muted></video>
</div>
<div class="menu">
<div id="full" class="icono tooltip">
<i class="mdi mdi-fullscreen"></i>
<span class="tooltiptext">Pantalla completa</span>
</div>
<div id="silencio" class="icono tooltip">
<i class="mdi mdi-microphone-off"></i>
<span class="tooltiptext">Silenciar micrófono</span>
</div>
<div id="stopVideo" class="icono tooltip">
<i class="mdi mdi-video-off"></i>
<span class="tooltiptext">Apagar mi cámara</span>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
let miStream;
const socket = io()
var my_video = document.querySelector("#my_video");
if (navigator.mediaDevices.getUserMedia)
navigator.mediaDevices.getUserMedia( video: true, audio: true )
.then(function (stream)
console.log('Showing my own video')
my_video.srcObject = stream;
miStream = stream;
peer.on('call', call =>
call.answer(stream)
const video_other = document.getElementById('video_other');
call.on('stream', userVideoStream =>
console.log('Showing other user's video 1')
video_other.srcObject = userVideoStream;
)
)
socket.on('user-connected', userID =>
connectToNewUser(userID, stream)
);
)
.catch(function (error)
console.log("Something went wrong!");
);
var peer = new Peer(undefined,
path: '/peerjs',
host: '/',
port: '3030'
);
var room = '12345'; //room name, set by php
// Send interviews data to server
peer.on('open', id =>
socket.emit('the-interview',
room: room,
id: id
);
)
// Function for send our ID and video to the other user
const connectToNewUser = (userID, stream) =>
const call = peer.call(userID, stream);
const video_other = document.getElementById('video_other');
call.on('stream', userVideoStream =>
console.log('Showing other user's video 2')
video_other.srcObject = userVideoStream;
)
// other "work in progress" stuff for video call UI
// funcion para el silencio
function silencio()
const enabled = miStream.getAudioTracks()[0].enabled;
if (enabled)
miStream.getAudioTracks()[0].enabled = false;
$('#silencio i').removeClass('mdi-microphone-off').addClass('mdi-microphone');
else
$('#silencio i').removeClass('mdi-microphone').addClass('mdi-microphone-off');
miStream.getAudioTracks()[0].enabled = true;
$(document).on('click', '#silencio', function ()
silencio();
);
// funcion para apagar cámara
function stopVideo()
const enabled = miStream.getVideoTracks()[0].enabled;
if (enabled)
miStream.getVideoTracks()[0].enabled = false;
$('#stopVideo i').removeClass('mdi-video-off').addClass('mdi-video');
else
$('#stopVideo i').removeClass('mdi-video').addClass('mdi-video-off');
miStream.getVideoTracks()[0].enabled = true;
$(document).on('click', '#stopVideo', function ()
stopVideo();
);
// Pantalla completa
$(document).on('click', '#full', function ()
if ($(this).hasClass('activado'))
exitFullScreen();
else
toggleFullScreen();
)
function toggleFullScreen()
var losvideos = document.getElementById("losvideos");
if (losvideos.requestFullscreen)
if (document.fullScreenElement)
document.cancelFullScreen();
else
losvideos.requestFullscreen();
else if (losvideos.msRequestFullscreen)
if (document.msFullscreenElement)
document.msExitFullscreen();
else
losvideos.msRequestFullscreen();
else if (losvideos.mozRequestFullScreen)
if (document.mozFullScreenElement)
document.mozCancelFullScreen();
else
losvideos.mozRequestFullScreen();
else if (losvideos.webkitRequestFullscreen)
if (document.webkitFullscreenElement)
document.webkitCancelFullScreen();
else
losvideos.webkitRequestFullscreen();
else
alert("Fullscreen API is not supported");
$('#losvideos').bind('webkitfullscreenchange mozfullscreenchange fullscreenchange', function (e)
var state = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen;
var event = state ? 'FullscreenOn' : 'FullscreenOff';
$('#full i').removeClass('mdi-fullscreen-exit').addClass('mdi-fullscreen');
$('#full').removeClass('activado');
if (event == "FullscreenOn")
$('#full i').removeClass('mdi-fullscreen').addClass('mdi-fullscreen-exit');
$('#full').addClass('activado');
);
function exitFullScreen()
if (document.exitFullscreen)
document.exitFullscreen();
else if (document.msExitFullscreen)
document.msExitFullscreen();
else if (document.mozCancelFullScreen)
document.mozCancelFullScreen();
else if (document.webkitExitFullscreen)
document.webkitExitFullscreen();
$(document).on('click', '#contyo', function ()
if ($(this).hasClass('big'))
$('#contyo').removeClass('big').attr('style', false)
$('#conttu').attr('style', false)
else
$('#conttu').css( 'width': '250px', 'z-index': '1', 'right': '10px', 'bottom': '10px', 'top': 'unset', 'left': 'unset' )
$('#contyo').css( 'width': '100%', 'z-index': '0', 'right': '0', 'bottom': '-4px' ).addClass('big')
)
</script>
</body>
</html>
我不知道如何在这段代码中实现 TURN 和 STUN 的东西。
拜托,我真的需要帮助。在提出问题之前,我总是到处搜索。对我来说,能够在不使用第三方服务的情况下编写程序来进行视频通话已经是一个巨大的成功。
但我现在的首要任务是让视频通话始终正常工作,无论浏览器、位置如何……什么都没有。如果有人可以提出建议以实现我的另一个目标,即“房间”,我将不胜感激。
【问题讨论】:
【参考方案1】:我不知道你的项目有多大。然而,对于我的小项目,这个解决方案效果很好。 您只需在https://xirsys.com/ 注册一个帐户并注册免费的 TURN 服务器服务。之后,在客户端代码中,在 Peer initiation 中,将 peer 构造函数的配置添加到 iceserver 中。
var peer = new Peer(undefined,
path: '/peerjs',
host: '/',
port: '3030',
config: 'iceServers':.......
);
希望我的回答对你有所帮助。
【讨论】:
以上是关于使用 peerjs socket.io nodeJS 进行视频通话有时才有效的主要内容,如果未能解决你的问题,请参考以下文章