Changeset View
Changeset View
Standalone View
Standalone View
src/resources/js/meet/client.js
Show All 40 Lines | function Client() | ||||
navigator.mediaDevices.addEventListener('devicechange', () => { | navigator.mediaDevices.addEventListener('devicechange', () => { | ||||
trigger('deviceChange') | trigger('deviceChange') | ||||
}) | }) | ||||
/** | /** | ||||
* Sample statistics | * Sample statistics | ||||
*/ | */ | ||||
this.getStats = async () => { | this.getStats = async () => { | ||||
let consumerStats = {}; | let consumerStats = {} | ||||
for (const consumer of Object.values(consumers)) { | for (const consumer of Object.values(consumers)) { | ||||
const stats = await consumer.getStats() | const stats = await consumer.getStats() | ||||
const peerId = consumer.peerId | const peerId = consumer.peerId | ||||
const peer = peers.self && peers.self.id === peerId ? peers.self : peers[peerId] | const peer = peers.self && peers.self.id === peerId ? peers.self : peers[peerId] | ||||
const name = peer ? peer['nickname'] : "" | const name = peer ? peer.nickname : '' | ||||
const entryName = name + ":" + consumer.id | const entryName = name + ':' + consumer.id | ||||
stats.forEach((stat) => { | stats.forEach((stat) => { | ||||
if (stat["type"] == "inbound-rtp") { | if (stat.type == 'inbound-rtp') { | ||||
if (stat["kind"] == "video") { | if (stat.kind == 'video') { | ||||
//There should only be one matching entry | // There should only be one matching entry | ||||
console.assert(!(entryName in consumerStats)) | console.assert(!(entryName in consumerStats)) | ||||
consumerStats[entryName] = stat | consumerStats[entryName] = stat | ||||
consumerStats[entryName]['activeLayers'] = consumerActiveLayers[consumer.id] | consumerStats[entryName].activeLayers = consumerActiveLayers[consumer.id] | ||||
consumerStats[entryName]['score'] = consumerScore[consumer.id] | consumerStats[entryName].score = consumerScore[consumer.id] | ||||
} | } | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
let sendTransportStats = {}; | let sendTransportStats = {} | ||||
if (sendTransport) { | if (sendTransport) { | ||||
(await sendTransport.getStats()).forEach((stat) => { | (await sendTransport.getStats()).forEach((stat) => { | ||||
if (stat["type"] == "outbound-rtp") { | if (stat.type == 'outbound-rtp') { | ||||
const entryName = stat["kind"] + ":" + stat["id"] | const entryName = stat.kind + ':' + stat.id | ||||
sendTransportStats[entryName] = stat | sendTransportStats[entryName] = stat | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
let receiveTransportStats = {}; | let receiveTransportStats = {} | ||||
if (recvTransport) { | if (recvTransport) { | ||||
(await recvTransport.getStats()).forEach((stat) => { | (await recvTransport.getStats()).forEach((stat) => { | ||||
if (stat["type"] == "inbound-rtp") { | if (stat.type == 'inbound-rtp') { | ||||
//NOTE: The inbound-rtp stats with ssrc 1234 are RtpProbator, which is used for REMB (you'll see a lot of PLI's for it) | // NOTE: The inbound-rtp stats with ssrc 1234 are RtpProbator, | ||||
const entryName = stat["kind"] + ":" + stat["id"] | // which is used for REMB (you'll see a lot of PLI's for it) | ||||
const entryName = stat.kind + ':' + stat.id | |||||
receiveTransportStats[entryName] = stat | receiveTransportStats[entryName] = stat | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
let camProducerStats = {}; | let camProducerStats = {} | ||||
if (camProducer) { | if (camProducer) { | ||||
(await camProducer.getStats()).forEach((stat) => { | (await camProducer.getStats()).forEach((stat) => { | ||||
if (stat["type"] == "outbound-rtp") { | if (stat.type == 'outbound-rtp') { | ||||
camProducerStats[stat["id"]] = stat | camProducerStats[stat.id] = stat | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
let micProducerStats = {}; | let micProducerStats = {} | ||||
if (micProducer) { | if (micProducer) { | ||||
(await micProducer.getStats()).forEach((stat) => { | (await micProducer.getStats()).forEach((stat) => { | ||||
if (stat["type"] == "outbound-rtp") { | if (stat.type == 'outbound-rtp') { | ||||
micProducerStats[stat["id"]] = stat | micProducerStats[stat.id] = stat | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
let screenProducerStats = {}; | let screenProducerStats = {} | ||||
if (screenProducer) { | if (screenProducer) { | ||||
(await screenProducer.getStats()).forEach((stat) => { | (await screenProducer.getStats()).forEach((stat) => { | ||||
if (stat["type"] == "outbound-rtp") { | if (stat.type == 'outbound-rtp') { | ||||
screenProducerStats[stat["id"]] = stat | screenProducerStats[stat.id] = stat | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
return { | return { | ||||
'roomId': roomId, | roomId, | ||||
'sendTransportState': sendTransport ? sendTransport.connectionState : "undefined", | sendTransportStats, | ||||
'sendTransportStats': sendTransportStats, | receiveTransportStats, | ||||
'receiveTransportState': recvTransport ? recvTransport.connectionState : "undefined", | camProducerStats, | ||||
'receiveTransportStats': receiveTransportStats, | micProducerStats, | ||||
'camProducerStats': camProducerStats, | screenProducerStats, | ||||
'micProducerStats': micProducerStats, | consumerStats, | ||||
'screenProducerStats': screenProducerStats, | 'receiveTransportState': recvTransport ? recvTransport.connectionState : 'undefined', | ||||
'consumerStats': consumerStats, | 'sendTransportState': sendTransport ? sendTransport.connectionState : 'undefined' | ||||
}; | } | ||||
} | } | ||||
/** | /** | ||||
* Start a session (join a room) | * Start a session (join a room) | ||||
*/ | */ | ||||
this.joinSession = (token, props) => { | this.joinSession = (token, props) => { | ||||
// Store the join properties for later | // Store the join properties for later | ||||
joinProps = props | joinProps = props | ||||
Show All 26 Lines | this.closeSession = async (reason) => { | ||||
if (recvTransport) { | if (recvTransport) { | ||||
recvTransport.close() | recvTransport.close() | ||||
recvTransport = null | recvTransport = null | ||||
} | } | ||||
// Remove peers' video elements | // Remove peers' video elements | ||||
Object.values(peers).forEach(peer => { | Object.values(peers).forEach(peer => { | ||||
if (peer.videoElement) { | media.resetVideoElement(peer.videoElement, true) | ||||
$(peer.videoElement).remove() | media.resetVideoElement(peer.screenVideoElement, true) | ||||
} | |||||
if (peer.screenVideoElement) { | |||||
$(peer.screenVideoElement).remove() | |||||
} | |||||
}) | }) | ||||
// Reset state | // Reset state | ||||
eventHandlers = {} | eventHandlers = {} | ||||
camProducer = null | camProducer = null | ||||
micProducer = null | micProducer = null | ||||
screenProducer = null | screenProducer = null | ||||
consumers = {} | consumers = {} | ||||
▲ Show 20 Lines • Show All 276 Lines • ▼ Show 20 Lines | const initSocket = (token) => { | ||||
break | break | ||||
default: | default: | ||||
console.error('Unknow request method: ' + request.method) | console.error('Unknow request method: ' + request.method) | ||||
} | } | ||||
}) | }) | ||||
socket.on('notification', (notification) => { | socket.on('notification', (notification) => { | ||||
console.warn("notification", notification) | |||||
switch (notification.method) { | switch (notification.method) { | ||||
case 'roomReady': | case 'roomReady': | ||||
iceServers = notification.data.iceServers | iceServers = notification.data.iceServers | ||||
roomId = notification.data.roomId | roomId = notification.data.roomId | ||||
joinRoom() | joinRoom() | ||||
return | return | ||||
case 'roomBack': | case 'roomBack': | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | const initSocket = (token) => { | ||||
trigger('updatePeer', updatePeerState(peer)) | trigger('updatePeer', updatePeerState(peer)) | ||||
} | } | ||||
return | return | ||||
} | } | ||||
case 'consumerScoreChanged': { | case 'consumerScoreChanged': { | ||||
const { consumerId, score } = notification.data | const { consumerId, score } = notification.data | ||||
consumerScore[consumerId] = score; | consumerScore[consumerId] = score | ||||
return | return | ||||
} | } | ||||
case 'consumerLayersChanged': { | case 'consumerLayersChanged': { | ||||
const { consumerId, layers } = notification.data | const { consumerId, layers } = notification.data | ||||
consumerActiveLayers[consumerId] = layers; | consumerActiveLayers[consumerId] = layers | ||||
return | return | ||||
} | } | ||||
case 'changeLanguage': | case 'changeLanguage': | ||||
updatePeerProperty(notification.data, 'language') | updatePeerProperty(notification.data, 'language') | ||||
return | return | ||||
case 'changeNickname': | case 'changeNickname': | ||||
▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | const joinRoom = async () => { | ||||
let tracks = [] | let tracks = [] | ||||
let screenTracks = [] | let screenTracks = [] | ||||
// We receive newConsumer requests before we add the peer to peers list, | // We receive newConsumer requests before we add the peer to peers list, | ||||
// therefore we look here for any consumers that belong to this peer and update | // therefore we look here for any consumers that belong to this peer and update | ||||
// the peer. If we do not do this we have to wait about 20 seconds for repeated | // the peer. If we do not do this we have to wait about 20 seconds for repeated | ||||
// newConsumer requests | // newConsumer requests | ||||
Object.keys(consumers).forEach(cid => { | Object.keys(consumers).forEach(cid => { | ||||
const consumer = consumers[cid]; | const consumer = consumers[cid] | ||||
if (consumer.peerId === peer.id) { | if (consumer.peerId === peer.id) { | ||||
(consumer.source == 'screen' ? screenTracks : tracks).push(consumer.track) | (consumer.source == 'screen' ? screenTracks : tracks).push(consumer.track) | ||||
} | } | ||||
}) | }) | ||||
if (tracks.length) { | if (tracks.length) { | ||||
setPeerTracks(peer, tracks) | setPeerTracks(peer, tracks) | ||||
} | } | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | this.setCamera = async (deviceId, noUpdate) => { | ||||
keyFrameRequestDelay: 3000, | keyFrameRequestDelay: 3000, | ||||
appData: { | appData: { | ||||
source : 'webcam' | source : 'webcam' | ||||
} | } | ||||
}) | }) | ||||
// Workaround the firefox screenshare issue. | // Workaround the firefox screenshare issue. | ||||
// With this we effectively limit ourselves to 640 width | // With this we effectively limit ourselves to 640 width | ||||
await camProducer.setMaxSpatialLayer(1); | await camProducer.setMaxSpatialLayer(1) | ||||
camProducer.on('transportclose', () => { | camProducer.on('transportclose', () => { | ||||
camProducer = null | camProducer = null | ||||
}) | }) | ||||
camProducer.on('trackended', () => { | camProducer.on('trackended', () => { | ||||
this.setCamera('', true) | this.setCamera('', true) | ||||
}) | }) | ||||
▲ Show 20 Lines • Show All 529 Lines • Show Last 20 Lines |