gpt4 book ai didi

javascript - localhost : how to setup XHR-Signaling (connection. openSignalingChannel 未被调用)

转载 作者:数据小太阳 更新时间:2023-10-29 04:20:10 27 4
gpt4 key购买 nike

我正在使用 RTCMultiConnection v3.4.4

我想在本地主机上运行 WebRTC。我选择了 XHR-Signaling,因为我希望项目完全离线。我不希望它依赖于互联网,因为一切都在本地主机上(稍后部署在 LAN 上)

我包含了 XHRConnection.js 并设置了 connection.setCustomSocketHandler(XHRConnection)。我还覆盖了 connection.openSignalingChannel...

但是,当我打开/启动房间时,我的视频会显示,但被 disableInputButtons() 禁用的按钮仍然保持禁用状态。聊天不工作。

我在覆盖 connection.openSignalingChannel... 时做了一个 console.log 来确认它是否被调用过,但它没有。

请帮助了解如何在本地主机上实现 XHR 信号。

谢谢。

代码:

文件:Audio+Video+TextChat+FileSharing.html

<!-- Demo version: 2017.08.10 -->
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Audio+Video+TextChat+FileSharing using RTCMultiConnection</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="shortcut icon" href="./logo.png">
<link rel="stylesheet" href="./stylesheet.css">
<script src="./menu.js"></script>
</head>
<body>
<h1>
Audio+Video+TextChat+FileSharing using RTCMultiConnection
<p class="no-mobile">
Multi-user (many-to-many) video streaming + text chat + file sharing using mesh networking model.
</p>
</h1>

<section class="make-center">
<input type="text" id="room-id" value="abcdef" autocorrect=off autocapitalize=off size=20>
<button id="open-room">Open Room</button><button id="join-room">Join Room</button><button id="open-or-join-room">Auto Open Or Join Room</button>

<br><br>
<input type="text" id="input-text-chat" placeholder="Enter Text Chat" disabled>
<button id="share-file" disabled>Share File</button>
<br><br>
<button id="btn-leave-room" disabled>Leave/or close the room</button>

<div id="room-urls" style="text-align: center;display: none;background: #F1EDED;margin: 15px -10px;border: 1px solid rgb(189, 189, 189);border-left: 0;border-right: 0;"></div>

<div id="chat-container">
<div id="file-container"></div>
<div class="chat-output"></div>
</div>
<div id="videos-container"></div>
</section>

<script src="./RTCMultiConnection.min.js"></script>
<script src="./adapter.js"></script>
<script src="./XHRConnection.js"></script>

<!-- custom layout for HTML5 audio/video elements -->
<link rel="stylesheet" href="./getHTMLMediaElement.css">
<script src="./getHTMLMediaElement.js"></script>
<script src="./FileBufferReader.js"></script>
<script>
// ......................................................
// .......................UI Code........................
// ......................................................
document.getElementById('open-room').onclick = function() {
disableInputButtons();
connection.open( document.getElementById('room-id').value , function() {
showRoomURL(connection.sessionid);
xhr
(
'start-broadcast.php' ,
function( responseText ){ console.log( 'Broadcast started [' + document.getElementById('room-id').value + ']' ) },
JSON.stringify( { name: document.getElementById('room-id').value } )
);
});
};

document.getElementById('join-room').onclick = function() {
disableInputButtons();
connection.join(document.getElementById('room-id').value);
};

document.getElementById('open-or-join-room').onclick = function() {
disableInputButtons();
connection.openOrJoin(document.getElementById('room-id').value, function(isRoomExists, roomid) {
if (!isRoomExists) {
showRoomURL(roomid);
}
});
};

document.getElementById('btn-leave-room').onclick = function() {
this.disabled = true;

if (connection.isInitiator) {
// use this method if you did NOT set "autoCloseEntireSession===true"
// for more info: https://github.com/muaz-khan/RTCMultiConnection#closeentiresession
connection.closeEntireSession(function() {
document.querySelector('h1').innerHTML = 'Entire session has been closed.';
});
} else {
connection.leave();
}
};

// ......................................................
// ................FileSharing/TextChat Code.............
// ......................................................

document.getElementById('share-file').onclick = function() {
var fileSelector = new FileSelector();
fileSelector.selectSingleFile(function(file) {
connection.send(file);
});
};

document.getElementById('input-text-chat').onkeyup = function(e) {
if (e.keyCode != 13) return;

// removing trailing/leading whitespace
this.value = this.value.replace(/^\s+|\s+$/g, '');
if (!this.value.length) return;

connection.send(this.value);
appendDIV(this.value);
this.value = '';
};

var chatContainer = document.querySelector('.chat-output');

function appendDIV(event) {
var div = document.createElement('div');
div.innerHTML = event.data || event;
chatContainer.insertBefore(div, chatContainer.firstChild);
div.tabIndex = 0;
div.focus();

document.getElementById('input-text-chat').focus();
}


// ......................................................
// ..................RTCMultiConnection Code.............
// ......................................................

var connection = new RTCMultiConnection();
connection.setCustomSocketHandler(XHRConnection);
connection.direction = 'one-way';
// by default, socket.io server is assumed to be deployed on your own URL
// connection.socketURL = '/';
connection.trickleIce = false;

// comment-out below line if you do not have your own socket.io server
// connection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/';

//connection.socketMessageEvent = 'audio-video-file-chat-demo';
connection.enableLogs = true;
connection.enableFileSharing = true; // by default, it is "false".

// this object is used to store "onmessage" callbacks from "openSignalingChannel handler
var onMessageCallbacks = {};

// this object is used to make sure identical messages are not used multiple times
var messagesReceived = {};

// overriding "openSignalingChannel handler
connection.openSignalingChannel = function (config) {

console.log( 'called: openSignalingChannel' );
var channel = config.channel || this.channel;
onMessageCallbacks[channel] = config.onmessage;

// let RTCMultiConnection know that server connection is opened!
if (config.onopen) {
console.log( 'Calling the config.open object' );
setTimeout(config.onopen, 1);
}
else console.log( 'No config.open object' );

// returning an object to RTCMultiConnection
// so it can send data using "send" method
return {
send: function (data) {
data = {
channel: channel,
message: data,
sender: connection.userid
};

// posting data to server
// data is also JSON-ified.
xhr('xhr-signalhandler-post.php', null, JSON.stringify(data));
},
channel: channel
};
};

connection.session = {
audio: true,
video: true,
data: true
};

connection.sdpConstraints.mandatory = {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
};

connection.videosContainer = document.getElementById('videos-container');
connection.onstream = function(event) {
var width = parseInt(connection.videosContainer.clientWidth / 2) - 20;
var mediaElement = getHTMLMediaElement(event.mediaElement, {
title: event.userid,
buttons: ['full-screen'],
width: width,
showOnMouseEnter: false
});

connection.videosContainer.appendChild(mediaElement);

setTimeout(function() {
mediaElement.media.play();
}, 5000);

mediaElement.id = event.streamid;
};

connection.onstreamended = function(event) {
var mediaElement = document.getElementById(event.streamid);
if (mediaElement) {
mediaElement.parentNode.removeChild(mediaElement);
}
};

connection.onmessage = appendDIV;
connection.filesContainer = document.getElementById('file-container');

connection.onopen = function() {
console.log( "com. openend" );
document.getElementById('share-file').disabled = false;
document.getElementById('input-text-chat').disabled = false;
document.getElementById('btn-leave-room').disabled = false;

document.querySelector('h1').innerHTML = 'You are connected with: ' + connection.getAllParticipants().join(', ');
};

connection.onclose = function() {
if (connection.getAllParticipants().length) {
document.querySelector('h1').innerHTML = 'You are still connected with: ' + connection.getAllParticipants().join(', ');
} else {
document.querySelector('h1').innerHTML = 'Seems session has been closed or all participants left.';
}
};

connection.onEntireSessionClosed = function(event) {
document.getElementById('share-file').disabled = true;
document.getElementById('input-text-chat').disabled = true;
document.getElementById('btn-leave-room').disabled = true;

document.getElementById('open-or-join-room').disabled = false;
document.getElementById('open-room').disabled = false;
document.getElementById('join-room').disabled = false;
document.getElementById('room-id').disabled = false;

connection.attachStreams.forEach(function(stream) {
stream.stop();
});

// don't display alert for moderator
if (connection.userid === event.userid) return;
document.querySelector('h1').innerHTML = 'Entire session has been closed by the moderator: ' + event.userid;
};

