RTCMultiConnection API References
You can search docs/APIs here:
- You can run nodejs on a separate domain or separate port or on a separate server
- You can set
socketURL="ip-address"
to link nodejs server - Now you can run RTCMultiConnection demos on any webpage; whether it is PHP page, ASP.net page, python or ruby page or whatever framework running top over HTML.
connection.socketURL = 'https://onlyChangingPort.com:8888/';
connection.socketURL = 'https://separateDomain.com:443/';
connection.socketURL = '/'; // same domain
// or a free signaling server:
// v3.4.7 or newer
connection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/';
// v3.4.6 or older
connection.socketURL = 'https://webrtcweb.com:9001/';
You can pass your custom socket.io parameters as well:
// starts with "&"
// &fullName=Muaz
// &meetingId=xyz
connection.socketCustomParameters = '&fullName=Muaz&country=PK&meetingId=xyz';
Now you can open server.js
and access above parameters here:
// you can find below line on "server.js" file
require('./Signaling-Server.js')(app, function(socket) {
var params = socket.handshake.query;
var meetingId = params.meetingId;
var fullName = params.fullName;
var country = params.country;
var userid = params.userid;
// etc.
});
This feature allows you reliably update-extra data on nodejs before socket.io connection opens.
connection.extra = {
fullName: 'Muaz Khan',
joinedAt: (new Date).toISOString()
};s
connection.socketCustomParameters = '&extra=' + JSON.stringify(connection.extra);
connection.openOrJoin('room-id');
This method allows you change video resolutions or audio sources without making a new getUserMedia request i.e. it modifies your existing MediaStream:
var width = 1280;
var height = 720;
var supports = navigator.mediaDevices.getSupportedConstraints();
var constraints = {};
if (supports.width && supports.height) {
constraints = {
width: width,
height: height
};
}
connection.applyConstraints({
video: constraints
});
applyConstraints
access mediaConstraints
object, defined here:
This method allows you replace your front-camera video with back-camera video or replace video with screen or replace older low-quality video with new high quality video.
// here is its simpler usage
connection.replaceTrack({
screen: true,
oneway: true
});
You can even pass MediaStreamTrack
object:
var videoTrack = yourVideoStream.getVideoTracks()[0];
connection.replaceTrack(videoTrack);
You can even pass MediaStream
object:
connection.replaceTrack(yourVideoStream);
You can even force to replace tracks only with a single user:
var remoteUserId = 'single-remote-userid';
var videoTrack = yourVideoStream.getVideoTracks()[0];
connection.replaceTrack(videoTrack, remoteUserId);
If you replaced a video or audio track, RTCMultiConnection keeps record of old track, and allows you move-back-to previous track:
connection.resetTrack(null, true);
It takes following arguments:
[Array of user-ids]
or"single-user-id"
ornull
- Is video track (boolean): Either
true
orfalse
.null
means replace all last tracks.
// with single user
connection.resetTrack('specific-userid', true);
// with multiple users
connection.resetTrack(['first-user', 'second-user'], true);
// NULL means all users
connection.resetTrack(null, true);
// reset only audio
connection.resetTrack(null, false);
// to reset all last-tracks (both audio and video)
connection.resetTrack();
Means that you can reset all tracks that are replaced recently.
This event allows you show online/offline statuses of the user:
connection.onUserStatusChanged = function(status) {
document.getElementById(event.userid).src = status === 'online' ? 'online.gif' : 'offline.gif';
};
You can even manually call above method from onopen
, onstream
and similar events to get the most accurate result possible:
connection.onopen = connection.stream = function(event) {
connection.onUserStatusChanged({
userid: event.userid,
extra: event.extra,
status: 'online'
});
};
connection.onleave = connection.streamended = connection.onclose = function(event) {
connection.onUserStatusChanged({
userid: event.userid,
extra: event.extra,
status: 'offline'
});
};
connection.maxParticipantsAllowed = 1; // one-to-one
connection.onRoomFull = function(roomid) {
alert('Room is full.');
};
This method allows you get the socket
object used for signaling (handshake/presence-detection/etc.):
var socket = connection.getSocket();
socket.emit('custom-event', 'hi there');
socket.on('custom-event', function(message) {
alert(message);
});
If socket isn't connected yet, then above method will auto-connect it. It is using connectSocket
to connect socket. See below section.
It is same like old RTCMultiConnection connect
method:
connectSocket
method simply initializes socket.io server so that you can send custom-messages before creating/joining rooms:
connection.connectSocket(function(socket) {
socket.on('custom-message', function(message) {
alert(message);
// custom message
if(message.joinMyRoom) {
connection.join(message.roomid);
}
});
socket.emit('custom-message', 'hi there');
connection.open('room-id');
});
A string
property, allows you set custom socket.io event listener:
connection.socketCustomEvent = 'abcdef';
connection.openOrJoin('roomid', function() {
connection.socket.on(connection.socketCustomEvent, function(message) {
alert(message);
});
connection.socket.emit(connection.socketCustomEvent, 'My userid is: ' + connection.userid);
});
This method allows you set custom socket listeners anytime, during a live session:
connection.setCustomSocketEvent('abcdef');
connection.socket.on('abcdef', function(message) {
alert(message);
});
connection.socket.emit('abcdef', 'My userid is: ' + connection.userid);
This object allows you capture audio/video stream yourself. RTCMultiConnection will NEVER know about your stream until you add it yourself, manually:
var options = {
localMediaConstraints: {
audio: true,
video: true
},
onGettingLocalMedia: function(stream) {},
onLocalMediaError: function(error) {}
};
connection.getUserMediaHandler(options);
Its defined here:
You can force dontAttachStream
and dontGetRemoteStream
for any or each user in any situation:
connection.setUserPreferences = function(userPreferences) {
if (connection.dontAttachStream) {
// current user's streams will NEVER be shared with any other user
userPreferences.dontAttachLocalStream = true;
}
if (connection.dontGetRemoteStream) {
// current user will NEVER receive any stream from any other user
userPreferences.dontGetRemoteStream = true;
}
return userPreferences;
};
Scenarios:
- All users in the room are having cameras
- All users in the room can see only self video
- All users in the room can text-chat or share files; but can't share videos
- As soon as teacher or moderator or presenter enters in the room; he can ask all the participants or specific participants to share their cameras with single or multiple users.
They can enable cameras as following:
connection.onmessage = function(event) {
var message = event.data;
if(message.shareYourCameraWithMe) {
connection.dontAttachStream = false;
connection.renegotiate(event.userid); // share only with single user
}
if(message.shareYourCameraWithAllUsers) {
connection.dontAttachStream = false;
connection.renegotiate(); // share with all users
}
}
i.e. setUserPreferences
allows you enable camera on demand.
This method allows you check presence of the moderators/rooms:
connection.checkPresence('roomid', function(isRoomEists, roomid) {
if(isRoomEists) {
connection.join(roomid);
}
else {
connection.open(roomid);
}
});
This event is fired as soon as callee says "I am ready for offer. I enabled camera. Please create offer and share.".
connection.onReadyForOffer = function(remoteUserId, userPreferences) {
// if OfferToReceiveAudio/OfferToReceiveVideo should be enabled for specific users
userPreferences.localPeerSdpConstraints.OfferToReceiveAudio = true;
userPreferences.localPeerSdpConstraints.OfferToReceiveVideo = true;
userPreferences.dontAttachStream = false; // according to situation
userPreferences.dontGetRemoteStream = false; // according to situation
// below line must be included. Above all lines are optional.
connection.multiPeersHandler.createNewPeer(remoteUserId, userPreferences);
};
This event is fired as soon as someone tries to join you. You can either reject his request or set preferences.
connection.onNewParticipant = function(participantId, userPreferences) {
// if OfferToReceiveAudio/OfferToReceiveVideo should be enabled for specific users
userPreferences.localPeerSdpConstraints.OfferToReceiveAudio = true;
userPreferences.localPeerSdpConstraints.OfferToReceiveVideo = true;
userPreferences.dontAttachStream = false; // according to situation
userPreferences.dontGetRemoteStream = false; // according to situation
// below line must be included. Above all lines are optional.
// if below line is NOT included; "join-request" will be considered rejected.
connection.acceptParticipationRequest(participantId, userPreferences);
};
Or:
var alreadyAllowed = {};
connection.onNewParticipant = function(participantId, userPreferences) {
if(alreadyAllowed[participantId]) {
connection.addParticipationRequest(participantId, userPreferences);
return;
}
var message = participantId + ' is trying to join your room. Confirm to accept his request.';
if( window.confirm(messsage ) ) {
connection.addParticipationRequest(participantId, userPreferences);
}
};
Disconnect with single or multiple users. This method allows you keep connected to socket
however either leave entire room or remove single or multiple users:
connection.disconnectWith('remoteUserId');
// to leave entire room
connection.getAllParticipants().forEach(function(participantId) {
connection.disconnectWith(participantId);
});
Get list of all participants that are connected with current user.
var numberOfUsersInTheRoom = connection.getAllParticipants().length;
var remoteUserId = 'xyz';
var isUserConnectedWithYou = connection.getAllParticipants().indexOf(remoteUserId) !== -1;
connection.getAllParticipants().forEach(function(remoteUserId) {
var user = connection.peers[remoteUserId];
console.log(user.extra);
user.peer.close();
alert(user.peer === webkitRTCPeerConnection);
});
Set number of users who can join your room.
// to allow another single person to join your room
// it will become one-to-one (i.e. you+anotherUser)
connection.maxParticipantsAllowed = 1;
This method allows you skip Socket.io and force custom signaling implementations e.g. SIP-signaling, XHR-signaling, SignalR/WebSync signaling, Firebase/PubNub signaling etc.
Here is Firebase example:
<script src="/dev/globals.js"></script>
<script src="/dev/FirebaseConnection.js"></script>
<script>
var connection = new RTCMultiConnection();
connection.firebase = 'your-firebase-account';
// below line replaces FirebaseConnection
connection.setCustomSocketHandler(FirebaseConnection);
</script>
Here is PubNub example:
<script src="/dev/globals.js"></script>
<script src="/dev/PubNubConnection.js"></script>
<script>
var connection = new RTCMultiConnection();
// below line replaces PubNubConnection
connection.setCustomSocketHandler(PubNubConnection);
</script>
SIP/SignalR/WebSync/XHR signaling:
// please don't forget linking /dev/globals.js
var connection = new RTCMultiConnection();
// SignalR (requires /dev/SignalRConnection.js)
connection.setCustomSocketHandler(SignalRConnection);
// WebSync (requires /dev/WebSyncConnection.js)
connection.setCustomSocketHandler(WebSyncConnection);
// XHR (requires /dev/XHRConnection.js)
connection.setCustomSocketHandler(XHRConnection);
// Sip (requires /dev/SipConnection.js)
connection.setCustomSocketHandler(SipConnection);
Please check FirebaseConnection
or PubNubConnection.js
to understand how it works.
For more information:
- https://rtcmulticonnection.herokuapp.com/demos/Audio+Video+TextChat+FileSharing.html#comment-2670178473
- https://rtcmulticonnection.herokuapp.com/demos/Audio+Video+TextChat+FileSharing.html#comment-2670182313
By default, logs are enabled.
connection.enableLogs = false; // to disable logs
connection.extra = {
joinTime: new Date()
};
connection.updateExtraData();
Here is how to get extra-data:
var extra = connection.peers['remote-userid'].extra;
alert( extra.joinTime);
Recent commit supports this as well:
connection.onstream = function(event) {
if(event.type === 'remote') {
connection.socket.emit('get-remote-user-extra-data', event.userid, function(extra) {
alert( extra.joinTime );
});
}
}:
You can force all the extra-data to be synced among all connected users.
connection.extra.fullName = 'New Full Name';
connection.updateExtraData(); // now above value will be auto synced among all connected users
This event is fired as soon as extra-data from any user is updated:
connection.onExtraDataUpdated = function(event) {
console.log('extra data updated', event.userid, event.extra);
// make sure that <video> header is having latest fullName
document.getElementById('video-header').innerHTML = event.extra.fullName;
};
It is similar to this:
Socket.io options:
connection.socketOptions = {
'force new connection': true, // For SocketIO version < 1.0
'forceNew': true, // For SocketIO version >= 1.0
'transport': 'polling' // fixing transport:unknown issues
};
Or:
connection.socketOptions.resource = 'custom';
connection.socketOptions.transport = 'polling';
connection.socketOptions['try multiple transports'] = false;
connection.socketOptions.secure = true;
connection.socketOptions.port = '9001';
connection.socketOptions['max reconnection attempts'] = 100;
// etc.
connection.open('roomid', function() {
connection.socket.emit('whatever', 'hmm');
connection.socket.disconnect();
});
Wanna detect current browser?
if(connection.DetectRTC.browser.isChrome) {
// it is Chrome
}
// you can even set backward compatibility hack
connection.UA = connection.DetectRTC.browser;
if(connection.UA.isChrome) { }
Wanna detect if user is having microphone or webcam?
connection.DetectRTC.detectMediaAvailability(function(media){
if(media.hasWebcam) { }
if(media.hasMicrophone) { }
if(media.hasSpeakers) { }
});
Get files problematically instead of using input[type=file]
:
connection.invokeSelectFileDialog(function(file) {
var file = this.files[0];
if(file){
connection.shareFile(file);
}
});
Force bandwidth, bitrates, etc.
var BandwidthHandler = connection.BandwidthHandler;
connection.bandwidth = {
audio: 128,
video: 256,
screen: 300
};
connection.processSdp = function(sdp) {
sdp = BandwidthHandler.setApplicationSpecificBandwidth(sdp, connection.bandwidth, !!connection.session.screen);
sdp = BandwidthHandler.setVideoBitrates(sdp, {
min: connection.bandwidth.video,
max: connection.bandwidth.video
});
sdp = BandwidthHandler.setOpusAttributes(sdp);
sdp = BandwidthHandler.setOpusAttributes(sdp, {
'stereo': 1,
//'sprop-stereo': 1,
'maxaveragebitrate': connection.bandwidth.audio * 1000 * 8,
'maxplaybackrate': connection.bandwidth.audio * 1000 * 8,
//'cbr': 1,
//'useinbandfec': 1,
// 'usedtx': 1,
'maxptime': 3
});
return sdp;
};
A DOM-element to show progress-bars and preview files.
connection.filesContainer = document.getElementById('files-container');
A DOM-element to append videos or audios or screens:
connection.videosContainer = document.getElementById('videos-container');
If screen or video capturing fails:
connection.onMediaError = function(error) {
alert( 'onMediaError:\n' + JSON.stringify(error) );
};
Note on 10-02-2018:
replaceTrack
is preferred overrenegotiate
.
Recreate peers. Capture new video using connection.captureUserMedia
and call connection.renegotiate()
and that new video will be shared with all connected users.
connection.renegotiate('with-single-userid');
connection.renegotiate(); // with all users
You can even pass streamCallback
and check if user declined prompt to share
screen:
connection.addStream({
screen: true,
oneway: true,
streamCallback: function(screenStream) {
// this will be fired as soon as stream is captured
if (!screenStream) {
alert('User did NOT select to share any stream. He clicked "Cancel" button instead.');
return;
}
screenStream.onended = function() {
document.getElementById('share-screen').disabled = false;
// or show button
$('#share-screen').show();
};
};
});
You can even pass streamCallback
:
connection.removeStream('streamid');
connection.renegotiate();
You must set userid before opening or joining a room:
connection.userid = 'abcdef';
connection.openOrJoin('roomid');
To enable two-way audio however one-way screen or video:
// video is oneway, however audio is two-way
connection.session = {
audio: 'two-way',
video: true,
oneway: true
};
// screen is oneway, however audio is two-way
connection.session = {
audio: 'two-way',
screen: true,
oneway: true
};
To enable file sharing. By default, it is false
:
connection.enableFileSharing = true;
Change userid and update userid among all connected peers:
connection.changeUserId('new-userid');
// or callback to check if userid is successfully changed
connection.changeUserId('new-userid', function() {
alert('Your userid is successfully changed to: ' + connection.userid);
});
It is true
by default. If you are handling window.onbeforeunload
yourself, then you can set it to false
:
connection.closeBeforeUnload = false;
window.onbeforeunlaod = function() {
connection.close();
};
You can skip using autoCloseEntireSession
. You can keep session/room opened whenever/wherever required and dynamically close the entire room using this method.
connection.closeEntireSession();
// or callback
connection.closeEntireSession(function() {
alert('Entire session has been closed.');
});
// or before leaving a page
connection.closeBeforeUnload = false;
window.onbeforeunlaod = function() {
connection.closeEntireSession();
};
connection.closeSocket(); // close socket.io connections
This event is fired if two users tries to open same room.
connection.onUserIdAlreadyTaken = function(useridAlreadyTaken, yourNewUserId) {
if (connection.enableLogs) {
console.warn('Userid already taken.', useridAlreadyTaken, 'Your new userid:', yourNewUserId);
}
connection.join(useridAlreadyTaken);
};
Above event gets fired out of this code:
moderator1.open('same-roomid');
moderator2.open('same-roomid');
You can tell users that room-moderator closed entire session:
connection.onEntireSessionClosed = function(event) {
console.info('Entire session is closed: ', event.sessionid, event.extra);
};
Open room:
connection.open('roomid', function(isRoomCreated, roomid, error) {
if(error) {
alert(error);
// if error says that room is already created
connection.join('room-id');
return;
}
});
Join room:
connection.join('roomid', function(isRoomJoined, roomid, error) {
if(error) {
// maybe room does not exist
// maybe room is full
// maybe password is invalid
alert(error);
return;
}
});
// or pass "options"
connection.join('roomid', {
localPeerSdpConstraints: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
},
remotePeerSdpConstraints: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
},
isOneWay: false,
isDataOnly: false
});
connection.openOrJoin('roomid');
// or
connection.openOrJoin('roomid', function(isRoomOpened, roomid) {
if(isRoomOpened === true) {
alert('opened the room');
}
else {
alert('joined the room');
}
});
By default, it is false
. Which means that RTCMultiConnection will always capture video if connection.session.video===true
.
If you are attaching external streams, you can ask RTCMultiConnection to DO NOT capture video:
connection.dontCaptureUserMedia = true;
By default, it is false
. Which means that RTCMultiConnection will always attach local streams.
connection.dontAttachStream = true;
By default, it is false
. Which means that RTCMultiConnection will always get remote streams.
connection.dontGetRemoteStream = true;
This event is fired as soon as RTCMultiConnection calls the nativePeer.setLocalDescription
method.
This event helps you say: "incoming call" or debug peers if connection didn't establish till next 3 seconds.
This method is helpful if you switch between cameras or you add screen or add other camera or change anything:
connection.onSettingLocalDescription = fucntion(event) {
console.log('Trying to connect with', event.userid);
var nativePeer = event.peer;
var localStreams = nativePeer.getLocalStreams();
var remoteStreams = nativePeer.getRemoteStreams();
// make sure that you are correctly displaying all remote videos
var tries = 0;
(function looper() {
if(tries > 10) return; // throw error here
tries++;
// make sure that each user's video.id == hisUserID
var video = document.getElementById(event.userid);
// skip: if user left or if user video is playing
if(!video || video.currentTIme > 0) return;
video.src = URL.createObjectURL ( nativePeer.getRemoteStreams()[0] );
video.play();
setTimeout(looper, 1000); // repeat till 10-seconds
})();
};
You can skip any stream or allow RTCMultiConnection to share a stream with remote users.
nativePeer.addStream
method will be called only if below event permits the MediaStream
object:
connection.beforeAddingStream = function(stream, peer) {
if(stream.id == 'any-streamid') return; // skip
if(stream.isScreen) return; // skip
if(stream.inactive) return; // skip
// var remoteUserId = peer.userid;
// var remoteUserExtra = connection.peers[remoteUserId].extra;
return stream; // otherwise allow RTCMultiConnection to share this stream with remote users
};
This method allows you get full control over screen-parameters:
connection.__getScreenConstraints = connection.getScreenConstraints;
connection.getScreenConstraints = function(callback) {
connection.__getScreenConstraints(function(error, screen_constraints) {
if (connection.DetectRTC.browser.name === 'Chrome') {
delete screen_constraints.mandatory.minAspectRatio;
delete screen_constraints.mandatory.googLeakyBucket;
delete screen_constraints.mandatory.googTemporalLayeredScreencast;
delete screen_constraints.mandatory.maxWidth;
delete screen_constraints.mandatory.maxHeight;
delete screen_constraints.mandatory.minFrameRate;
delete screen_constraints.mandatory.maxFrameRate;
}
callback(error, screen_constraints);
});
};
Or to more simplify it:
connection.__getScreenConstraints = connection.getScreenConstraints;
connection.getScreenConstraints = function(callback) {
connection.__getScreenConstraints(function(error, screen_constraints) {
if (connection.DetectRTC.browser.name === 'Chrome') {
screen_constraints.mandatory = {
chromeMediaSource: screen_constraints.mandatory.chromeMediaSource,
chromeMediaSourceId: screen_constraints.mandatory.chromeMediaSourceId
};
}
callback(error, screen_constraints);
});
};
You can even delete width/height for Firefox:
connection.__getScreenConstraints = connection.getScreenConstraints;
connection.getScreenConstraints = function(callback) {
connection.__getScreenConstraints(function(error, screen_constraints) {
if (connection.DetectRTC.browser.name === 'Chrome') {
delete screen_constraints.mandatory.minAspectRatio;
}
if (connection.DetectRTC.browser.name === 'Firefox') {
delete screen_constraints.width;
delete screen_constraints.height;
}
callback(error, screen_constraints);
});
};
First step, install this chrome extension:
Now use below code in any RTCMultiConnection (screen) demo:
<script src="/dev/globals.js"></script>
<!-- capture screen from any HTTPs domain! -->
<script src="https://cdn.webrtc-experiment.com:443/getScreenId.js"></script>
<script>
// Using getScreenId.js to capture screen from any domain
// You do NOT need to deploy Chrome Extension YOUR-Self!!
connection.getScreenConstraints = function(callback, audioPlusTab) {
if (isAudioPlusTab(connection, audioPlusTab)) {
audioPlusTab = true;
}
getScreenConstraints(function(error, screen_constraints) {
if (!error) {
screen_constraints = connection.modifyScreenConstraints(screen_constraints);
callback(error, screen_constraints);
}
}, audioPlusTab);
};
</script>
Don't want to link /dev/globals.js
or want to simplify codes???
<!-- capture screen from any HTTPs domain! -->
<script src="https://cdn.webrtc-experiment.com:443/getScreenId.js"></script>
<script>
// Using getScreenId.js to capture screen from any domain
// You do NOT need to deploy Chrome Extension YOUR-Self!!
connection.getScreenConstraints = function(callback) {
getScreenConstraints(function(error, screen_constraints) {
if (!error) {
screen_constraints = connection.modifyScreenConstraints(screen_constraints);
callback(error, screen_constraints);
}
});
};
</script>
RTCMultiConnection now supports WebRTC scalable broadcasting. Two new API are introduced: enableScalableBroadcast
and singleBroadcastAttendees
.
connection.enableScalableBroadcast = true; // by default, it is false.
connection.singleBroadcastAttendees = 3; // how many users are handled by each broadcaster
Live Demos:
DemoTitle | TestLive | ViewSource |
---|---|---|
Scalable Audio/Video Broadcast | Demo | Source |
Scalable Screen Broadcast | Demo | Source |
Scalable Video Broadcast | Demo | Source |
Scalable File Sharing | Demo | Source |
This event is fired for scalable-broadcast-initiator.
connection.onNumberOfBroadcastViewersUpdated = function(event) {
// event.broadcastId
// event.numberOfBroadcastViewers
console.info('Number of broadcast (', event.broadcastId, ') viewers', event.numberOfBroadcastViewers);
};
You can manually get number-of-broadcast viewers as well:
connection.getNumberOfBroadcastViewers('broadcast-unique-id', function(numberOfBroadcastViewers) {
alert(numberOfBroadcastViewers);
});
connection.onstream = function(event) {
if(event.mediaElement) {
event.mediaElement.muted = true;
delete event.mediaElement;
}
var video = document.createElement('video');
if(event.type === 'local') {
video.muted = true;
}
video.src = URL.createObjectURL(event.stream);
connection.videosContainer.appendChild(video);
}
connection.multiPeersHandler.onPeerStateChanged = function(state) {
if (state.iceConnectionState.search(/disconnected|closed|failed/gi) === -1 && !connection.isConnected) {
connection.isConnected = true;
var peer = connection.peers[state.userid].peer;
getStats(peer, function(result) {
if (!result || !result.connectionType) return;
// "relay" means TURN server
// "srflx" or "prflx" means STUN server
// "host" means neither STUN, nor TURN
console.debug('Incoming stream is using:', result.connectionType.remote.candidateType);
console.debug('Outgoing stream is using:', result.connectionType.local.candidateType);
// user external ip-addresses
console.debug('Remote user ip-address:', result.connectionType.remote.ipAddress);
console.debug('Local user ip-address:', result.connectionType.local.ipAddress);
// UDP is a real media port; TCP is a fallback.
console.debug('Peers are connected on port:', result.connectionType.transport);
}, 5000);
return;
}
};
You can compare muteType
for onmute
event; and unmuteType
for onunmute
event.
connection.onmute = function(e) {
if (!e.mediaElement) {
return;
}
if (e.muteType === 'both' || e.muteType === 'video') {
e.mediaElement.src = null;
e.mediaElement.pause();
e.mediaElement.poster = e.snapshot || 'https://cdn.webrtc-experiment.com/images/muted.png';
} else if (e.muteType === 'audio') {
e.mediaElement.muted = true;
}
};
connection.onunmute = function(e) {
if (!e.mediaElement) {
return;
}
if (e.unmuteType === 'both' || e.unmuteType === 'video') {
e.mediaElement.poster = null;
e.mediaElement.src = URL.createObjectURL(e.stream);
e.mediaElement.play();
} else if (e.unmuteType === 'audio') {
e.mediaElement.muted = false;
}
};
connection.bandwidth = {
audio: 128,
video: 1024,
screen: 1024
};
var videoConstraints = {
mandatory: {
maxWidth: 1920,
maxHeight: 1080,
minAspectRatio: 1.77,
minFrameRate: 3,
maxFrameRate: 64
},
optional: []
};
connection.mediaConstraints.video = videoConstraints;
For low-latency audio:
By default, RTCMultiConnection tries to use last available microphone and camera. However you can disable this behavior and ask to use default devices instead:
// pass second parameter to force options
var connection = new RTCMultiConnection(roomId, {
useDefaultDevices: true
});
By default, you always have to call open
or join
or openOrJoin
methods manually. However you can force RTCMultiConnection to auto open/join room as soon as constructor is initialized.
// pass second parameter to force options
var connection = new RTCMultiConnection(roomId, {
autoOpenOrJoin: true
});
connection.codecs.video = 'H264';
<script src="/dev/CodecsHandler.js"></script>
<script>
// in your HTML file
connection.processSdp = function(sdp) {
// Disable NACK to test IDR recovery
sdp = CodecsHandler.disableNACK(sdp);
return sdp;
};
</script>
connection.codecs.video = 'VP8';
connection.codecs.audio = 'G722';
<script src="/dev/CodecsHandler.js"></script>
<script>
// in your HTML file
if(connection.DetectRTC.browser.name === 'Firefox') {
connection.getAllParticipants().forEach(function(p) {
var peer = connection.peers[p].peer;
CodecsHandler.prioritize('audio/opus', peer);
});
}
</script>
StreamHasData.js
allows you check if remote stream started flowing or if remote stream is successfully received or if remote stream has data or not.
<script src="/dev/StreamHasData.js"></script>
<script>
connection.videosContainer = document.getElementById('videos-container');
connection.onstream = function(event) {
StreamHasData.check(event.mediaElement, function(hasData) {
if (!hasData) {
alert('Seems stream does NOT has any data.');
}
// append video here
connection.videosContainer.appendChild(event.mediaElement);
event.mediaElement.play();
setTimeout(function() {
event.mediaElement.play();
}, 5000);
});
};
</script>
Demo: https://rtcmulticonnection.herokuapp.com/demos/StreamHasData.html
You can share files using connection.send(file)
. E.g.
fileInput.onchange = function() {
var file = this.files[0];
if(!file) return;
connection.send(file);
};
If you mistakenly shared wrong file, you can stop further sharing:
var file;
fileInput.onchange = function() {
file = this.files[0];
if(!file) return;
// First step: Set UUID for your file object
file.uuid = connection.token();
connection.send(file);
};
if(connection.fbr) {
// Second Last step: remove/delete file chunks based on file UUID
delete connection.fbr.chunks[file.uuid];
}
You can even set connection.fbr=null
. It is VERY EASY & reliable:
connection.fbr = null;
You can even try any of these (you don't need to care about file UUID):
if(connection.fbr) {
// clearing all file chunks
// removing all file receivers
connection.fbr.chunks = {};
connection.fbr.users = {};
}
You can set ports, logs, socket-URLs and other configuration using config.json
.
{
"socketURL": "/",
"socketMessageEvent": "RTCMultiConnection-Message",
"socketCustomEvent": "RTCMultiConnection-Custom-Message",
"port": "9001",
"enableLogs": "true"
}
Note: config.json
is completely optional. You can set each property directly in your HTML files using connection.property
e.g.
connection.socketURL = '/';
connection.socketMessageEvent = 'RTCMultiConnection-Message';
// etc.
config.json
provides enableLogs
attribute.
If enableLogs:true
then all unexpected-server-errors are logged into logs.json
file.
So, if you're facing unexpected-server-disconnection, or if your application is NOT working properly; for example, if userid
is NOT getting updated or if extra-data
is NOT getting-synced; then you can look into logs.json
to see unexpected errors.
You can either remove enableLogs
from the config.json
to disable logs; or you can use false
:
{
"enableLogs": "false"
}
- Getting Started guide for RTCMultiConnection
- Installation Guide
- How to Use?
- API Reference
- Upgrade from v2 to v3
- How to write iOS/Android applications?
- Tips & Tricks
- https://twitter.com/WebRTCWeb i.e. @WebRTCWeb
RTCMultiConnection is released under MIT licence . Copyright (c) Muaz Khan.