[mirotalksfu] - add video mirror

هذا الالتزام موجود في:
Miroslav Pejic
2024-09-27 10:06:03 +02:00
الأصل 2c71dd8a37
التزام b0f8438192
9 ملفات معدلة مع 60 إضافات و30 حذوفات

عرض الملف

@@ -55,7 +55,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.5.74
* @version 1.5.75
*
*/

عرض الملف

@@ -385,6 +385,7 @@ module.exports = {
},
producerVideo: {
videoPictureInPicture: true,
videoMirrorButton: true,
fullScreenButton: true,
snapShotButton: true,
muteAudioButton: true,
@@ -392,6 +393,7 @@ module.exports = {
},
consumerVideo: {
videoPictureInPicture: true,
videoMirrorButton: true,
fullScreenButton: true,
snapShotButton: true,
focusVideoButton: true,

عرض الملف

@@ -1,6 +1,6 @@
{
"name": "mirotalksfu",
"version": "1.5.74",
"version": "1.5.75",
"description": "WebRTC SFU browser-based video calls",
"main": "Server.js",
"scripts": {
@@ -64,7 +64,7 @@
"compression": "1.7.4",
"cors": "2.8.5",
"crypto-js": "4.2.0",
"dompurify": "^3.1.6",
"dompurify": "^3.1.7",
"express": "4.21.0",
"express-openid-connect": "^2.17.1",
"fluent-ffmpeg": "^2.1.3",
@@ -77,7 +77,7 @@
"mediasoup-client": "3.7.16",
"ngrok": "^5.0.0-beta.2",
"nodemailer": "^6.9.15",
"openai": "^4.63.0",
"openai": "^4.65.0",
"qs": "6.13.0",
"socket.io": "4.8.0",
"swagger-ui-express": "5.0.1",

عرض الملف

@@ -442,10 +442,6 @@ th {
width: 180px;
}
#VideoMirrorDiv {
margin-top: 10px;
}
/*--------------------------------------------------------------
# RTMP settings
--------------------------------------------------------------*/

عرض الملف

@@ -192,6 +192,7 @@ video {
object-fit: var(--videoObjFit);
border-radius: 10px;
cursor: pointer;
transition: transform 0.3s ease-in-out;
}
#canvasAIElement {

عرض الملف

@@ -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.5.74
* @version 1.5.75
*
*/
@@ -213,6 +213,7 @@ let isEnumerateVideoDevices = false;
let isAudioAllowed = false;
let isVideoAllowed = false;
let isVideoPrivacyActive = false;
let isInitVideoMirror = false;
let isRecording = false;
let isAudioVideoAllowed = false;
let isParticipantsListOpen = false;
@@ -658,6 +659,10 @@ function setupInitButtons() {
initStopScreenButton.onclick = async () => {
await toggleScreenSharing();
};
initVideoMirrorButton.onclick = () => {
initVideo.classList.toggle('mirror');
isInitVideoMirror = initVideo.classList.contains('mirror');
};
}
// ####################################################
@@ -925,7 +930,11 @@ async function whoAreYou() {
});
const serverButtons = response.data.message;
if (serverButtons) {
BUTTONS = serverButtons;
// Merge serverButtons into BUTTONS, keeping the existing keys in BUTTONS if they are not present in serverButtons
BUTTONS = {
...BUTTONS, // Spread current BUTTONS first to keep existing keys
...serverButtons, // Overwrite or add new keys from serverButtons
};
console.log('04 ----> AXIOS ROOM BUTTONS SETTINGS', {
serverButtons: serverButtons,
clientButtons: BUTTONS,
@@ -1980,6 +1989,7 @@ function setButtonsInit() {
setTippy('initAudioVideoButton', 'Toggle the audio & video', 'top');
setTippy('initStartScreenButton', 'Toggle screen sharing', 'top');
setTippy('initStopScreenButton', 'Toggle screen sharing', 'top');
setTippy('initVideoMirrorButton', 'Toggle video mirror', 'top');
}
if (!isAudioAllowed) hide(initAudioButton);
if (!isVideoAllowed) hide(initVideoButton);
@@ -2246,11 +2256,13 @@ function handleCameraMirror(video) {
// Desktop devices...
if (!video.classList.contains('mirror')) {
video.classList.toggle('mirror');
isInitVideoMirror = true;
}
} else {
// Mobile, Tablet, IPad devices...
if (video.classList.contains('mirror')) {
video.classList.remove('mirror');
isInitVideoMirror = false;
}
}
}
@@ -2347,11 +2359,6 @@ function handleSelects() {
lS.setSettings(localStorageSettings);
e.target.blur();
};
switchVideoMirror.onchange = (e) => {
rc.toggleVideoMirror();
rc.roomMessage('toggleVideoMirror', e.currentTarget.checked);
e.target.blur();
};
switchSounds.onchange = (e) => {
isSoundEnabled = e.currentTarget.checked;
rc.roomMessage('sounds', isSoundEnabled);
@@ -2903,7 +2910,6 @@ function handleRoomClientEvents() {
show(stopVideoButton);
setColor(startVideoButton, 'red');
setVideoButtonsDisabled(false);
switchVideoMirror.disabled = false;
// if (isParticipantsListOpen) getRoomParticipants();
});
rc.on(RoomClient.EVENTS.pauseVideo, () => {
@@ -2926,7 +2932,6 @@ function handleRoomClientEvents() {
show(startVideoButton);
setVideoButtonsDisabled(false);
isVideoPrivacyActive = false;
switchVideoMirror.disabled = true;
// if (isParticipantsListOpen) getRoomParticipants();
});
rc.on(RoomClient.EVENTS.startScreen, () => {
@@ -4458,7 +4463,7 @@ function showAbout() {
imageUrl: image.about,
customClass: { image: 'img-about' },
position: 'center',
title: 'WebRTC SFU v1.5.74',
title: 'WebRTC SFU v1.5.75',
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.5.74
* @version 1.5.75
*
*/
@@ -45,6 +45,7 @@ const html = {
videoPrivacy: 'far fa-circle',
expand: 'fas fa-ellipsis-vertical',
hideALL: 'fas fa-eye',
mirror: 'fas fa-arrow-right-arrow-left',
};
const icons = {
@@ -1406,6 +1407,10 @@ class RoomClient {
if (type == mediaType.video) this.videoProducerId = producer.id;
if (type == mediaType.screen) this.screenProducerId = producer.id;
elem = await this.handleProducer(producer.id, type, stream);
// No mirror effect for producer
if (!isInitVideoMirror && elem.classList.contains('mirror')) {
elem.classList.toggle('mirror');
}
//if (!screen && !isEnumerateDevices) enumerateVideoDevices(stream);
} else {
this.localAudioStream = stream;
@@ -1882,7 +1887,7 @@ class RoomClient {
}
async handleProducer(id, type, stream) {
let elem, vb, vp, ts, d, p, i, au, pip, fs, pm, pb, pn;
let elem, vb, vp, ts, d, p, i, au, pip, fs, pm, pb, pn, mv;
switch (type) {
case mediaType.video:
case mediaType.screen:
@@ -1914,6 +1919,9 @@ class RoomClient {
ts = document.createElement('button');
ts.id = id + '__snapshot';
ts.className = html.snapshot;
mv = document.createElement('button');
mv.id = id + '__mirror';
mv.className = html.mirror;
pn = document.createElement('button');
pn.id = id + '__pin';
pn.className = html.pin;
@@ -1945,6 +1953,7 @@ class RoomClient {
BUTTONS.producerVideo.videoPictureInPicture &&
this.isVideoPictureInPictureSupported &&
vb.appendChild(pip);
BUTTONS.producerVideo.videoMirrorButton && vb.appendChild(mv);
BUTTONS.producerVideo.fullScreenButton && this.isVideoFullScreenSupported && vb.appendChild(fs);
if (!this.isMobileDevice) vb.appendChild(pn);
d.appendChild(elem);
@@ -1959,6 +1968,7 @@ class RoomClient {
this.isVideoFullScreenSupported && this.handleFS(elem.id, fs.id);
this.handleDD(elem.id, this.peer_id, true);
this.handleTS(elem.id, ts.id);
this.handleMV(elem.id, mv.id);
this.handlePN(elem.id, pn.id, d.id, isScreen);
this.handleZV(elem.id, d.id, this.peer_id);
if (!isScreen) this.handleVP(elem.id, vp.id);
@@ -1968,6 +1978,7 @@ class RoomClient {
handleAspectRatio();
if (!this.isMobileDevice) {
this.setTippy(pn.id, 'Toggle Pin', 'bottom');
this.setTippy(mv.id, 'Toggle mirror', 'bottom');
this.setTippy(pip.id, 'Toggle picture in picture', 'bottom');
this.setTippy(ts.id, 'Snapshot', 'bottom');
this.setTippy(vp.id, 'Toggle video privacy', 'bottom');
@@ -2262,7 +2273,7 @@ class RoomClient {
}
async handleConsumer(id, type, stream, peer_name, peer_info) {
let elem, vb, d, p, i, cm, au, pip, fs, ts, sf, sm, sv, gl, ban, ko, pb, pm, pv, pn, ha;
let elem, vb, d, p, i, cm, au, pip, fs, ts, sf, sm, sv, gl, ban, ko, pb, pm, pv, pn, ha, mv;
let eDiv, eBtn, eVc; // expand buttons
@@ -2311,6 +2322,9 @@ class RoomClient {
pip = document.createElement('button');
pip.id = id + '__pictureInPicture';
pip.className = html.pip;
mv = document.createElement('button');
mv.id = id + '__videoMirror';
mv.className = html.mirror;
fs = document.createElement('button');
fs.id = id + '__fullScreen';
fs.className = html.fullScreen;
@@ -2379,6 +2393,7 @@ class RoomClient {
BUTTONS.consumerVideo.videoPictureInPicture &&
this.isVideoPictureInPictureSupported &&
vb.appendChild(pip);
BUTTONS.consumerVideo.videoMirrorButton && vb.appendChild(mv);
BUTTONS.consumerVideo.fullScreenButton && this.isVideoFullScreenSupported && vb.appendChild(fs);
BUTTONS.consumerVideo.focusVideoButton && vb.appendChild(ha);
if (!this.isMobileDevice) vb.appendChild(pn);
@@ -2393,6 +2408,7 @@ class RoomClient {
this.isVideoFullScreenSupported && this.handleFS(elem.id, fs.id);
this.handleDD(elem.id, remotePeerId);
this.handleTS(elem.id, ts.id);
this.handleMV(elem.id, mv.id);
this.handleSF(sf.id);
this.handleHA(ha.id, d.id);
this.handleSM(sm.id, peer_name);
@@ -2425,6 +2441,7 @@ class RoomClient {
this.setTippy(pn.id, 'Toggle Pin', 'bottom');
this.setTippy(ha.id, 'Toggle Focus mode', 'bottom');
this.setTippy(pip.id, 'Toggle picture in picture', 'bottom');
this.setTippy(mv.id, 'Toggle mirror', 'bottom');
this.setTippy(ts.id, 'Snapshot', 'bottom');
this.setTippy(sf.id, 'Send file', 'bottom');
this.setTippy(sm.id, 'Send message', 'bottom');
@@ -3610,6 +3627,21 @@ class RoomClient {
}
}
// ####################################################
// HANDLE VIDEO MIRROR
// ####################################################
handleMV(elemId, tsId) {
let videoPlayer = this.getId(elemId);
let btnMv = this.getId(tsId);
if (btnMv && videoPlayer) {
btnMv.addEventListener('click', () => {
videoPlayer.classList.toggle('mirror');
//rc.roomMessage('toggleVideoMirror', videoPlayer.classList.contains('mirror'));
});
}
}
// ####################################################
// VIDEO CIRCLE - PRIVACY MODE
// ####################################################

عرض الملف

@@ -48,6 +48,7 @@ let BUTTONS = {
},
producerVideo: {
videoPictureInPicture: true,
videoMirrorButton: true,
fullScreenButton: true,
snapShotButton: true,
muteAudioButton: true,
@@ -55,6 +56,7 @@ let BUTTONS = {
},
consumerVideo: {
videoPictureInPicture: true,
videoMirrorButton: true,
fullScreenButton: true,
snapShotButton: true,
focusVideoButton: true,

عرض الملف

@@ -170,6 +170,7 @@ access to use this app.
<button id="initAudioVideoButton" class="fas fa-eye"></button>
<button id="initStartScreenButton" class="fas fa-desktop hidden"></button>
<button id="initStopScreenButton" class="fas fa-stop-circle hidden"></button>
<button id="initVideoMirrorButton" class="fas fa-arrow-right-arrow-left"></button>
<select id="initVideoSelect" class="form-select text-light bg-dark"></select>
<select id="initMicrophoneSelect" class="form-select text-light bg-dark"></select>
<select id="initSpeakerSelect" class="form-select text-light bg-dark"></select>
@@ -378,15 +379,6 @@ access to use this app.
<p>Video Source:</p>
</div>
<select id="videoSelect" class="form-select text-light bg-dark"></select>
<div id="VideoMirrorDiv">
<div class="title">
<i class="fas fa-arrow-right-arrow-left"></i>
<p>Toggle mirror</p>
<div class="form-check form-switch form-switch-md">
<input id="switchVideoMirror" class="form-check-input" type="checkbox" checked />
</div>
</div>
</div>
<br />
<div class="title">
<i class="fas fa-palette"></i>