[mirotalksfu] - improve nodemailer, update dep, speaker focus WIP
هذا الالتزام موجود في:
@@ -205,6 +205,8 @@ module.exports = class Peer {
|
||||
kind: producer_kind,
|
||||
rtpParameters: producer_rtpParameters,
|
||||
});
|
||||
|
||||
this.addProducer(producer.id, producer);
|
||||
} catch (error) {
|
||||
log.error(`Error creating producer for transport ID ${producerTransportId}`, {
|
||||
error: error.message,
|
||||
@@ -222,8 +224,6 @@ module.exports = class Peer {
|
||||
|
||||
appData.mediaType = producer_type;
|
||||
|
||||
this.addProducer(id, producer);
|
||||
|
||||
if (['simulcast', 'svc'].includes(type)) {
|
||||
const { scalabilityMode } = rtpParameters.encodings[0];
|
||||
const spatialLayer = parseInt(scalabilityMode.substring(1, 2)); // 1/2/3
|
||||
@@ -316,6 +316,8 @@ module.exports = class Peer {
|
||||
paused: true, // Start the consumer in a paused state
|
||||
ignoreDtx: true, // Ignore DTX (Discontinuous Transmission)
|
||||
});
|
||||
|
||||
this.addConsumer(consumer.id, consumer);
|
||||
} catch (error) {
|
||||
log.error(`Error creating consumer for transport ID ${consumer_transport_id}`, {
|
||||
error: error.message,
|
||||
@@ -330,8 +332,6 @@ module.exports = class Peer {
|
||||
|
||||
const { id, type, kind, rtpParameters, producerPaused } = consumer;
|
||||
|
||||
this.addConsumer(id, consumer);
|
||||
|
||||
if (['simulcast', 'svc'].includes(type)) {
|
||||
// simulcast - L1T3/L2T3/L3T3 | svc - L3T3
|
||||
const { scalabilityMode } = rtpParameters.encodings[0];
|
||||
|
||||
@@ -102,6 +102,7 @@ module.exports = class Room {
|
||||
videoAIEnabled: this.videoAIEnabled,
|
||||
thereIsPolls: this.thereIsPolls(),
|
||||
shareMediaData: this.shareMediaData,
|
||||
dominantSpeaker: this.activeSpeakerObserverEnabled,
|
||||
peers: JSON.stringify([...this.peers]),
|
||||
};
|
||||
}
|
||||
@@ -311,10 +312,16 @@ module.exports = class Room {
|
||||
.then((router) => {
|
||||
this.router = router;
|
||||
if (this.audioLevelObserverEnabled) {
|
||||
this.startAudioLevelObservation();
|
||||
log.info('Audio Level Observer enabled, starting observation...');
|
||||
this.startAudioLevelObservation().catch((err) => {
|
||||
log.error('Failed to start audio level observation', err);
|
||||
});
|
||||
}
|
||||
if (this.activeSpeakerObserverEnabled) {
|
||||
this.startActiveSpeakerObserver();
|
||||
log.info('Active Speaker Observer enabled, starting observation...');
|
||||
this.startActiveSpeakerObserver().catch((err) => {
|
||||
log.error('Failed to start active speaker observer', err);
|
||||
});
|
||||
}
|
||||
this.router.observer.on('close', () => {
|
||||
log.info('---------------> Router is now closed as the last peer has left the room', {
|
||||
@@ -385,9 +392,9 @@ module.exports = class Room {
|
||||
peer_name: peer_name,
|
||||
audioVolume: audioVolume,
|
||||
};
|
||||
// Uncomment the following line for debugging
|
||||
// log.debug('Sending audio volume', data);
|
||||
this.sendToAll('audioVolume', data);
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -401,6 +408,7 @@ module.exports = class Room {
|
||||
addProducerToAudioLevelObserver(producer) {
|
||||
if (this.audioLevelObserverEnabled) {
|
||||
this.audioLevelObserver.addProducer(producer);
|
||||
log.info('Producer added to audio level observer', { producer });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,25 +425,40 @@ module.exports = class Room {
|
||||
// ####################################################
|
||||
|
||||
async startActiveSpeakerObserver() {
|
||||
log.debug('Start activeSpeakerObserver for signaling dominant speaker...');
|
||||
this.activeSpeakerObserver = await this.router.createActiveSpeakerObserver();
|
||||
this.activeSpeakerObserver.on('dominantspeaker', (dominantSpeaker) => {
|
||||
if (!dominantSpeaker.producer) {
|
||||
return;
|
||||
}
|
||||
log.debug('activeSpeakerObserver "dominantspeaker" event', dominantSpeaker.producer.id);
|
||||
this.peers.forEach((peer) => {
|
||||
const { id, peer_audio, peer_name } = peer;
|
||||
peer.producers.forEach((peerProducer) => {
|
||||
if (
|
||||
peerProducer.id === dominantSpeaker.producer.id &&
|
||||
peerProducer.kind === 'audio' &&
|
||||
peer_audio
|
||||
) {
|
||||
const data = {
|
||||
peer_id: id,
|
||||
peer_name: peer_name,
|
||||
};
|
||||
// log.debug('Sending dominant speaker', data);
|
||||
this.sendToAll('dominantSpeaker', data);
|
||||
if (peer.producers instanceof Map) {
|
||||
for (const peerProducer of peer.producers.values()) {
|
||||
if (
|
||||
peerProducer.id === dominantSpeaker.producer.id &&
|
||||
peerProducer.kind === 'audio' &&
|
||||
peer_audio
|
||||
) {
|
||||
let videoProducerId = null;
|
||||
for (const p of peer.producers.values()) {
|
||||
if (p.kind === 'video') {
|
||||
videoProducerId = p.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const data = {
|
||||
producer_id: videoProducerId,
|
||||
peer_id: id,
|
||||
peer_name: peer_name,
|
||||
};
|
||||
log.debug('Sending dominant speaker', data);
|
||||
this.sendToAll('dominantSpeaker', data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -443,6 +466,7 @@ module.exports = class Room {
|
||||
addProducerToActiveSpeakerObserver(producer) {
|
||||
if (this.activeSpeakerObserverEnabled) {
|
||||
this.activeSpeakerObserver.addProducer(producer);
|
||||
log.info('Producer added to active speaker observer', { producer });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ dev dependencies: {
|
||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||
* @version 1.8.61
|
||||
* @version 1.8.62
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1976,7 +1976,7 @@ function startServer() {
|
||||
peerInfo: peerInfo,
|
||||
});
|
||||
|
||||
// add & monitor producer audio level and active speaker
|
||||
// add & monitor producer audio level and dominant speaker
|
||||
if (kind === 'audio') {
|
||||
room.addProducerToAudioLevelObserver({ producerId: producer_id });
|
||||
room.addProducerToActiveSpeakerObserver({ producerId: producer_id });
|
||||
|
||||
@@ -647,6 +647,7 @@ module.exports = {
|
||||
* - port : SMTP port (default: 587 for TLS)
|
||||
* - username : SMTP auth username
|
||||
* - password : SMTP auth password (store ONLY in .env)
|
||||
* - from : Sender email address (default: same as username)
|
||||
* - sendTo : Recipient email for alerts
|
||||
*
|
||||
* Common Providers:
|
||||
@@ -669,6 +670,7 @@ module.exports = {
|
||||
port: parseInt(process.env.EMAIL_PORT) || 587,
|
||||
username: process.env.EMAIL_USERNAME || 'your_username',
|
||||
password: process.env.EMAIL_PASSWORD || 'your_password',
|
||||
from: process.env.EMAIL_FROM || process.env.EMAIL_USERNAME,
|
||||
sendTo: process.env.EMAIL_SEND_TO || 'sfu.mirotalk@gmail.com',
|
||||
},
|
||||
|
||||
@@ -1341,10 +1343,10 @@ module.exports = {
|
||||
*/
|
||||
router: {
|
||||
// Enable audio level monitoring (for detecting who is speaking)
|
||||
audioLevelObserverEnabled: true,
|
||||
audioLevelObserverEnabled: process.env.MEDIASOUP_ROUTER_AUDIO_LEVEL_OBSERVER_ENABLED !== 'false',
|
||||
|
||||
// Disable active speaker detection (uses more CPU)
|
||||
activeSpeakerObserverEnabled: false,
|
||||
activeSpeakerObserverEnabled: process.env.MEDIASOUP_ROUTER_ACTIVE_SPEAKER_OBSERVER_ENABLED === 'true',
|
||||
|
||||
/**
|
||||
* Supported Media Codecs
|
||||
|
||||
@@ -15,6 +15,7 @@ const EMAIL_HOST = emailConfig.host || false;
|
||||
const EMAIL_PORT = emailConfig.port || false;
|
||||
const EMAIL_USERNAME = emailConfig.username || false;
|
||||
const EMAIL_PASSWORD = emailConfig.password || false;
|
||||
const EMAIL_FROM = emailConfig.from || emailConfig.username;
|
||||
const EMAIL_SEND_TO = emailConfig.sendTo || false;
|
||||
|
||||
if (EMAIL_ALERT && EMAIL_HOST && EMAIL_PORT && EMAIL_USERNAME && EMAIL_PASSWORD && EMAIL_SEND_TO) {
|
||||
@@ -24,12 +25,16 @@ if (EMAIL_ALERT && EMAIL_HOST && EMAIL_PORT && EMAIL_USERNAME && EMAIL_PASSWORD
|
||||
port: EMAIL_PORT,
|
||||
username: EMAIL_USERNAME,
|
||||
password: EMAIL_PASSWORD,
|
||||
from: EMAIL_FROM,
|
||||
to: EMAIL_SEND_TO,
|
||||
});
|
||||
}
|
||||
|
||||
const IS_TLS_PORT = EMAIL_PORT === 465;
|
||||
const transport = nodemailer.createTransport({
|
||||
host: EMAIL_HOST,
|
||||
port: EMAIL_PORT,
|
||||
secure: IS_TLS_PORT,
|
||||
auth: {
|
||||
user: EMAIL_USERNAME,
|
||||
pass: EMAIL_PASSWORD,
|
||||
@@ -67,7 +72,7 @@ function sendEmailAlert(event, data) {
|
||||
function sendEmail(subject, body) {
|
||||
transport
|
||||
.sendMail({
|
||||
from: EMAIL_USERNAME,
|
||||
from: EMAIL_FROM,
|
||||
to: EMAIL_SEND_TO,
|
||||
subject: subject,
|
||||
html: body,
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم