[mirotalksfu] - add audioLevelObserver

main
Miroslav Pejic 4 years ago
parent 05b37c5403
commit c153c59a47

@ -9,6 +9,7 @@ module.exports = class Room {
this.id = room_id; this.id = room_id;
this.worker = worker; this.worker = worker;
this.router = null; this.router = null;
this.audioLevelObserver = null;
this.io = io; this.io = io;
this._isLocked = false; this._isLocked = false;
this._roomPassword = null; this._roomPassword = null;
@ -29,10 +30,49 @@ module.exports = class Room {
.then( .then(
function (router) { function (router) {
this.router = router; this.router = router;
this.startAudioLevelObservation(router);
}.bind(this), }.bind(this),
); );
} }
// ####################################################
// PRODUCER AUDIO LEVEL OBSERVER
// ####################################################
async startAudioLevelObservation(router) {
log.debug('Start audioLevelObserver for signaling active speaker...');
this.audioLevelObserver = await router.createAudioLevelObserver({
maxEntries: 1,
threshold: -80,
interval: 800,
});
this.audioLevelObserver.on('volumes', (volumes) => {
const volume = volumes[0].volume;
let audioVolume = Math.round(Math.pow(10, volume / 85) * 10); // 1-10
if (audioVolume > 2) {
//console.log('PEERS', this.peers);
this.peers.forEach((peer) => {
peer.producers.forEach((producer) => {
if (producer.kind == 'audio') {
let data = { peer_id: peer.id, audioVolume: audioVolume };
//log.debug('audioLevelObserver', data);
this.io.emit('audioVolume', data);
}
});
});
}
});
this.audioLevelObserver.on('silence', () => {
log.debug('audioLevelObserver', { volume: 'silence' });
});
}
addProducerToAudioLevelObserver(producer) {
this.audioLevelObserver.addProducer(producer);
}
getRtpCapabilities() { getRtpCapabilities() {
return this.router.rtpCapabilities; return this.router.rtpCapabilities;
} }

@ -479,9 +479,15 @@ io.on('connection', (socket) => {
log.debug('Produce', { log.debug('Produce', {
kind: kind, kind: kind,
peer_name: peer_name, peer_name: peer_name,
peer_id: socket.id,
producer_id: producer_id, producer_id: producer_id,
}); });
// add & monitor producer audio level
if (kind === 'audio') {
roomList.get(socket.room_id).addProducerToAudioLevelObserver({ producerId: producer_id });
}
// peer_info audio Or video ON // peer_info audio Or video ON
let data = { let data = {
peer_name: peer_name, peer_name: peer_name,

@ -735,6 +735,31 @@ progress {
padding: 0; padding: 0;
} }
/*--------------------------------------------------------------
# Speech bar
--------------------------------------------------------------*/
.speechbar {
position: absolute;
top: 0;
bottom: 0;
right: 2px;
width: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
pointer-events: none;
}
.bar {
width: 6px;
border-radius: 6px;
background: rgba(#19bb5c, 0.65);
transition-property: height background-color;
transition-duration: 0.25s;
}
/*-------------------------------------------------------------- /*--------------------------------------------------------------
# Pulse class effect # Pulse class effect
--------------------------------------------------------------*/ --------------------------------------------------------------*/

@ -17,8 +17,7 @@
right: 0px; right: 0px;
} }
#videoMediaContainer div { .Camera {
/* Camera */
position: relative; position: relative;
vertical-align: middle; vertical-align: middle;
align-self: center; align-self: center;

@ -133,6 +133,9 @@ class RoomClient {
this.myVideoEl = null; this.myVideoEl = null;
this.debug = false; this.debug = false;
this.videoProducerId = null;
this.audioProducerId = null;
this.consumers = new Map(); this.consumers = new Map();
this.producers = new Map(); this.producers = new Map();
this.producerLabel = new Map(); this.producerLabel = new Map();
@ -513,6 +516,13 @@ class RoomClient {
}.bind(this), }.bind(this),
); );
this.socket.on(
'audioVolume',
function (data) {
this.handleAudioVolume(data);
}.bind(this),
);
this.socket.on( this.socket.on(
'disconnect', 'disconnect',
function () { function () {
@ -599,7 +609,7 @@ class RoomClient {
} }
producer = await this.producerTransport.produce(params); producer = await this.producerTransport.produce(params);
console.log('Producer id', producer.id); console.log('PRODUCER', producer);
this.producers.set(producer.id, producer); this.producers.set(producer.id, producer);
@ -607,8 +617,10 @@ class RoomClient {
if (!audio) { if (!audio) {
this.localVideoStream = stream; this.localVideoStream = stream;
elem = await this.handleProducer(producer.id, type, stream); elem = await this.handleProducer(producer.id, type, stream);
this.videoProducerId = producer.id;
} else { } else {
this.localAudioStream = stream; this.localAudioStream = stream;
this.audioProducerId = producer.id;
} }
producer.on('trackended', () => { producer.on('trackended', () => {
@ -749,7 +761,7 @@ class RoomClient {
} }
async handleProducer(id, type, stream) { async handleProducer(id, type, stream) {
let elem, d, p, i, b, fs; let elem, d, p, i, b, fs, pm, pb;
this.removeVideoOff(this.peer_id); this.removeVideoOff(this.peer_id);
d = document.createElement('div'); d = document.createElement('div');
d.className = 'Camera'; d.className = 'Camera';
@ -773,11 +785,20 @@ class RoomClient {
fs = document.createElement('button'); fs = document.createElement('button');
fs.id = id + '__fullScreen'; fs.id = id + '__fullScreen';
fs.className = html.fullScreen; fs.className = html.fullScreen;
pm = document.createElement('div');
pb = document.createElement('div');
pm.setAttribute('id', this.peer_id + '_pitchMeter');
pb.setAttribute('id', this.peer_id + '_pitchBar');
pm.className = 'speechbar';
pb.className = 'bar';
pb.style.height = '1%';
pm.appendChild(pb);
d.appendChild(elem); d.appendChild(elem);
d.appendChild(i); d.appendChild(i);
d.appendChild(p); d.appendChild(p);
d.appendChild(b); d.appendChild(b);
d.appendChild(fs); d.appendChild(fs);
d.appendChild(pm);
this.videoMediaContainer.appendChild(d); this.videoMediaContainer.appendChild(d);
this.attachMediaStream(elem, stream, type, 'Producer'); this.attachMediaStream(elem, stream, type, 'Producer');
this.myVideoEl = elem; this.myVideoEl = elem;
@ -950,7 +971,7 @@ class RoomClient {
} }
handleConsumer(id, type, stream, peer_name, peer_info) { handleConsumer(id, type, stream, peer_name, peer_info) {
let elem, d, p, i, b, fs; let elem, d, p, i, b, fs, pb, pm;
switch (type) { switch (type) {
case mediaType.video: case mediaType.video:
this.removeVideoOff(peer_info.peer_id); this.removeVideoOff(peer_info.peer_id);
@ -976,11 +997,20 @@ class RoomClient {
fs = document.createElement('button'); fs = document.createElement('button');
fs.id = id + '__fullScreen'; fs.id = id + '__fullScreen';
fs.className = html.fullScreen; fs.className = html.fullScreen;
pm = document.createElement('div');
pb = document.createElement('div');
pm.setAttribute('id', peer_info.peer_id + '__pitchMeter');
pb.setAttribute('id', peer_info.peer_id + '__pitchBar');
pm.className = 'speechbar';
pb.className = 'bar';
pb.style.height = '1%';
pm.appendChild(pb);
d.appendChild(elem); d.appendChild(elem);
d.appendChild(p); d.appendChild(p);
d.appendChild(i); d.appendChild(i);
d.appendChild(b); d.appendChild(b);
d.appendChild(fs); d.appendChild(fs);
d.appendChild(pm);
this.videoMediaContainer.appendChild(d); this.videoMediaContainer.appendChild(d);
this.attachMediaStream(elem, stream, type, 'Consumer'); this.attachMediaStream(elem, stream, type, 'Consumer');
this.handleFS(elem.id, fs.id); this.handleFS(elem.id, fs.id);
@ -1025,7 +1055,7 @@ class RoomClient {
// #################################################### // ####################################################
async setVideoOff(peer_info, remotePeer = false) { async setVideoOff(peer_info, remotePeer = false) {
let d, i, h, b, p; let d, i, h, b, p, pm, pb;
let peer_id = peer_info.peer_id; let peer_id = peer_info.peer_id;
let peer_name = peer_info.peer_name; let peer_name = peer_info.peer_name;
let peer_audio = peer_info.peer_audio; let peer_audio = peer_info.peer_audio;
@ -1046,10 +1076,19 @@ class RoomClient {
h = document.createElement('i'); h = document.createElement('i');
h.id = peer_info.peer_id + '__hand'; h.id = peer_info.peer_id + '__hand';
h.className = html.userHand; h.className = html.userHand;
pm = document.createElement('div');
pb = document.createElement('div');
pm.setAttribute('id', peer_id + '__pitchMeter');
pb.setAttribute('id', peer_id + '__pitchBar');
pm.className = 'speechbar';
pb.className = 'bar';
pb.style.height = '1%';
pm.appendChild(pb);
d.appendChild(i); d.appendChild(i);
d.appendChild(p); d.appendChild(p);
d.appendChild(b); d.appendChild(b);
d.appendChild(h); d.appendChild(h);
d.appendChild(pm);
this.videoMediaContainer.appendChild(d); this.videoMediaContainer.appendChild(d);
this.setVideoAvatarImgName(i.id, peer_name); this.setVideoAvatarImgName(i.id, peer_name);
this.getId(i.id).style.display = 'block'; this.getId(i.id).style.display = 'block';
@ -2272,6 +2311,31 @@ class RoomClient {
}); });
} }
// ####################################################
// HANDLE AUDIO VOLUME
// ####################################################
handleAudioVolume(data) {
let peerId = data.peer_id;
let pbProducer = this.getId(peerId + '_pitchBar');
let pbConsumer = this.getId(peerId + '__pitchBar');
let audioVolume = data.audioVolume * 10; //10-100
// console.log('Active speaker', { peer_id: peerId, audioVolume: audioVolume });
if (audioVolume > 40) {
if (pbProducer) pbProducer.style.backgroundColor = 'orange';
if (pbConsumer) pbConsumer.style.backgroundColor = 'orange';
} else {
if (pbProducer) pbProducer.style.backgroundColor = '#19bb5c';
if (pbConsumer) pbConsumer.style.backgroundColor = '#19bb5c';
}
if (pbProducer) pbProducer.style.height = audioVolume + '%';
if (pbConsumer) pbConsumer.style.height = audioVolume + '%';
setTimeout(function () {
if (pbProducer) pbProducer.style.height = '0%';
if (pbConsumer) pbConsumer.style.height = '0%';
}, 2000);
}
// #################################################### // ####################################################
// PEER ACTION // PEER ACTION
// #################################################### // ####################################################

Loading…
Cancel
Save