[mirotalksfu] - replace ScriptProcessorNode (deprecated) with AudioWorkletNode

هذا الالتزام موجود في:
Miroslav Pejic
2025-07-09 14:36:41 +02:00
الأصل f8c43426f3
التزام 61d0896e5e
7 ملفات معدلة مع 186 إضافات و81 حذوفات

عرض الملف

@@ -1047,7 +1047,9 @@ module.exports = {
*/
whoAreYou: {
title: process.env.WHO_ARE_YOU_TITLE || 'Who are you?',
description: process.env.WHO_ARE_YOU_DESCRIPTION || "If you\'re the presenter, please log in now.<br />Otherwise, kindly wait for the presenter to join.",
description:
process.env.WHO_ARE_YOU_DESCRIPTION ||
"If you\'re the presenter, please log in now.<br />Otherwise, kindly wait for the presenter to join.",
buttonLoginLabel: process.env.WHO_ARE_YOU_BUTTON_LOGIN_LABEL || 'LOGIN',
buttonJoinLabel: process.env.WHO_ARE_YOU_JOIN_LABEL || 'JOIN ROOM',
},

130
package-lock.json مولّد
عرض الملف

@@ -1,19 +1,19 @@
{
"name": "mirotalksfu",
"version": "1.8.84",
"version": "1.8.85",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mirotalksfu",
"version": "1.8.84",
"version": "1.8.85",
"license": "AGPL-3.0",
"dependencies": {
"@aws-sdk/client-s3": "^3.842.0",
"@aws-sdk/lib-storage": "^3.842.0",
"@mattermost/client": "10.8.0",
"@ngrok/ngrok": "1.5.1",
"@sentry/node": "^9.35.0",
"@sentry/node": "^9.36.0",
"async-mutex": "^0.5.0",
"axios": "^1.10.0",
"chokidar": "^4.0.3",
@@ -23,7 +23,7 @@
"crypto-js": "4.2.0",
"discord.js": "^14.21.0",
"dompurify": "^3.2.6",
"dotenv": "^17.0.1",
"dotenv": "^17.1.0",
"express": "5.1.0",
"express-openid-connect": "^2.18.1",
"fluent-ffmpeg": "^2.1.3",
@@ -36,7 +36,7 @@
"mediasoup": "3.16.5",
"mediasoup-client": "3.12.4",
"nodemailer": "^7.0.5",
"openai": "^5.8.2",
"openai": "^5.8.3",
"qs": "6.14.0",
"sanitize-filename": "^1.6.3",
"socket.io": "4.8.1",
@@ -54,7 +54,7 @@
"proxyquire": "^2.1.3",
"should": "^13.2.3",
"sinon": "^21.0.0",
"webpack": "^5.99.9",
"webpack": "^5.100.0",
"webpack-cli": "^6.0.1"
},
"engines": {
@@ -3692,9 +3692,9 @@
}
},
"node_modules/@prisma/instrumentation": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.10.1.tgz",
"integrity": "sha512-JC8qzgEDuFKjuBsqrZvXHINUb12psnE6Qy3q5p2MBhalC1KW1MBBUwuonx6iS5TCfCdtNslHft8uc2r+EdLWWg==",
"version": "6.11.1",
"resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.11.1.tgz",
"integrity": "sha512-mrZOev24EDhnefmnZX7WVVT7v+r9LttPRqf54ONvj6re4XMF7wFTpK2tLJi4XHB7fFp/6xhYbgRel8YV7gQiyA==",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/instrumentation": "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0"
@@ -3744,18 +3744,18 @@
"license": "Apache-2.0"
},
"node_modules/@sentry/core": {
"version": "9.35.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.35.0.tgz",
"integrity": "sha512-bdAtzVQZ/wn4L/m8r2OUCCG/NWr0Q8dyZDwdwvINJaMbyhDRUdQh/MWjrz+id/3JoOL1LigAyTV1h4FJDGuwUQ==",
"version": "9.36.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.36.0.tgz",
"integrity": "sha512-LU6EmsXPxi8QFkrx0fCqhXicsJA6uUWCD0VrxePZzs+Xs0SgVNDxOgRELVrZa4LPomQJBR5wmm3Duozp9JkHcQ==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/node": {
"version": "9.35.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-9.35.0.tgz",
"integrity": "sha512-7ifFqTsa3BtZGRAgqoWqYf7OJizKSyEzQlSixgBc253wyYWiLaVJ15By9Y4ozd+PbgpOPqfDN5B45Y+OxtQnQw==",
"version": "9.36.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-9.36.0.tgz",
"integrity": "sha512-MUaMWeuIm83LCu/1u9UmULqbhqEfqMjKHGNAZK/lqPu6Vh3E00AQhZmhRcVe7K8ZUOYuFQkSS40zNgKlcSz/hA==",
"license": "MIT",
"dependencies": {
"@opentelemetry/api": "^1.9.0",
@@ -3787,9 +3787,10 @@
"@opentelemetry/resources": "^1.30.1",
"@opentelemetry/sdk-trace-base": "^1.30.1",
"@opentelemetry/semantic-conventions": "^1.34.0",
"@prisma/instrumentation": "6.10.1",
"@sentry/core": "9.35.0",
"@sentry/opentelemetry": "9.35.0",
"@prisma/instrumentation": "6.11.1",
"@sentry/core": "9.36.0",
"@sentry/node-core": "9.36.0",
"@sentry/opentelemetry": "9.36.0",
"import-in-the-middle": "^1.14.2",
"minimatch": "^9.0.0"
},
@@ -3806,13 +3807,15 @@
"node": ">=14"
}
},
"node_modules/@sentry/node/node_modules/@sentry/opentelemetry": {
"version": "9.35.0",
"resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-9.35.0.tgz",
"integrity": "sha512-XJmSC71KaN+qwYf5EEobLDyWum4FijpIjnpTVTYOrq037uUCpxJEGtgQHq0X+DE/ycVUX/Og2PiAgTeCQEYfDg==",
"node_modules/@sentry/node/node_modules/@sentry/node-core": {
"version": "9.36.0",
"resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-9.36.0.tgz",
"integrity": "sha512-hrsIxkEbPHJ6a37LUFX4Bkbhx8nAKQVRCUDzwUw2TCXyW9eLPkbiIxW7Q4vNYAE7MiBTQoG7KJrb+0VMaNNS9A==",
"license": "MIT",
"dependencies": {
"@sentry/core": "9.35.0"
"@sentry/core": "9.36.0",
"@sentry/opentelemetry": "9.36.0",
"import-in-the-middle": "^1.14.2"
},
"engines": {
"node": ">=18"
@@ -3821,7 +3824,28 @@
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0",
"@opentelemetry/core": "^1.30.1 || ^2.0.0",
"@opentelemetry/instrumentation": "^0.57.1 || ^0.200.0",
"@opentelemetry/instrumentation": "^0.57.1 || ^0.202.0",
"@opentelemetry/resources": "^1.30.1 || ^2.0.0",
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0",
"@opentelemetry/semantic-conventions": "^1.34.0"
}
},
"node_modules/@sentry/node/node_modules/@sentry/opentelemetry": {
"version": "9.36.0",
"resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-9.36.0.tgz",
"integrity": "sha512-1J3deP+QKekKv03EUj3GZRN8o3l+4o5wnAzaa1/5KqW7y+16eywYsIQsb6Mj7cGZ3Mjcg9ltSm5iDEpiqnuS4Q==",
"license": "MIT",
"dependencies": {
"@sentry/core": "9.36.0"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0",
"@opentelemetry/core": "^1.30.1 || ^2.0.0",
"@opentelemetry/instrumentation": "^0.57.1 || ^0.202.0",
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0",
"@opentelemetry/semantic-conventions": "^1.34.0"
}
@@ -4713,9 +4737,9 @@
}
},
"node_modules/@types/estree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"dev": true,
"license": "MIT"
},
@@ -5109,9 +5133,9 @@
}
},
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -5129,6 +5153,19 @@
"acorn": "^8"
}
},
"node_modules/acorn-import-phases": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.3.tgz",
"integrity": "sha512-jtKLnfoOzm28PazuQ4dVBcE9Jeo6ha1GAJvq3N0LlNOszmTfx+wSycBehn+FN0RnyeR77IBxN/qVYMw0Rlj0Xw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10.13.0"
},
"peerDependencies": {
"acorn": "^8.14.0"
}
},
"node_modules/agent-base": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
@@ -6219,9 +6256,9 @@
}
},
"node_modules/dotenv": {
"version": "17.0.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.0.1.tgz",
"integrity": "sha512-GLjkduuAL7IMJg/ZnOPm9AnWKJ82mSE2tzXLaJ/6hD6DhwGfZaXG77oB8qbReyiczNxnbxQKyh0OE5mXq0bAHA==",
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.1.0.tgz",
"integrity": "sha512-tG9VUTJTuju6GcXgbdsOuRhupE8cb4mRgY5JLRCh4MtGoVo3/gfGUtOMwmProM6d0ba2mCFvv+WrpYJV6qgJXQ==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -8539,9 +8576,9 @@
}
},
"node_modules/openai": {
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/openai/-/openai-5.8.2.tgz",
"integrity": "sha512-8C+nzoHYgyYOXhHGN6r0fcb4SznuEn1R7YZMvlqDbnCuE0FM2mm3T1HiYW6WIcMS/F1Of2up/cSPjLPaWt0X9Q==",
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/openai/-/openai-5.8.3.tgz",
"integrity": "sha512-IdotKmquCnpouTRvF9xRXVhMx6K5Sc8zkD6Usf+so+NTQ+qiJ8bLSCd7LBb8b/Rof7uYltlSxJhNp+spphKI4Q==",
"license": "Apache-2.0",
"bin": {
"openai": "bin/cli"
@@ -10504,22 +10541,23 @@
}
},
"node_modules/webpack": {
"version": "5.99.9",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz",
"integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==",
"version": "5.100.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.0.tgz",
"integrity": "sha512-H8yBSBTk+BqxrINJnnRzaxU94SVP2bjd7WmA+PfCphoIdDpeQMJ77pq9/4I7xjLq38cB1bNKfzYPZu8pB3zKtg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
"@types/estree": "^1.0.8",
"@types/json-schema": "^7.0.15",
"@webassemblyjs/ast": "^1.14.1",
"@webassemblyjs/wasm-edit": "^1.14.1",
"@webassemblyjs/wasm-parser": "^1.14.1",
"acorn": "^8.14.0",
"acorn": "^8.15.0",
"acorn-import-phases": "^1.0.3",
"browserslist": "^4.24.0",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.17.1",
"enhanced-resolve": "^5.17.2",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
@@ -10533,7 +10571,7 @@
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.11",
"watchpack": "^2.4.1",
"webpack-sources": "^3.2.3"
"webpack-sources": "^3.3.3"
},
"bin": {
"webpack": "bin/webpack.js"
@@ -10620,9 +10658,9 @@
}
},
"node_modules/webpack-sources": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
"integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
"dev": true,
"license": "MIT",
"engines": {

عرض الملف

@@ -1,6 +1,6 @@
{
"name": "mirotalksfu",
"version": "1.8.84",
"version": "1.8.85",
"description": "WebRTC SFU browser-based video calls",
"main": "Server.js",
"scripts": {
@@ -61,7 +61,7 @@
"@aws-sdk/lib-storage": "^3.842.0",
"@mattermost/client": "10.8.0",
"@ngrok/ngrok": "1.5.1",
"@sentry/node": "^9.35.0",
"@sentry/node": "^9.36.0",
"async-mutex": "^0.5.0",
"axios": "^1.10.0",
"chokidar": "^4.0.3",
@@ -71,7 +71,7 @@
"crypto-js": "4.2.0",
"discord.js": "^14.21.0",
"dompurify": "^3.2.6",
"dotenv": "^17.0.1",
"dotenv": "^17.1.0",
"express": "5.1.0",
"express-openid-connect": "^2.18.1",
"fluent-ffmpeg": "^2.1.3",
@@ -84,7 +84,7 @@
"mediasoup": "3.16.5",
"mediasoup-client": "3.12.4",
"nodemailer": "^7.0.5",
"openai": "^5.8.2",
"openai": "^5.8.3",
"qs": "6.14.0",
"sanitize-filename": "^1.6.3",
"socket.io": "4.8.1",
@@ -102,7 +102,7 @@
"proxyquire": "^2.1.3",
"should": "^13.2.3",
"sinon": "^21.0.0",
"webpack": "^5.99.9",
"webpack": "^5.100.0",
"webpack-cli": "^6.0.1"
}
}

عرض الملف

@@ -69,13 +69,14 @@ let BRAND = {
},
whoAreYou: {
title: 'Who are you?',
description: "If you\'re the presenter, please log in now.<br />Otherwise, kindly wait for the presenter to join.",
description:
"If you\'re the presenter, please log in now.<br />Otherwise, kindly wait for the presenter to join.",
buttonLoginLabel: 'LOGIN',
buttonJoinLabel: 'JOIN ROOM',
},
about: {
imageUrl: '../images/mirotalk-logo.gif',
title: '<strong>WebRTC SFU v1.8.84</strong>',
title: '<strong>WebRTC SFU v1.8.85</strong>',
html: `
<button
id="support-button"

عرض الملف

@@ -11,7 +11,7 @@ if (location.href.substr(0, 5) !== 'https') location.href = 'https' + location.h
* @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.84
* @version 1.8.85
*
*/
@@ -297,7 +297,8 @@ let isRoomLocked = false;
let initStream = null;
let scriptProcessor = null;
let audioContext = null;
let workletNode = null;
// window.location.origin + '/join/' + roomId
// window.location.origin + '/join/?room=' + roomId + '&token=' + myToken
@@ -755,37 +756,64 @@ function setupInitButtons() {
async function getMicrophoneVolumeIndicator(stream) {
if (isAudioContextSupported() && hasAudioTrack(stream)) {
stopMicrophoneProcessing();
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const microphone = audioContext.createMediaStreamSource(stream);
scriptProcessor = audioContext.createScriptProcessor(1024, 1, 1);
scriptProcessor.onaudioprocess = function (event) {
const inputBuffer = event.inputBuffer.getChannelData(0);
let sum = 0;
for (let i = 0; i < inputBuffer.length; i++) {
sum += inputBuffer[i] * inputBuffer[i];
}
const rms = Math.sqrt(sum / inputBuffer.length);
const volume = Math.max(0, Math.min(1, rms * 10));
updateVolumeIndicator(volume);
};
microphone.connect(scriptProcessor);
scriptProcessor.connect(audioContext.destination);
try {
stopMicrophoneProcessing();
console.log('Start microphone volume indicator for audio track', stream.getAudioTracks()[0]);
audioContext = new (window.AudioContext || window.webkitAudioContext)();
const microphone = audioContext.createMediaStreamSource(stream);
await audioContext.audioWorklet.addModule('/js/VolumeProcessor.js');
workletNode = new AudioWorkletNode(audioContext, 'volume-processor');
// Handle data from VolumeProcessor.js
workletNode.port.onmessage = (event) => {
const data = event.data;
switch (data.type) {
case 'volumeIndicator':
updateVolumeIndicator(data.volume);
break;
//...
default:
console.warn('Unknown message type from VolumeProcessor:', data.type);
break;
}
};
microphone.connect(workletNode);
workletNode.connect(audioContext.destination);
} catch (error) {
console.error('Error initializing microphone volume indicator:', error);
stopMicrophoneProcessing();
}
} else {
console.warn('Microphone volume indicator not supported for this browser');
}
}
function stopMicrophoneProcessing() {
if (scriptProcessor) {
scriptProcessor.disconnect();
scriptProcessor = null;
console.log('Stop microphone volume indicator');
if (workletNode) {
try {
workletNode.disconnect();
} catch (error) {
console.warn('Error disconnecting workletNode:', error);
}
workletNode = null;
}
if (audioContext) {
try {
if (audioContext.state !== 'closed') {
audioContext.close();
}
} catch (error) {
console.warn('Error closing audioContext:', error);
}
audioContext = null;
}
bars.forEach((bar) => {
bar.classList.toggle('inactive');
});
}
function updateVolumeIndicator(volume) {
const activeBars = Math.ceil(volume * bars.length);
const normalizedVolume = Math.max(0, Math.min(1, volume));
const activeBars = Math.ceil(normalizedVolume * bars.length);
bars.forEach((bar, index) => {
bar.classList.toggle('active', index < activeBars);
});
@@ -796,11 +824,13 @@ function isAudioContextSupported() {
}
function hasAudioTrack(mediaStream) {
if (!mediaStream) return false;
const audioTracks = mediaStream.getAudioTracks();
return audioTracks.length > 0;
}
function hasVideoTrack(mediaStream) {
if (!mediaStream) return false;
const videoTracks = mediaStream.getVideoTracks();
return videoTracks.length > 0;
}
@@ -5479,7 +5509,7 @@ function showAbout() {
position: 'center',
imageUrl: BRAND.about?.imageUrl && BRAND.about.imageUrl.trim() !== '' ? BRAND.about.imageUrl : image.about,
customClass: { image: 'img-about' },
title: BRAND.about?.title && BRAND.about.title.trim() !== '' ? BRAND.about.title : 'WebRTC SFU v1.8.84',
title: BRAND.about?.title && BRAND.about.title.trim() !== '' ? BRAND.about.title : 'WebRTC SFU v1.8.85',
html: `
<br />
<div id="about">

عرض الملف

@@ -9,7 +9,7 @@
* @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.84
* @version 1.8.85
*
*/

عرض الملف

@@ -0,0 +1,34 @@
// volume-processor.js
class VolumeProcessor extends AudioWorkletProcessor {
constructor() {
super();
}
process(inputs, outputs, parameters) {
const input = inputs[0];
if (!input || input.length === 0) {
return true;
}
const inputData = input[0];
if (!inputData || inputData.length === 0) {
return true;
}
let sum = 0;
for (let i = 0; i < inputData.length; i++) {
sum += inputData[i] * inputData[i];
}
const rms = Math.sqrt(sum / inputData.length);
const volume = Math.max(0, Math.min(1, rms * 10));
// Send volume data for UI updates
this.port.postMessage({
type: 'volumeIndicator',
volume: volume,
});
return true;
}
}
registerProcessor('volume-processor', VolumeProcessor);