Merge remote-tracking branch 'upstream/develop' into share_photo_from_mobile_gallery

auto_join_3.3
Astagor 2020-05-05 08:11:23 +02:00
commit 9e14cfd924
7 changed files with 341 additions and 19 deletions

View File

@ -33,7 +33,7 @@ var config =
*/
audioOutputSupportedBrowsers :
[
'chrome',
'chrome',
'opera'
],
// Socket.io request timeout

View File

@ -38,6 +38,7 @@ import messagesCzech from './translations/cs';
import messagesItalian from './translations/it';
import messagesUkrainian from './translations/uk';
import messagesTurkish from './translations/tr';
import messagesLatvian from './translations/lv';
import './index.css';
@ -63,7 +64,8 @@ const messages =
'cs' : messagesCzech,
'it' : messagesItalian,
'uk' : messagesUkrainian,
'tr' : messagesTurkish
'tr' : messagesTurkish,
'lv' : messagesLatvian
};
const locale = navigator.language.split(/[-_]/)[0]; // language without region code

View File

@ -0,0 +1,170 @@
{
"socket.disconnected": "Esat bezsaistē",
"socket.reconnecting": "Esat bezsaistē, tiek mēģināts pievienoties",
"socket.reconnected": "Esat atkārtoti pievienojies",
"socket.requestError": "Kļūme servera pieprasījumā",
"room.chooseRoom": "Ievadiet sapulces telpas nosaukumu (ID), kurai vēlaties pievienoties",
"room.cookieConsent": "Lai uzlabotu lietotāja pieredzi, šī vietne izmanto sīkfailus",
"room.consentUnderstand": "Es saprotu un piekrītu",
"room.joined": "Jūs esiet pievienojies sapulces telpai",
"room.cantJoin": "Nav iespējams pievienoties sapulces telpai",
"room.youLocked": "Jūs aizslēdzāt sapulces telpu",
"room.cantLock": "Nav iespējams aizslēgt sapulces telpu",
"room.youUnLocked": "Jūs atslēdzāt sapulces telpu",
"room.cantUnLock": "Nav iespējams atslēgt sapulces telpu",
"room.locked": "Sapulces telpa tagad ir AIZSLĒGTA",
"room.unlocked": "Sapulces telpa tagad ir ATSLĒGTA",
"room.newLobbyPeer": "Jauns dalībnieks ienācis uzgaidāmajā telpā",
"room.lobbyPeerLeft": "Dalībnieks uzgaidāmo telpu pameta",
"room.lobbyPeerChangedDisplayName": "Dalībnieks uzgaidāmajā telpā nomainīja vārdu uz {displayName}",
"room.lobbyPeerChangedPicture": "Dalībnieks uzgaidāmajā telpā nomainīja pašattēlu",
"room.setAccessCode": "Pieejas kods sapulces telpai aktualizēts",
"room.accessCodeOn": "Pieejas kods sapulces telpai tagad ir aktivēts",
"room.accessCodeOff": "Pieejas kods sapulces telpai tagad ir deaktivēts (atslēgts)",
"room.peerChangedDisplayName": "{oldDisplayName} pārsaucās par {displayName}",
"room.newPeer": "{displayName} pievienojās sapulces telpai",
"room.newFile": "Pieejams jauns fails",
"room.toggleAdvancedMode": "Pārslēgt uz advancēto režīmu",
"room.setDemocraticView": "Nomainīts izkārtojums uz demokrātisko skatu",
"room.setFilmStripView": "Nomainīts izkārtojums uz diapozitīvu (filmstrip) skatu",
"room.loggedIn": "Jūs esat ierakstījies (sistēmā)",
"room.loggedOut": "Jūs esat izrakstījies (no sistēmas)",
"room.changedDisplayName": "Jūsu vārds mainīts uz {displayName}",
"room.changeDisplayNameError": "Gadījās ķibele ar Jūsu vārda nomaiņu",
"room.chatError": "Nav iespējams nosūtīt tērziņa ziņu",
"room.aboutToJoin": "Jūs grasāties pievienoties sapulcei",
"room.roomId": "Sapulces telpas nosaukums (ID): {roomName}",
"room.setYourName": "Norādiet savu dalības vārdu un izvēlieties kā vēlaties pievienoties sapulcei:",
"room.audioOnly": "Vienīgi audio",
"room.audioVideo": "Audio & video",
"room.youAreReady": "Ok, Jūs esiet gatavi!",
"room.emptyRequireLogin": "Sapulces telpa ir tukša! Jūs varat Ierakstīties sistēmā, lai uzsāktu vadīt sapulci vai pagaidīt kamēr pievienojas sapulces rīkotājs/vadītājs",
"room.locketWait": "Sapulce telpa ir slēgta. Jūs atrodaties tās uzgaidāmajā telpā. Uzkavējieties, kamēr kāds Jūs sapulcē ielaiž ...",
"room.lobbyAdministration": "Uzgaidāmās telpas administrēšana",
"room.peersInLobby": "Dalībnieki uzgaidāmajā telpā",
"room.lobbyEmpty": "Pašreiz uzgaidāmajā telpā neviena nav",
"room.hiddenPeers": "{hiddenPeersCount, plural, one {participant} other {participants}}",
"room.me": "Es",
"room.spotlights": "Aktīvie (referējošie) dalībnieki",
"room.passive": "Pasīvie dalībnieki",
"room.videoPaused": "Šis video ir pauzēts",
"room.muteAll": "Noklusināt visus dalībnieku mikrofonus",
"room.stopAllVideo": "Izslēgt visu dalībnieku kameras",
"room.closeMeeting": "Beigt sapulci",
"room.clearChat": "Nodzēst visus tērziņus",
"room.clearFileSharing": "Notīrīt visus kopīgotos failus",
"room.speechUnsupported": "Jūsu pārlūks neatbalsta balss atpazīšanu",
"room.moderatoractions": "Moderatora rīcība",
"room.raisedHand": "{displayName} pacēla roku",
"room.loweredHand": "{displayName} nolaida roku",
"room.extraVideo": "Papildus video",
"me.mutedPTT": "Jūs esat noklusināts. Turiet taustiņu SPACE-BAR, lai runātu",
"roles.gotRole": "Jūs ieguvāt lomu: {role}",
"roles.lostRole": "Jūs zaudējāt lomu: {role}",
"tooltip.login": "Ierakstīties",
"tooltip.logout": "Izrakstīties",
"tooltip.admitFromLobby": "Ielaist no uzgaidāmās telpas",
"tooltip.lockRoom": "Aizslēgt sapulces telpu",
"tooltip.unLockRoom": "Atlēgt sapulces telpu",
"tooltip.enterFullscreen": "Aktivēt pilnekrāna režīmu",
"tooltip.leaveFullscreen": "Pamest pilnekrānu",
"tooltip.lobby": "Parādīt uzgaidāmo telpu",
"tooltip.settings": "Parādīt iestatījumus",
"tooltip.participants": "Parādīt dalībniekus",
"tooltip.kickParticipant": "Izvadīt (izspert) dalībnieku",
"tooltip.muteParticipant": "Noklusināt dalībnieku",
"tooltip.muteParticipantVideo": "Atslēgt dalībnieka video",
"tooltip.raisedHand": "Pacelt roku",
"label.roomName": "Sapulces telpas nosaukums (ID)",
"label.chooseRoomButton": "Turpināt",
"label.yourName": "Jūu vārds",
"label.newWindow": "Jauns logs",
"label.fullscreen": "Pilnekrāns",
"label.openDrawer": "Atvērt atvilkni",
"label.leave": "Pamest",
"label.chatInput": "Rakstiet tērziņa ziņu...",
"label.chat": "Tērzētava",
"label.filesharing": "Failu koplietošana",
"label.participants": "Dalībnieki",
"label.shareFile": "Koplietot failu",
"label.fileSharingUnsupported": "Failu koplietošana netiek atbalstīta",
"label.unknown": "Nezināms",
"label.democratic": "Demokrātisks skats",
"label.filmstrip": "Diapozitīvu (filmstrip) skats",
"label.low": "Zema",
"label.medium": "Vidēja",
"label.high": "Augsta (HD)",
"label.veryHigh": "Ļoti augsta (FHD)",
"label.ultra": "Ultra (UHD)",
"label.close": "Aizvērt",
"label.media": "Mediji",
"label.appearence": "Izskats",
"label.advanced": "Advancēts",
"label.addVideo": "Pievienot video",
"settings.settings": "Iestatījumi",
"settings.camera": "Kamera",
"settings.selectCamera": "Izvēlieties kameru (video ierīci)",
"settings.cantSelectCamera": "Nav iespējams lietot šo kameru (video ierīci)",
"settings.audio": "Skaņas ierīce",
"settings.selectAudio": "Izvēlieties skaņas ierīci",
"settings.cantSelectAudio": "Nav iespējams lietot šo skaņas (audio) ierīci",
"settings.resolution": "Iestatiet jūsu video izšķirtspēju",
"settings.layout": "Sapulces telpas izkārtojums",
"settings.selectRoomLayout": "Iestatiet sapulces telpas izkārtojumu",
"settings.advancedMode": "Advancētais režīms",
"settings.permanentTopBar": "Pastāvīga augšējā (ekrānaugšas) josla",
"settings.lastn": "Jums redzamo video/kameru skaits",
"settings.hiddenControls": "Slēpto mediju vadība",
"settings.notificationSounds": "Paziņojumu skaņas",
"filesharing.saveFileError": "Nav iespējams saglabāt failu",
"filesharing.startingFileShare": "Tiek mēģināts kopīgot failu",
"filesharing.successfulFileShare": "Fails sekmīgi kopīgots",
"filesharing.unableToShare": "Nav iespējams kopīgot failu",
"filesharing.error": "Atgadījās faila kopīgošanas kļūme",
"filesharing.finished": "Fails ir lejupielādēts",
"filesharing.save": "Saglabāt",
"filesharing.sharedFile": "{displayName} kopīgoja failu",
"filesharing.download": "Lejuplādēt",
"filesharing.missingSeeds": "Ja šis process aizņem ilgu laiku, iespējams nav neviena, kas sēklo (seed) šo torentu. Mēģiniet palūgt kādu atkārtoti augšuplādēt Jūsu gribēto failu.",
"devices.devicesChanged": "Jūsu ierīces pamainījās. Iestatījumu izvēlnē (dialogā) iestatiet jaunās ierīces.",
"device.audioUnsupported": "Skaņa (audio) netiek atbalstīta",
"device.activateAudio": "Iespējot/aktivēt mikrofonu (izejošo skaņu)",
"device.muteAudio": "Atslēgt/noklusināt mikrofonu (izejošo skaņu) ",
"device.unMuteAudio": "Ieslēgt mikrofonu (izejošo skaņu)",
"device.videoUnsupported": "Kamera (izejošais video) netiek atbalstīta",
"device.startVideo": "Ieslēgt kameru (izejošo video)",
"device.stopVideo": "Izslēgt kameru (izejošo video)",
"device.screenSharingUnsupported": "Ekrāna kopīgošana netiek atbalstīta",
"device.startScreenSharing": "Sākt ekrāna kopīgošanu",
"device.stopScreenSharing": "Beigt ekrāna kopīgošanu",
"devices.microphoneDisconnected": "Mikrofons atvienots",
"devices.microphoneError": "Atgadījās kļūme, piekļūstot jūsu mikrofonam",
"devices.microPhoneMute": "Mikrofons izslēgts/noklusināts",
"devices.micophoneUnMute": "Mikrofons ieslēgts",
"devices.microphoneEnable": "Mikrofons iespējots",
"devices.microphoneMuteError": "Nav iespējams izslēgt Jūsu mikrofonu",
"devices.microphoneUnMuteError": "Nav iespējams ieslēgt Jūsu mikrofonu",
"devices.screenSharingDisconnected" : "Ekrāna kopīgošana nenotiek (atvienota)",
"devices.screenSharingError": "Atgadījās kļūme, piekļūstot Jūsu ekrānam",
"devices.cameraDisconnected": "Kamera atvienota",
"devices.cameraError": "Atgadījās kļūme, piekļūstot Jūsu kamerai",
"moderator.clearChat": "Moderators nodzēsa tērziņus",
"moderator.clearFiles": "Moderators notīrīja failus",
"moderator.muteAudio": "Moderators noklusināja jūsu mikrofonu",
"moderator.muteVideo": "Moderators atslēdza jūsu kameru"
}

View File

@ -247,6 +247,8 @@ module.exports =
// When truthy, the room will be open to all users when as long as there
// are allready users in the room
activateOnHostJoin : true,
// Room size before spreading to new router
routerScaleSize : 20,
// Mediasoup settings
mediasoup :
{

View File

@ -39,6 +39,8 @@ class Peer extends EventEmitter
this._email = null;
this._routerId = null;
this._rtpCapabilities = null;
this._raisedHand = false;
@ -238,6 +240,16 @@ class Peer extends EventEmitter
this._email = email;
}
get routerId()
{
return this._routerId;
}
set routerId(routerId)
{
this._routerId = routerId;
}
get rtpCapabilities()
{
return this._rtpCapabilities;

View File

@ -31,6 +31,8 @@ const permissionsFromRoles =
...config.permissionsFromRoles
};
const ROUTER_SCALE_SIZE = config.routerScaleSize || 20;
class Room extends EventEmitter
{
/**
@ -38,32 +40,45 @@ class Room extends EventEmitter
*
* @async
*
* @param {mediasoup.Worker} mediasoupWorker - The mediasoup Worker in which a new
* @param {mediasoup.Worker} mediasoupWorkers - The mediasoup Worker in which a new
* mediasoup Router must be created.
* @param {String} roomId - Id of the Room instance.
*/
static async create({ mediasoupWorker, roomId })
static async create({ mediasoupWorkers, roomId })
{
logger.info('create() [roomId:"%s"]', roomId);
// Router media codecs.
const mediaCodecs = config.mediasoup.router.mediaCodecs;
// Create a mediasoup Router.
const mediasoupRouter = await mediasoupWorker.createRouter({ mediaCodecs });
const mediasoupRouters = new Map();
// Create a mediasoup AudioLevelObserver.
const audioLevelObserver = await mediasoupRouter.createAudioLevelObserver(
let firstRouter = null;
for (const worker of mediasoupWorkers)
{
const router = await worker.createRouter({ mediaCodecs });
if (!firstRouter)
firstRouter = router;
mediasoupRouters.set(router.id, router);
}
// Create a mediasoup AudioLevelObserver on first router
const audioLevelObserver = await firstRouter.createAudioLevelObserver(
{
maxEntries : 1,
threshold : -80,
interval : 800
});
return new Room({ roomId, mediasoupRouter, audioLevelObserver });
firstRouter = null;
return new Room({ roomId, mediasoupRouters, audioLevelObserver });
}
constructor({ roomId, mediasoupRouter, audioLevelObserver })
constructor({ roomId, mediasoupRouters, audioLevelObserver })
{
logger.info('constructor() [roomId:"%s"]', roomId);
@ -98,8 +113,13 @@ class Room extends EventEmitter
this._peers = {};
// mediasoup Router instance.
this._mediasoupRouter = mediasoupRouter;
// Array of mediasoup Router instances.
this._mediasoupRouters = mediasoupRouters;
// The router we are currently putting peers in
this._routerIterator = this._mediasoupRouters.values();
this._currentRouter = this._routerIterator.next().value;
// mediasoup AudioLevelObserver.
this._audioLevelObserver = audioLevelObserver;
@ -122,8 +142,14 @@ class Room extends EventEmitter
this._closed = true;
this._chatHistory = null;
this._fileHistory = null;
this._lobby.close();
this._lobby = null;
// Close the peers.
for (const peer in this._peers)
{
@ -133,8 +159,19 @@ class Room extends EventEmitter
this._peers = null;
// Close the mediasoup Router.
this._mediasoupRouter.close();
// Close the mediasoup Routers.
for (const router of this._mediasoupRouters.values())
{
router.close();
}
this._routerIterator = null;
this._currentRouter = null;
this._mediasoupRouters.clear();
this._audioLevelObserver = null;
// Emit 'close' event.
this.emit('close');
@ -401,6 +438,9 @@ class Room extends EventEmitter
this._peers[peer.id] = peer;
// Assign routerId
peer.routerId = await this._getRouterId();
this._handlePeer(peer);
if (returning)
@ -560,11 +600,14 @@ class Room extends EventEmitter
async _handleSocketRequest(peer, request, cb)
{
const router =
this._mediasoupRouters.get(peer.routerId);
switch (request.method)
{
case 'getRouterRtpCapabilities':
{
cb(null, this._mediasoupRouter.rtpCapabilities);
cb(null, router.rtpCapabilities);
break;
}
@ -673,7 +716,7 @@ class Room extends EventEmitter
webRtcTransportOptions.enableTcp = true;
}
const transport = await this._mediasoupRouter.createWebRtcTransport(
const transport = await router.createWebRtcTransport(
webRtcTransportOptions
);
@ -772,6 +815,19 @@ class Room extends EventEmitter
const producer =
await transport.produce({ kind, rtpParameters, appData });
const pipeRouters = this._getRoutersToPipeTo(peer.routerId);
for (const [ routerId, destinationRouter ] of this._mediasoupRouters)
{
if (pipeRouters.includes(routerId))
{
await router.pipeToRouter({
producerId : producer.id,
router : destinationRouter
});
}
}
// Store the Producer into the Peer data Object.
peer.addProducer(producer.id, producer);
@ -1379,6 +1435,8 @@ class Room extends EventEmitter
producer.id
);
const router = this._mediasoupRouters.get(producerPeer.routerId);
// Optimization:
// - Create the server-side Consumer. If video, do it paused.
// - Tell its Peer about it and wait for its response.
@ -1389,7 +1447,7 @@ class Room extends EventEmitter
// NOTE: Don't create the Consumer if the remote Peer cannot consume it.
if (
!consumerPeer.rtpCapabilities ||
!this._mediasoupRouter.canConsume(
!router.canConsume(
{
producerId : producer.id,
rtpCapabilities : consumerPeer.rtpCapabilities
@ -1601,6 +1659,84 @@ class Room extends EventEmitter
socket.emit('notification', { method, data });
}
}
async _pipeProducersToNewRouter()
{
const peersToPipe =
Object.values(this._peers)
.filter((peer) => peer.routerId !== this._currentRouter.id);
for (const peer of peersToPipe)
{
const srcRouter = this._mediasoupRouters.get(peer.routerId);
for (const producerId of peer.producers.keys())
{
await srcRouter.pipeToRouter({
producerId,
router : this._currentRouter
});
}
}
}
async _getRouterId()
{
if (this._currentRouter)
{
const routerLoad =
Object.values(this._peers)
.filter((peer) => peer.routerId === this._currentRouter.id).length;
if (routerLoad >= ROUTER_SCALE_SIZE)
{
this._currentRouter = this._routerIterator.next().value;
if (this._currentRouter)
{
await this._pipeProducersToNewRouter();
return this._currentRouter.id;
}
}
else
{
return this._currentRouter.id;
}
}
return this._getLeastLoadedRouter();
}
// Returns an array of router ids we need to pipe to
_getRoutersToPipeTo(originRouterId)
{
return Object.values(this._peers)
.map((peer) => peer.routerId)
.filter((routerId, index, self) =>
routerId !== originRouterId && self.indexOf(routerId) === index
);
}
_getLeastLoadedRouter()
{
let load = Infinity;
let id;
for (const routerId of this._mediasoupRouters.keys())
{
const routerLoad =
Object.values(this._peers).filter((peer) => peer.routerId === routerId).length;
if (routerLoad < load)
{
id = routerId;
load = routerLoad;
}
}
return id;
}
}
module.exports = Room;

View File

@ -644,9 +644,9 @@ async function getOrCreateRoom({ roomId })
{
logger.info('creating a new Room [roomId:"%s"]', roomId);
const mediasoupWorker = getMediasoupWorker();
// const mediasoupWorker = getMediasoupWorker();
room = await Room.create({ mediasoupWorker, roomId });
room = await Room.create({ mediasoupWorkers, roomId });
rooms.set(roomId, room);