[mirotalksfu] - add audioLevelObserver
هذا الالتزام موجود في:
@@ -9,6 +9,7 @@ module.exports = class Room {
|
||||
this.id = room_id;
|
||||
this.worker = worker;
|
||||
this.router = null;
|
||||
this.audioLevelObserver = null;
|
||||
this.io = io;
|
||||
this._isLocked = false;
|
||||
this._roomPassword = null;
|
||||
@@ -29,10 +30,49 @@ module.exports = class Room {
|
||||
.then(
|
||||
function (router) {
|
||||
this.router = router;
|
||||
this.startAudioLevelObservation(router);
|
||||
}.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() {
|
||||
return this.router.rtpCapabilities;
|
||||
}
|
||||
|
||||
@@ -479,9 +479,15 @@ io.on('connection', (socket) => {
|
||||
log.debug('Produce', {
|
||||
kind: kind,
|
||||
peer_name: peer_name,
|
||||
peer_id: socket.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
|
||||
let data = {
|
||||
peer_name: peer_name,
|
||||
|
||||
@@ -735,6 +735,31 @@ progress {
|
||||
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
|
||||
--------------------------------------------------------------*/
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
#videoMediaContainer div {
|
||||
/* Camera */
|
||||
.Camera {
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
align-self: center;
|
||||
|
||||
@@ -133,6 +133,9 @@ class RoomClient {
|
||||
this.myVideoEl = null;
|
||||
this.debug = false;
|
||||
|
||||
this.videoProducerId = null;
|
||||
this.audioProducerId = null;
|
||||
|
||||
this.consumers = new Map();
|
||||
this.producers = new Map();
|
||||
this.producerLabel = new Map();
|
||||
@@ -513,6 +516,13 @@ class RoomClient {
|
||||
}.bind(this),
|
||||
);
|
||||
|
||||
this.socket.on(
|
||||
'audioVolume',
|
||||
function (data) {
|
||||
this.handleAudioVolume(data);
|
||||
}.bind(this),
|
||||
);
|
||||
|
||||
this.socket.on(
|
||||
'disconnect',
|
||||
function () {
|
||||
@@ -599,7 +609,7 @@ class RoomClient {
|
||||
}
|
||||
producer = await this.producerTransport.produce(params);
|
||||
|
||||
console.log('Producer id', producer.id);
|
||||
console.log('PRODUCER', producer);
|
||||
|
||||
this.producers.set(producer.id, producer);
|
||||
|
||||
@@ -607,8 +617,10 @@ class RoomClient {
|
||||
if (!audio) {
|
||||
this.localVideoStream = stream;
|
||||
elem = await this.handleProducer(producer.id, type, stream);
|
||||
this.videoProducerId = producer.id;
|
||||
} else {
|
||||
this.localAudioStream = stream;
|
||||
this.audioProducerId = producer.id;
|
||||
}
|
||||
|
||||
producer.on('trackended', () => {
|
||||
@@ -749,7 +761,7 @@ class RoomClient {
|
||||
}
|
||||
|
||||
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);
|
||||
d = document.createElement('div');
|
||||
d.className = 'Camera';
|
||||
@@ -773,11 +785,20 @@ class RoomClient {
|
||||
fs = document.createElement('button');
|
||||
fs.id = id + '__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(i);
|
||||
d.appendChild(p);
|
||||
d.appendChild(b);
|
||||
d.appendChild(fs);
|
||||
d.appendChild(pm);
|
||||
this.videoMediaContainer.appendChild(d);
|
||||
this.attachMediaStream(elem, stream, type, 'Producer');
|
||||
this.myVideoEl = elem;
|
||||
@@ -950,7 +971,7 @@ class RoomClient {
|
||||
}
|
||||
|
||||
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) {
|
||||
case mediaType.video:
|
||||
this.removeVideoOff(peer_info.peer_id);
|
||||
@@ -976,11 +997,20 @@ class RoomClient {
|
||||
fs = document.createElement('button');
|
||||
fs.id = id + '__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(p);
|
||||
d.appendChild(i);
|
||||
d.appendChild(b);
|
||||
d.appendChild(fs);
|
||||
d.appendChild(pm);
|
||||
this.videoMediaContainer.appendChild(d);
|
||||
this.attachMediaStream(elem, stream, type, 'Consumer');
|
||||
this.handleFS(elem.id, fs.id);
|
||||
@@ -1025,7 +1055,7 @@ class RoomClient {
|
||||
// ####################################################
|
||||
|
||||
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_name = peer_info.peer_name;
|
||||
let peer_audio = peer_info.peer_audio;
|
||||
@@ -1046,10 +1076,19 @@ class RoomClient {
|
||||
h = document.createElement('i');
|
||||
h.id = peer_info.peer_id + '__hand';
|
||||
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(p);
|
||||
d.appendChild(b);
|
||||
d.appendChild(h);
|
||||
d.appendChild(pm);
|
||||
this.videoMediaContainer.appendChild(d);
|
||||
this.setVideoAvatarImgName(i.id, peer_name);
|
||||
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
|
||||
// ####################################################
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم