[mirotalk] - improve quick devices access, fix test speaker, update dep

This commit is contained in:
Miroslav Pejic
2025-12-19 17:29:00 +01:00
parent bd0739ece0
commit e82eeae41d
8 changed files with 163 additions and 59 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# ====================================================
# MiroTalk P2P v.1.6.88 - Environment Configuration
# MiroTalk P2P v.1.6.89 - Environment Configuration
# ====================================================
# App environment
+1 -1
View File
@@ -2,7 +2,7 @@
/**
* ==============================================
* MiroTalk P2P v.1.6.88 - Configuration File
* MiroTalk P2P v.1.6.89 - Configuration File
* ==============================================
*
* Branding and customizations require a license:
+1 -1
View File
@@ -45,7 +45,7 @@ dependencies: {
* @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
* @version 1.6.88
* @version 1.6.89
*
*/
+48 -47
View File
@@ -1,17 +1,17 @@
{
"name": "mirotalk",
"version": "1.6.88",
"version": "1.6.89",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mirotalk",
"version": "1.6.88",
"version": "1.6.89",
"license": "AGPL-3.0",
"dependencies": {
"@mattermost/client": "11.2.0",
"@ngrok/ngrok": "1.7.0",
"@sentry/node": "^10.32.0",
"@sentry/node": "^10.32.1",
"axios": "^1.13.2",
"chokidar": "^5.0.0",
"colors": "^1.4.0",
@@ -30,7 +30,7 @@
"jsdom": "^27.3.0",
"jsonwebtoken": "^9.0.3",
"nodemailer": "^7.0.11",
"openai": "^6.14.0",
"openai": "^6.15.0",
"qs": "^6.14.0",
"socket.io": "^4.8.1",
"swagger-ui-express": "^5.0.1",
@@ -43,7 +43,7 @@
"prettier": "3.7.4",
"proxyquire": "^2.1.3",
"should": "^13.2.3",
"sinon": "^21.0.0"
"sinon": "^21.0.1"
}
},
"node_modules/@acemir/cssom": {
@@ -1107,18 +1107,18 @@
"license": "Apache-2.0"
},
"node_modules/@sentry/core": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.32.0.tgz",
"integrity": "sha512-E+ihb8+5PBfYMamnXHalgsmxkcG2YQqhRdgYf3yWJ5dJvi4njh1VWK3kNVj1GvsU6ktaielAx4Rg5dwEFMnbZg==",
"version": "10.32.1",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.32.1.tgz",
"integrity": "sha512-PH2ldpSJlhqsMj2vCTyU0BI2Fx1oIDhm7Izo5xFALvjVCS0gmlqHt1udu6YlKn8BtpGH6bGzssvv5APrk+OdPQ==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/node": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.32.0.tgz",
"integrity": "sha512-KENGLH34gUlrNd9QVJFp37w64DZmorWarm67sFJ2J+VmBII0JMkbIJy1SdHyHxGtgitbokotMTjjf9isVnWwlw==",
"version": "10.32.1",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.32.1.tgz",
"integrity": "sha512-oxlybzt8QW0lx/QaEj1DcvZDRXkgouewFelu/10dyUwv5So3YvipfvWInda+yMLmn25OggbloDQ0gyScA2jU3g==",
"license": "MIT",
"dependencies": {
"@opentelemetry/api": "^1.9.0",
@@ -1151,9 +1151,9 @@
"@opentelemetry/sdk-trace-base": "^2.2.0",
"@opentelemetry/semantic-conventions": "^1.37.0",
"@prisma/instrumentation": "6.19.0",
"@sentry/core": "10.32.0",
"@sentry/node-core": "10.32.0",
"@sentry/opentelemetry": "10.32.0",
"@sentry/core": "10.32.1",
"@sentry/node-core": "10.32.1",
"@sentry/opentelemetry": "10.32.1",
"import-in-the-middle": "^2",
"minimatch": "^9.0.0"
},
@@ -1162,14 +1162,14 @@
}
},
"node_modules/@sentry/node-core": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.32.0.tgz",
"integrity": "sha512-O+TVuF1fO0j37W6IzdHCpTIr4uUkFzcSKgxNmH9ihYpRzkQgfLDZJWVxtov+H8/1pC5lkvl2VZhWmY+SWj2kHA==",
"version": "10.32.1",
"resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.32.1.tgz",
"integrity": "sha512-w56rxdBanBKc832zuwnE+zNzUQ19fPxfHEtOhK8JGPu3aSwQYcIxwz9z52lOx3HN7k/8Fj5694qlT3x/PokhRw==",
"license": "MIT",
"dependencies": {
"@apm-js-collab/tracing-hooks": "^0.3.1",
"@sentry/core": "10.32.0",
"@sentry/opentelemetry": "10.32.0",
"@sentry/core": "10.32.1",
"@sentry/opentelemetry": "10.32.1",
"import-in-the-middle": "^2"
},
"engines": {
@@ -1186,12 +1186,12 @@
}
},
"node_modules/@sentry/opentelemetry": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.32.0.tgz",
"integrity": "sha512-owGL94JAgbwxgaeUNLktJWMShZPo04ZKTaQhhLz3YmVDJFj8VFOQXdWBMqv1Gv6T6/fCuTlwzJ3rvpSOImxXUQ==",
"version": "10.32.1",
"resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.32.1.tgz",
"integrity": "sha512-YLssSz5Y+qPvufrh2cDaTXDoXU8aceOhB+YTjT8/DLF6SOj7Tzen52aAcjNaifawaxEsLCC8O+B+A2iA+BllvA==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.32.0"
"@sentry/core": "10.32.1"
},
"engines": {
"node": ">=18"
@@ -1248,9 +1248,9 @@
}
},
"node_modules/@sinonjs/fake-timers": {
"version": "13.0.5",
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz",
"integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==",
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.1.0.tgz",
"integrity": "sha512-cqfapCxwTGsrR80FEgOoPsTonoefMBY7dnUEbQ+GRcved0jvkJLzvX6F4WtN+HBqbPX/SiFsIRUp+IrCW/2I2w==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -1258,14 +1258,13 @@
}
},
"node_modules/@sinonjs/samsam": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz",
"integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==",
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz",
"integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@sinonjs/commons": "^3.0.1",
"lodash.get": "^4.4.2",
"type-detect": "^4.1.0"
}
},
@@ -4397,14 +4396,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
"deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.",
"dev": true,
"license": "MIT"
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -5051,9 +5042,9 @@
}
},
"node_modules/openai": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-6.14.0.tgz",
"integrity": "sha512-ZPD9MG5/sPpyGZ0idRoDK0P5MWEMuXe0Max/S55vuvoxqyEVkN94m9jSpE3YgNgz3WoESFvozs57dxWqAco31w==",
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-6.15.0.tgz",
"integrity": "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g==",
"license": "Apache-2.0",
"bin": {
"openai": "bin/cli"
@@ -6093,16 +6084,16 @@
}
},
"node_modules/sinon": {
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-21.0.0.tgz",
"integrity": "sha512-TOgRcwFPbfGtpqvZw+hyqJDvqfapr1qUlOizROIk4bBLjlsjlB00Pg6wMFXNtJRpu+eCZuVOaLatG7M8105kAw==",
"version": "21.0.1",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-21.0.1.tgz",
"integrity": "sha512-Z0NVCW45W8Mg5oC/27/+fCqIHFnW8kpkFOq0j9XJIev4Ld0mKmERaZv5DMLAb9fGCevjKwaEeIQz5+MBXfZcDw==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@sinonjs/commons": "^3.0.1",
"@sinonjs/fake-timers": "^13.0.5",
"@sinonjs/samsam": "^8.0.1",
"diff": "^7.0.0",
"@sinonjs/fake-timers": "^15.1.0",
"@sinonjs/samsam": "^8.0.3",
"diff": "^8.0.2",
"supports-color": "^7.2.0"
},
"funding": {
@@ -6110,6 +6101,16 @@
"url": "https://opencollective.com/sinon"
}
},
"node_modules/sinon/node_modules/diff": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz",
"integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/sinon/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "mirotalk",
"version": "1.6.88",
"version": "1.6.89",
"description": "A free WebRTC browser-based video call",
"main": "server.js",
"scripts": {
@@ -43,7 +43,7 @@
"dependencies": {
"@mattermost/client": "11.2.0",
"@ngrok/ngrok": "1.7.0",
"@sentry/node": "^10.32.0",
"@sentry/node": "^10.32.1",
"axios": "^1.13.2",
"chokidar": "^5.0.0",
"colors": "^1.4.0",
@@ -62,7 +62,7 @@
"jsdom": "^27.3.0",
"jsonwebtoken": "^9.0.3",
"nodemailer": "^7.0.11",
"openai": "^6.14.0",
"openai": "^6.15.0",
"qs": "^6.14.0",
"socket.io": "^4.8.1",
"swagger-ui-express": "^5.0.1",
@@ -75,6 +75,6 @@
"prettier": "3.7.4",
"proxyquire": "^2.1.3",
"should": "^13.2.3",
"sinon": "^21.0.0"
"sinon": "^21.0.1"
}
}
+28 -1
View File
@@ -426,7 +426,8 @@ body {
transform: none !important;
}
/* Quick device picker (Audio): section headers + divider (Microphones / Speakers) */
/* Quick device picker: section headers + divider (Cameras / Microphones / Speakers) */
#bottomButtons #videoMenu .device-menu-header,
#bottomButtons #audioMenu .device-menu-header {
display: flex;
align-items: center;
@@ -439,11 +440,13 @@ body {
user-select: none;
}
#bottomButtons #videoMenu .device-menu-header i,
#bottomButtons #audioMenu .device-menu-header i {
width: 18px;
text-align: center;
}
#bottomButtons #videoMenu .device-menu-divider,
#bottomButtons #audioMenu .device-menu-divider {
height: 1px;
background: var(--btns-bg-color);
@@ -451,6 +454,30 @@ body {
margin: 8px 0;
}
/* Action buttons in device menu */
#bottomButtons #audioMenu .device-menu-action-btn,
#bottomButtons #videoMenu .device-menu-action-btn {
background: var(--body-bg);
border: 1px solid var(--border-color);
color: #fff;
font-weight: 500;
gap: 8px;
transition: all 0.2s ease;
}
#bottomButtons #audioMenu .device-menu-action-btn:hover,
#bottomButtons #videoMenu .device-menu-action-btn:hover {
background: var(--btns-bg-color) !important;
border-color: var(--btns-color);
transform: translateY(-1px) !important;
}
#bottomButtons #audioMenu .device-menu-action-btn i,
#bottomButtons #videoMenu .device-menu-action-btn i {
width: 18px;
text-align: center;
}
#bottomButtons button:hover {
background: var(--body-bg);
transform: var(--btns-hover-scale);
+1 -1
View File
@@ -77,7 +77,7 @@ let brand = {
},
about: {
imageUrl: '../images/mirotalk-logo.gif',
title: 'WebRTC P2P v1.6.88',
title: 'WebRTC P2P v1.6.89',
html: `
<button
id="support-button"
+79 -3
View File
@@ -15,7 +15,7 @@
* @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
* @version 1.6.88
* @version 1.6.89
*
*/
@@ -6487,7 +6487,7 @@ function setMySettingsBtn() {
hideShowMySettings();
});
speakerTestBtn.addEventListener('click', (e) => {
playSound('ring', true);
playSpeaker(audioOutputSelect?.value, 'ring');
});
myPeerNameSetBtn.addEventListener('click', (e) => {
updateMyPeerName();
@@ -13500,7 +13500,7 @@ function showAbout() {
Swal.fire({
background: swBg,
position: 'center',
title: brand.about?.title && brand.about.title.trim() !== '' ? brand.about.title : 'WebRTC P2P v1.6.88',
title: brand.about?.title && brand.about.title.trim() !== '' ? brand.about.title : 'WebRTC P2P v1.6.89',
imageUrl: brand.about?.imageUrl && brand.about.imageUrl.trim() !== '' ? brand.about.imageUrl : images.about,
customClass: { image: 'img-about' },
html: `
@@ -13935,6 +13935,31 @@ async function playSound(name, force = false, path = '../sounds/') {
}
}
/**
* Test speaker by playing a sound through the selected audio output device
* @param {string} deviceId - Optional audio output device ID. If not provided, uses the currently selected speaker
* @param {string} name audio to play
* @param {string} path od sound files
*/
async function playSpeaker(deviceId = null, name, path = '../sounds/') {
const selectedDeviceId = deviceId || audioOutputSelect?.value;
if (selectedDeviceId) {
const sound = path + name + '.mp3';
const audioToPlay = new Audio(sound);
try {
if (typeof audioToPlay.setSinkId === 'function') {
await audioToPlay.setSinkId(selectedDeviceId);
}
audioToPlay.volume = 0.5;
await audioToPlay.play();
} catch (err) {
console.error('Cannot play test sound:', err);
}
} else {
playSound(name, true);
}
}
/**
* Open specified URL
* @param {string} url to open
@@ -14208,7 +14233,27 @@ function setupQuickDeviceSwitchDropdowns() {
function rebuildVideoMenu() {
if (!videoMenu) return;
videoMenu.innerHTML = '';
appendMenuHeader(videoMenu, 'fas fa-video', 'Cameras');
appendSelectOptions(videoMenu, videoSelect, 'No cameras found', rebuildVideoMenu);
// Add settings button
appendMenuDivider(videoMenu);
const settingsBtn = document.createElement('button');
settingsBtn.type = 'button';
settingsBtn.className = 'device-menu-action-btn';
const settingsIcon = document.createElement('i');
settingsIcon.className = 'fas fa-cog';
settingsBtn.appendChild(settingsIcon);
settingsBtn.appendChild(document.createTextNode(' Open Video Settings'));
settingsBtn.addEventListener('click', () => {
hideShowMySettings();
// Simulate tab click to open video devices tab
setTimeout(() => {
tabVideoBtn.click();
}, 100);
});
videoMenu.appendChild(settingsBtn);
}
function rebuildAudioMenu() {
@@ -14230,6 +14275,37 @@ function setupQuickDeviceSwitchDropdowns() {
return;
}
appendSelectOptions(audioMenu, audioOutputSelect, 'No speakers found', rebuildAudioMenu);
// Add action buttons
appendMenuDivider(audioMenu);
// Test speaker button
const testBtn = document.createElement('button');
testBtn.type = 'button';
testBtn.className = 'device-menu-action-btn';
const testIcon = document.createElement('i');
testIcon.className = 'fa-solid fa-circle-play';
testBtn.appendChild(testIcon);
testBtn.appendChild(document.createTextNode(' Test Speaker'));
testBtn.addEventListener('click', () => playSpeaker(audioOutputSelect?.value, 'ring'));
audioMenu.appendChild(testBtn);
// Settings button
const settingsBtn = document.createElement('button');
settingsBtn.type = 'button';
settingsBtn.className = 'device-menu-action-btn';
const settingsIcon = document.createElement('i');
settingsIcon.className = 'fas fa-cog';
settingsBtn.appendChild(settingsIcon);
settingsBtn.appendChild(document.createTextNode(' Open Audio Settings'));
settingsBtn.addEventListener('click', () => {
hideShowMySettings();
// Simulate tab click to open audio devices tab
setTimeout(() => {
tabAudioBtn.click();
}, 100);
});
audioMenu.appendChild(settingsBtn);
}
// Hover behavior (desktop only). Note: rebuilding alone is invisible if the menu isn't opened.