connection.onUserIdAlreadyTaken = function(useridAlreadyTaken, yourNewUserId) {
// seems room is already opened
connection.join(useridAlreadyTaken);
};

function disableInputButtons() {
document.getElementById('open-or-join-room').disabled = true;
document.getElementById('open-room').disabled = true;
document.getElementById('join-room').disabled = true;
document.getElementById('room-id').disabled = true;
}

// ......................................................
// ......................Handling Room-ID................
// ......................................................

function showRoomURL(roomid) {
var roomHashURL = '#' + roomid;
var roomQueryStringURL = '?roomid=' + roomid;

var html = '<h2>Unique URL for your room:</h2><br>';

html += 'Hash URL: <a href="' + roomHashURL + '" target="_blank">' + roomHashURL + '</a>';
html += '<br>';
html += 'QueryString URL: <a href="' + roomQueryStringURL + '" target="_blank">' + roomQueryStringURL + '</a>';

var roomURLsDiv = document.getElementById('room-urls');
roomURLsDiv.innerHTML = html;

roomURLsDiv.style.display = 'block';
}

(function() {
var params = {},
r = /([^&=]+)=?([^&]*)/g;

function d(s) {
return decodeURIComponent(s.replace(/\+/g, ' '));
}
var match, search = window.location.search;
while (match = r.exec(search.substring(1)))
params[d(match[1])] = d(match[2]);
window.params = params;
})();

var roomid = '';
if (localStorage.getItem(connection.socketMessageEvent)) {
roomid = localStorage.getItem(connection.socketMessageEvent);
} else {
roomid = connection.token();
}
document.getElementById('room-id').value = roomid;
document.getElementById('room-id').onkeyup = function() {
localStorage.setItem(connection.socketMessageEvent, this.value);
};

var hashString = location.hash.replace('#', '');
if (hashString.length && hashString.indexOf('comment-') == 0) {
hashString = '';
}

var roomid = params.roomid;
if (!roomid && hashString.length) {
roomid = hashString;
}

if (roomid && roomid.length) {
document.getElementById('room-id').value = roomid;
localStorage.setItem(connection.socketMessageEvent, roomid);

// auto-join-room
(function reCheckRoomPresence() {
connection.checkPresence(roomid, function(isRoomExists) {
if (isRoomExists) {
connection.join(roomid);
return;
}

setTimeout(reCheckRoomPresence, 5000);
});
})();

disableInputButtons();
}
</script>

<footer>
<small id="send-message"></small>
</footer>

<script src="common.js"></script>
</body>
</html>

XHRConnection.js:

function XHRConnection(connection, connectCallback) {

connection.socket = {
send: function(data) {
data = {
message: data,
sender: connection.userid
};

// posting data to server
// data is also JSON-ified.
xhr('xhr-signalhandler-post.php', null, JSON.stringify(data));
}
};


// this object is used to make sure identical messages are not used multiple times
var messagesReceived = {};

function repeatedlyCheck() {
xhr('xhr-signalhandler-get.php', function(data) {
// if server says nothing; wait.
if (data == false) return setTimeout(repeatedlyCheck, 400);

// if already receied same message; skip.
if (messagesReceived[data.ID]) return setTimeout(repeatedlyCheck, 400);
messagesReceived[data.ID] = data.Message;

// "Message" property is JSON-ified in "openSignalingChannel handler
data = JSON.parse(data.Message);

if (data.eventName === connection.socketMessageEvent) {
onMessagesCallback(data.data);
}

if (data.eventName === 'presence') {
data = data.data;
if (data.userid === connection.userid) return;
connection.onUserStatusChanged({
userid: data.userid,
status: data.isOnline === true ? 'online' : 'offline',
extra: connection.peers[data.userid] ? connection.peers[data.userid].extra : {}
});
}

// repeatedly check the database
setTimeout(repeatedlyCheck, 1);
});
}

repeatedlyCheck();

setTimeout
(
function() {

if (connection.enableLogs) {
console.info('XHR connection opened');
}

connection.socket.emit('presence', {
userid: connection.userid,
isOnline: true
});

if( connectCallback ) {
console.log( 'Calling connectCallback...' );
connectCallback(connection.socket);
console.log( 'Done' );
}
},

2000
);

connection.socket.emit = function(eventName, data, callback) {
if (eventName === 'changed-uuid') return;
if (data.message && data.message.shiftedModerationControl) return;

connection.socket.send({
eventName: eventName,
data: data
});

if (callback) {
callback();
}
};

var mPeer = connection.multiPeersHandler;

function onMessagesCallback(message) {
if (message.remoteUserId != connection.userid) return;

if (connection.peers[message.sender] && connection.peers[message.sender].extra != message.extra) {
connection.peers[message.sender].extra = message.extra;
connection.onExtraDataUpdated({
userid: message.sender,
extra: message.extra
});
}

if (message.message.streamSyncNeeded && connection.peers[message.sender]) {
var stream = connection.streamEvents[message.message.streamid];
if (!stream || !stream.stream) {
return;
}

var action = message.message.action;

if (action === 'ended' || action === 'stream-removed') {
connection.onstreamended(stream);
return;
}

var type = message.message.type != 'both' ? message.message.type : null;
stream.stream[action](type);
return;
}

if (message.message === 'connectWithAllParticipants') {
if (connection.broadcasters.indexOf(message.sender) === -1) {
connection.broadcasters.push(message.sender);
}

mPeer.onNegotiationNeeded({
allParticipants: connection.getAllParticipants(message.sender)
}, message.sender);
return;
}

if (message.message === 'removeFromBroadcastersList') {
if (connection.broadcasters.indexOf(message.sender) !== -1) {
delete connection.broadcasters[connection.broadcasters.indexOf(message.sender)];
connection.broadcasters = removeNullEntries(connection.broadcasters);
}
return;
}

if (message.message === 'dropPeerConnection') {
connection.deletePeer(message.sender);
return;
}

if (message.message.allParticipants) {
if (message.message.allParticipants.indexOf(message.sender) === -1) {
message.message.allParticipants.push(message.sender);
}

message.message.allParticipants.forEach(function(participant) {
mPeer[!connection.peers[participant] ? 'createNewPeer' : 'renegotiatePeer'](participant, {
localPeerSdpConstraints: {
OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
remotePeerSdpConstraints: {
OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
isOneWay: !!connection.session.oneway || connection.direction === 'one-way',
isDataOnly: isData(connection.session)
});
});
return;
}

if (message.message.newParticipant) {
if (message.message.newParticipant == connection.userid) return;
if (!!connection.peers[message.message.newParticipant]) return;

mPeer.createNewPeer(message.message.newParticipant, message.message.userPreferences || {
localPeerSdpConstraints: {
OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
remotePeerSdpConstraints: {
OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
isOneWay: !!connection.session.oneway || connection.direction === 'one-way',
isDataOnly: isData(connection.session)
});
return;
}

if (message.message.readyForOffer || message.message.addMeAsBroadcaster) {
connection.addNewBroadcaster(message.sender);
}

if (message.message.newParticipationRequest && message.sender !== connection.userid) {
if (connection.peers[message.sender]) {
connection.deletePeer(message.sender);
}

var userPreferences = {
extra: message.extra || {},
localPeerSdpConstraints: message.message.remotePeerSdpConstraints || {
OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
remotePeerSdpConstraints: message.message.localPeerSdpConstraints || {
OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
isOneWay: typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way',
isDataOnly: typeof message.message.isDataOnly !== 'undefined' ? message.message.isDataOnly : isData(connection.session),
dontGetRemoteStream: typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way',
dontAttachLocalStream: !!message.message.dontGetRemoteStream,
connectionDescription: message,
successCallback: function() {
// if its oneway----- todo: THIS SEEMS NOT IMPORTANT.
if (typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way') {
connection.addNewBroadcaster(message.sender, userPreferences);
}

if (!!connection.session.oneway || connection.direction === 'one-way' || isData(connection.session)) {
connection.addNewBroadcaster(message.sender, userPreferences);
}
}
};

connection.onNewParticipant(message.sender, userPreferences);
return;
}

if (message.message.shiftedModerationControl) {
connection.onShiftedModerationControl(message.sender, message.message.broadcasters);
return;
}

if (message.message.changedUUID) {
if (connection.peers[message.message.oldUUID]) {
connection.peers[message.message.newUUID] = connection.peers[message.message.oldUUID];
delete connection.peers[message.message.oldUUID];
}
}

if (message.message.userLeft) {
mPeer.onUserLeft(message.sender);

if (!!message.message.autoCloseEntireSession) {
connection.leave();
}

return;
}

mPeer.addNegotiatedMessage(message.message, message.sender);
}

window.addEventListener('beforeunload', function() {
connection.socket.emit('presence', {
userid: connection.userid,
isOnline: false
});
}, false);
}


// a simple function to make XMLHttpRequests
function xhr( url, callback, data ) {

// if( data ) console.log('[' + url + '] sending: ' + JSON.stringify( data ) );

if (!window.XMLHttpRequest || !window.JSON){
console.log( 'No JSON and/or XMLHttpRequest support' );
return;
}

var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (callback && request.readyState == 4 && request.status == 200) {
// server MUST return JSON text

if( request.responseText != 'false' )
console.log('Logging non-false data [from ' + url + ']: ' + request.responseText + "[...data POST'ed: " + JSON.stringify( data ) + "]" );

callback(JSON.parse(request.responseText));
}
};

request.open( 'POST', url );
var formData = new FormData();

// you're passing "message" parameter
formData.append( 'message', data );
request.send(formData);
}

开始广播.php:

<?php
require( "connection.inc.php" );

if( isset( $_POST['message'] ) )
{
$data = json_decode( $_POST['message'] , true );
// Now, if someone initiates WebRTC session; you should make an XHR request to create a record in the room-table; and
// set "Owner-id" equals to that user's "user-id".

//{"message":{"eventName":"presence","data":{"userid":"winey","isOnline":true}},"sender":"winey"}

$query = " INSERT INTO active_broadcasts ( name ) VALUES ( '{$data['name']}' ) ";

if( $mysqli->query( $query ) )
{
$transport = json_encode( false );
exit( $transport );
}
else
exit( $mysqli->error );
}
else
exit( 'No data sent' );
?>

xhr-signalhandler-post.php:

<?php
require( "connection.inc.php" );

$response = array();

//{"message":{"eventName":"presence","data":{"userid":"winey","isOnline":true}},"sender":"winey"}

// var_dump( $_POST );
// exit;

if( isset( $_POST['message'] ) )
{
$query = " INSERT INTO webrtc-messages ( name ) VALUES ( '{$_POST['name']}' ) ";

if( $mysqli->query( $query ) )
{
$transport = json_encode( false );
exit( $transport );
}
else
exit( $mysqli->error );

// Now, if someone else joins the room; you can update above record; and append his "user-id" in the "Participants-id" column.
}


if( @$_POST["message"] = "undefined" )
$response = false;

$transport = json_encode( $response );
exit( $transport );

?>

xhr-signalhandler-get.php:

<?php
require( "connection.inc.php" );
$response = array();

// var_dump( $_POST );

if( isset( $_POST['message'] ) )
{
$query = "SELECT id , message , channel , `sender-id` FROM `webrtc-messages` ";

if( $mysqli->connect_errno )
exit ( "Failed to connect to MySQL: " . $mysqli->connect_error );

if( $res = $mysqli->query( $query ) )
{
if( $res->num_rows > 0 )
{
while( $value = mysqli_fetch_assoc( $res ) )
{
//
}
}
}
else
{
echo "<center class='text-danger'>Server error</center>";
exit( $mysqli->error );
}
}

if( @$_POST["message"] = "undefined" )
$response = false;

$transport = json_encode( $response );
exit( $transport );
?>

最佳答案

我从来没有玩过 WebRTC 或 RTCMultiConnection,但我想我明白你的问题出在哪里。

当您使用 XHR 时,您的客户端(网络浏览器)和服务器之间没有直接连接。因此,服务器无法将信息推送到客户端,因此永远不会触发 openSignalingChannel 覆盖。

诀窍是定期调用一个函数来检查服务器状态(又名长轮询)。

如果您查看关于 openSignalingChannel 覆盖 (http://www.rtcmulticonnection.org/docs/openSignalingChannel/#xhr-signaling) 的 RTCMultiConnection 文档,您会注意到 repeatedlyCheck(); 的使用。我认为这是您拼图中缺失的一 block 。

希望对您有所帮助。

关于javascript - localhost : how to setup XHR-Signaling (connection. openSignalingChannel 未被调用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45666142/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com