[mirotalk] - #150 allow Join room without audio/video
This commit is contained in:
+1
-1
@@ -38,7 +38,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.0.8
|
||||
* @version 1.0.9
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mirotalk",
|
||||
"version": "1.0.8",
|
||||
"version": "1.0.9",
|
||||
"description": "A free WebRTC browser-based video call",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
||||
+172
-74
@@ -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.0.8
|
||||
* @version 1.0.9
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -830,8 +830,8 @@ function refreshMainButtonsToolTipPlacement() {
|
||||
placement = btnsBarSelect.options[btnsBarSelect.selectedIndex].value == 'vertical' ? 'right' : 'top';
|
||||
setTippy(shareRoomBtn, 'Invite others to join', placement);
|
||||
setTippy(hideMeBtn, 'Toggle hide myself from the room view', placement);
|
||||
setTippy(audioBtn, 'Stop the audio', placement);
|
||||
setTippy(videoBtn, 'Stop the video', placement);
|
||||
setTippy(audioBtn, useAudio ? 'Stop the audio' : 'My audio is disabled', placement);
|
||||
setTippy(videoBtn, useVideo ? 'Stop the video' : 'My video is disabled', placement);
|
||||
setTippy(screenShareBtn, 'Start screen sharing', placement);
|
||||
setTippy(recordStreamBtn, 'Start recording', placement);
|
||||
setTippy(fullScreenBtn, 'View full screen', placement);
|
||||
@@ -1132,6 +1132,9 @@ async function handleConnect() {
|
||||
await initEnumerateDevices();
|
||||
await setupLocalVideoMedia();
|
||||
await setupLocalAudioMedia();
|
||||
if (!useVideo || (!useVideo && !useAudio)) {
|
||||
await loadLocalMedia(new MediaStream(), 'video');
|
||||
}
|
||||
getHtmlElementsById();
|
||||
setButtonsToolTip();
|
||||
manageLeftButtons();
|
||||
@@ -1305,14 +1308,14 @@ async function whoAreYou() {
|
||||
|
||||
await loadLocalStorage();
|
||||
|
||||
if (!buttons.main.showVideoBtn) {
|
||||
if (!useVideo || !buttons.main.showVideoBtn) {
|
||||
useVideo = false;
|
||||
elemDisplay(document.getElementById('initVideo'), false);
|
||||
elemDisplay(document.getElementById('initVideoBtn'), false);
|
||||
elemDisplay(document.getElementById('initVideoSelect'), false);
|
||||
elemDisplay(document.getElementById('tabVideoBtn'), false);
|
||||
}
|
||||
if (!buttons.main.showAudioBtn) {
|
||||
if (!useAudio || !buttons.main.showAudioBtn) {
|
||||
//useAudio = false;
|
||||
elemDisplay(document.getElementById('initAudioBtn'), false);
|
||||
elemDisplay(document.getElementById('initMicrophoneSelect'), false);
|
||||
@@ -1552,14 +1555,14 @@ function checkPeerAudioVideo() {
|
||||
let video = filterXSS(qs.get('video'));
|
||||
if (audio) {
|
||||
audio = audio.toLowerCase();
|
||||
let queryPeerAudio = audio === '1' || audio === 'true';
|
||||
let queryPeerAudio = useAudio ? audio === '1' || audio === 'true' : false;
|
||||
if (queryPeerAudio != null) handleAudio(audioBtn, false, queryPeerAudio);
|
||||
elemDisplay(document.getElementById('tabAudioBtn'), queryPeerAudio);
|
||||
console.log('Direct join', { audio: queryPeerAudio });
|
||||
}
|
||||
if (video) {
|
||||
video = video.toLowerCase();
|
||||
let queryPeerVideo = video === '1' || video === 'true';
|
||||
let queryPeerVideo = useVideo ? video === '1' || video === 'true' : false;
|
||||
if (queryPeerVideo != null) handleVideo(videoBtn, false, queryPeerVideo);
|
||||
elemDisplay(document.getElementById('tabVideoBtn'), queryPeerVideo);
|
||||
console.log('Direct join', { video: queryPeerVideo });
|
||||
@@ -1662,6 +1665,10 @@ async function handleAddPeer(config) {
|
||||
});
|
||||
}
|
||||
|
||||
if (!peer_video) {
|
||||
await loadRemoteMediaStream(new MediaStream(), peers, peer_id, 'video');
|
||||
}
|
||||
|
||||
await wbUpdate();
|
||||
playSound('addPeer');
|
||||
}
|
||||
@@ -1714,8 +1721,10 @@ async function handleOnTrack(peer_id, peers) {
|
||||
peerConnections[peer_id].ontrack = (event) => {
|
||||
const remoteVideoStream = getId(`${peer_id}_video`);
|
||||
const remoteAudioStream = getId(`${peer_id}_audio`);
|
||||
const remoteAvatarImage = getId(`${peer_id}_avatar`);
|
||||
|
||||
const peerInfo = peers[peer_id];
|
||||
const { peer_name } = peerInfo;
|
||||
const { peer_name, peer_video } = peerInfo;
|
||||
const { kind } = event.track;
|
||||
|
||||
console.log('[ON TRACK] - info', { peer_id, peer_name, kind });
|
||||
@@ -1734,12 +1743,16 @@ async function handleOnTrack(peer_id, peers) {
|
||||
? attachMediaStream(remoteAudioStream, event.streams[0])
|
||||
: loadRemoteMediaStream(event.streams[0], peers, peer_id, kind);
|
||||
break;
|
||||
case 'screen':
|
||||
// Currently replace the video track and vice versa
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
console.log('[ON TRACK] - SCREEN SHARING', { peer_id, peer_name, kind });
|
||||
// Create a new screen share video stream from track video (refreshMyStreamToPeers)
|
||||
const inboundStream = new MediaStream([event.track]);
|
||||
attachMediaStream(remoteVideoStream, inboundStream);
|
||||
remoteAvatarImage.style.display = 'none';
|
||||
remoteVideoStream.style.display = 'block';
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2178,27 +2191,6 @@ async function initEnumerateDevices() {
|
||||
console.log('05. init Enumerate Devices');
|
||||
await initEnumerateVideoDevices();
|
||||
await initEnumerateAudioDevices();
|
||||
if (!useAudio && !useVideo) {
|
||||
initEnumerateDevicesFailed = true;
|
||||
playSound('alert');
|
||||
await Swal.fire({
|
||||
allowOutsideClick: false,
|
||||
allowEscapeKey: false,
|
||||
background: '#000000',
|
||||
position: 'center',
|
||||
imageUrl: camMicOff,
|
||||
title: 'Camera and microphone not allowed',
|
||||
text: "Meet needs access to the camera and microphone. Click the locked camera and microphone icon in your browser's address bar, before to join room.",
|
||||
showDenyButton: false,
|
||||
confirmButtonText: `OK`,
|
||||
showClass: { popup: 'animate__animated animate__fadeInDown' },
|
||||
hideClass: { popup: 'animate__animated animate__fadeOutUp' },
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
openURL('/'); // back to homepage
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2343,7 +2335,7 @@ function addChild(device, els) {
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
|
||||
*/
|
||||
async function setupLocalVideoMedia() {
|
||||
if (localVideoMediaStream || initEnumerateDevicesFailed) {
|
||||
if (!useVideo || localVideoMediaStream || initEnumerateDevicesFailed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2355,6 +2347,7 @@ async function setupLocalVideoMedia() {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ video: videoConstraints });
|
||||
if (stream) {
|
||||
await loadLocalMedia(stream, 'video');
|
||||
console.log('10. Access granted to video device');
|
||||
}
|
||||
} catch (err) {
|
||||
handleMediaError('video', err);
|
||||
@@ -2367,7 +2360,7 @@ async function setupLocalVideoMedia() {
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
|
||||
*/
|
||||
async function setupLocalAudioMedia() {
|
||||
if (localAudioMediaStream || initEnumerateDevicesFailed) {
|
||||
if (!useAudio || localAudioMediaStream || initEnumerateDevicesFailed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2381,6 +2374,7 @@ async function setupLocalAudioMedia() {
|
||||
await loadLocalMedia(stream, 'audio');
|
||||
if (useAudio) {
|
||||
await getMicrophoneVolumeIndicator(stream);
|
||||
console.log('10. Access granted to audio device');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -2395,10 +2389,6 @@ async function setupLocalAudioMedia() {
|
||||
*/
|
||||
function handleMediaError(mediaType, err) {
|
||||
console.error(`[Error] - Access denied for ${mediaType} device`, err);
|
||||
playSound('alert');
|
||||
openURL(
|
||||
`/permission?roomId=${roomId}&getUserMediaError=${err.toString()} <br/> Check the common getusermedia errors <a href="https://blog.addpipe.com/common-getusermedia-errors" target="_blank">here</a>`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2406,9 +2396,7 @@ function handleMediaError(mediaType, err) {
|
||||
* @param {object} stream media stream audio - video
|
||||
*/
|
||||
async function loadLocalMedia(stream, kind) {
|
||||
console.log(`10. Access granted to ${kind} device`);
|
||||
|
||||
console.log('LOAD LOCAL MEDIA STREAM TRACKS', stream.getTracks());
|
||||
if (stream) console.log('LOAD LOCAL MEDIA STREAM TRACKS', stream.getTracks());
|
||||
|
||||
switch (kind) {
|
||||
case 'video':
|
||||
@@ -2604,6 +2592,18 @@ async function loadLocalMedia(stream, kind) {
|
||||
myVideoAvatarImage.style.display = 'block';
|
||||
myVideoStatusIcon.className = className.videoOff;
|
||||
videoBtn.className = className.videoOff;
|
||||
if (!isMobileDevice) {
|
||||
setTippy(myVideoStatusIcon, 'My video is disabled', 'bottom');
|
||||
}
|
||||
}
|
||||
|
||||
if (!useAudio) {
|
||||
const audioBtn = getId('audioBtn');
|
||||
myAudioStatusIcon.className = className.audioOff;
|
||||
audioBtn.className = className.audioOff;
|
||||
if (!isMobileDevice) {
|
||||
setTippy(myAudioStatusIcon, 'My audio is disabled', 'bottom');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'audio':
|
||||
@@ -2667,6 +2667,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
console.log('REMOTE PEER INFO', peers[peer_id]);
|
||||
|
||||
const peer_name = peers[peer_id]['peer_name'];
|
||||
const peer_audio = peers[peer_id]['peer_audio'];
|
||||
const peer_video = peers[peer_id]['peer_video'];
|
||||
const peer_video_status = peers[peer_id]['peer_video_status'];
|
||||
const peer_audio_status = peers[peer_id]['peer_audio_status'];
|
||||
@@ -2675,7 +2676,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
const peer_rec_status = peers[peer_id]['peer_rec_status'];
|
||||
const peer_privacy_status = peers[peer_id]['peer_privacy_status'];
|
||||
|
||||
console.log('LOAD REMOTE MEDIA STREAM TRACKS - PeerName:[' + peer_name + ']', stream.getTracks());
|
||||
if (stream) console.log('LOAD REMOTE MEDIA STREAM TRACKS - PeerName:[' + peer_name + ']', stream.getTracks());
|
||||
|
||||
switch (kind) {
|
||||
case 'video':
|
||||
@@ -2831,7 +2832,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
remoteVideoNavBar.appendChild(remoteVideoStatusIcon);
|
||||
remoteVideoNavBar.appendChild(remoteAudioStatusIcon);
|
||||
|
||||
if (buttons.remote.showAudioVolume) {
|
||||
if (peer_audio && buttons.remote.showAudioVolume) {
|
||||
remoteVideoNavBar.appendChild(remoteAudioVolume);
|
||||
}
|
||||
remoteVideoNavBar.appendChild(remoteHandStatusIcon);
|
||||
@@ -3616,6 +3617,7 @@ function getTimeToString(time) {
|
||||
* @param {MediaStream} localVideoMediaStream
|
||||
*/
|
||||
function refreshMyVideoStatus(localVideoMediaStream) {
|
||||
if (!localVideoMediaStream) return;
|
||||
// check Track video status
|
||||
localVideoMediaStream.getTracks().forEach((track) => {
|
||||
if (track.kind === 'video') {
|
||||
@@ -3629,6 +3631,7 @@ function refreshMyVideoStatus(localVideoMediaStream) {
|
||||
* @param {MediaStream} localAudioMediaStream
|
||||
*/
|
||||
function refreshMyAudioStatus(localAudioMediaStream) {
|
||||
if (!localAudioMediaStream) return;
|
||||
// check Track audio status
|
||||
localAudioMediaStream.getTracks().forEach((track) => {
|
||||
if (track.kind === 'audio') {
|
||||
@@ -4822,6 +4825,7 @@ function handleError(err) {
|
||||
* @param {object} stream media stream audio - video
|
||||
*/
|
||||
function attachMediaStream(element, stream) {
|
||||
if (!element || !stream) return;
|
||||
//console.log("DEPRECATED, attachMediaStream will soon be removed.");
|
||||
element.srcObject = stream;
|
||||
console.log('Success, media stream attached', stream.getTracks());
|
||||
@@ -5111,28 +5115,33 @@ async function stopLocalAudioTrack() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable - disable screen sharing
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia
|
||||
* @param {boolean} init screen before join
|
||||
* Toggle screen sharing and handle related actions
|
||||
* @param {boolean} init - Indicates if it's the initial screen share state
|
||||
*/
|
||||
async function toggleScreenSharing(init = false) {
|
||||
screenMaxFrameRate = parseInt(screenFpsSelect.value);
|
||||
const constraints = {
|
||||
audio: false, // enable/disable tab audio
|
||||
video: { frameRate: { max: screenMaxFrameRate } },
|
||||
}; // true | { frameRate: { max: screenMaxFrameRate } }
|
||||
|
||||
let screenMediaPromise = null;
|
||||
|
||||
try {
|
||||
// Going to save webcam video status before to screen share
|
||||
// Set screen frame rate
|
||||
screenMaxFrameRate = parseInt(screenFpsSelect.value);
|
||||
const constraints = {
|
||||
audio: false,
|
||||
video: { frameRate: { max: screenMaxFrameRate } },
|
||||
};
|
||||
|
||||
// Store webcam video status before screen sharing
|
||||
if (!isScreenStreaming) {
|
||||
myVideoStatusBefore = myVideoStatus;
|
||||
console.log('My video status before screen sharing: ' + myVideoStatusBefore);
|
||||
} else {
|
||||
if (!useVideo && !useAudio) {
|
||||
return handleToggleScreenException('Audio and Video are disabled', init);
|
||||
}
|
||||
}
|
||||
screenMediaPromise = isScreenStreaming
|
||||
|
||||
// Get screen or webcam media stream based on current state
|
||||
const screenMediaPromise = isScreenStreaming
|
||||
? await navigator.mediaDevices.getUserMedia(await getAudioVideoConstraints())
|
||||
: await navigator.mediaDevices.getDisplayMedia(constraints);
|
||||
|
||||
if (screenMediaPromise) {
|
||||
isVideoPrivacyActive = false;
|
||||
emitPeerStatus('privacy', isVideoPrivacyActive);
|
||||
@@ -5148,13 +5157,14 @@ async function toggleScreenSharing(init = false) {
|
||||
adaptAspectRatio();
|
||||
await refreshConstraints(screenMediaPromise, videoMaxFrameRate);
|
||||
}
|
||||
|
||||
await emitPeerStatus('screen', myScreenStatus);
|
||||
await stopLocalVideoTrack();
|
||||
await refreshMyLocalStream(screenMediaPromise);
|
||||
await refreshMyStreamToPeers(screenMediaPromise);
|
||||
|
||||
if (init) {
|
||||
// handle init media stream
|
||||
// Handle init media stream
|
||||
if (initStream) stopTracks(initStream);
|
||||
initStream = screenMediaPromise;
|
||||
if (hasVideoTrack(initStream)) {
|
||||
@@ -5171,23 +5181,82 @@ async function toggleScreenSharing(init = false) {
|
||||
}
|
||||
}
|
||||
|
||||
// Disable cam video when screen sharing stop
|
||||
// Disable cam video when screen sharing stops
|
||||
if (!init && !isScreenStreaming && !myVideoStatusBefore) setMyVideoOff(myPeerName);
|
||||
// Enable cam video when screen sharing stop
|
||||
// Enable cam video when screen sharing stops
|
||||
if (!init && !isScreenStreaming && myVideoStatusBefore) setMyVideoStatusTrue();
|
||||
|
||||
myVideo.classList.toggle('mirror');
|
||||
setScreenSharingStatus(isScreenStreaming);
|
||||
if (myVideoAvatarImage && !useVideo)
|
||||
|
||||
if (myVideoAvatarImage && !useVideo) {
|
||||
myVideoAvatarImage.style.display = isScreenStreaming ? 'none' : 'block';
|
||||
let myPrivacyBtn = getId('myPrivacyBtn');
|
||||
}
|
||||
|
||||
const myPrivacyBtn = getId('myPrivacyBtn');
|
||||
if (myPrivacyBtn) myPrivacyBtn.style.display = isScreenStreaming ? 'none' : 'inline';
|
||||
|
||||
if (isScreenStreaming || isVideoPinned) getId('myVideoPinBtn').click();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Error] Unable to share the screen', err);
|
||||
await handleToggleScreenException(`[Warning] Unable to share the screen: ${err}`, init);
|
||||
if (init) return;
|
||||
// userLog('error', 'Unable to share the screen ' + err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle exception and actions when toggling screen sharing
|
||||
* @param {string} reason - The reason message
|
||||
* @param {boolean} init - Indicates whether it's an initial state
|
||||
*/
|
||||
async function handleToggleScreenException(reason, init) {
|
||||
try {
|
||||
console.warn('handleToggleScreenException', reason);
|
||||
|
||||
// Update video privacy status
|
||||
isVideoPrivacyActive = false;
|
||||
emitPeerStatus('privacy', isVideoPrivacyActive);
|
||||
|
||||
// Inform peers about screen sharing stop
|
||||
emitPeersAction('screenStop');
|
||||
|
||||
// Turn off your video
|
||||
setMyVideoOff(myPeerName);
|
||||
|
||||
// Toggle screen streaming status
|
||||
isScreenStreaming = !isScreenStreaming;
|
||||
myScreenStatus = isScreenStreaming;
|
||||
|
||||
// Update screen sharing status
|
||||
setScreenSharingStatus(isScreenStreaming);
|
||||
|
||||
// Emit screen status to peers
|
||||
await emitPeerStatus('screen', myScreenStatus);
|
||||
|
||||
// Stop the local video track
|
||||
await stopLocalVideoTrack();
|
||||
|
||||
// Handle video status based on conditions
|
||||
if (!init && !isScreenStreaming && !myVideoStatusBefore) {
|
||||
setMyVideoOff(myPeerName);
|
||||
} else if (!init && !isScreenStreaming && myVideoStatusBefore) {
|
||||
setMyVideoStatusTrue();
|
||||
}
|
||||
|
||||
// Toggle the 'mirror' class on myVideo
|
||||
myVideo.classList.toggle('mirror');
|
||||
|
||||
// Handle video avatar image and privacy button visibility
|
||||
if (myVideoAvatarImage && !useVideo) {
|
||||
myVideoAvatarImage.style.display = isScreenStreaming ? 'none' : 'block';
|
||||
}
|
||||
|
||||
// Automatically pin the video if screen sharing or video is pinned
|
||||
if (isScreenStreaming || isVideoPinned) {
|
||||
getId('myVideoPinBtn').click();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Error] An unexpected error occurred', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5196,6 +5265,7 @@ async function toggleScreenSharing(init = false) {
|
||||
* @param {boolean} status of screen sharing
|
||||
*/
|
||||
function setScreenSharingStatus(status) {
|
||||
if (!useVideo) myVideo.style.display = status ? 'block' : 'none';
|
||||
initScreenShareBtn.className = status ? className.screenOff : className.screenOn;
|
||||
screenShareBtn.className = status ? className.screenOff : className.screenOn;
|
||||
setTippy(screenShareBtn, status ? 'Stop screen sharing' : 'Start screen sharing', placement);
|
||||
@@ -5261,7 +5331,7 @@ async function refreshMyStreamToPeers(stream, localAudioTrackChange = false) {
|
||||
const myAudioTrack =
|
||||
streamHasAudioTrack && (localAudioTrackChange || isScreenStreaming)
|
||||
? stream.getAudioTracks()[0]
|
||||
: localAudioMediaStream.getAudioTracks()[0];
|
||||
: localAudioMediaStream && localAudioMediaStream.getAudioTracks()[0];
|
||||
|
||||
// Refresh my stream to connected peers except myself
|
||||
for (const peer_id in peerConnections) {
|
||||
@@ -5270,7 +5340,7 @@ async function refreshMyStreamToPeers(stream, localAudioTrackChange = false) {
|
||||
// Replace video track
|
||||
const videoSender = peerConnections[peer_id].getSenders().find((s) => s.track && s.track.kind === 'video');
|
||||
|
||||
if (videoSender) {
|
||||
if (useVideo && videoSender) {
|
||||
videoSender.replaceTrack(stream.getVideoTracks()[0]);
|
||||
console.log('REPLACE VIDEO TRACK TO', { peer_id, peer_name });
|
||||
} else {
|
||||
@@ -5325,11 +5395,13 @@ async function refreshMyLocalStream(stream, localAudioTrackChange = false) {
|
||||
}
|
||||
|
||||
const tracksToInclude = [];
|
||||
const videoTrack = hasVideoTrack(stream) ? stream.getVideoTracks()[0] : localVideoMediaStream.getVideoTracks()[0];
|
||||
const videoTrack = hasVideoTrack(stream)
|
||||
? stream.getVideoTracks()[0]
|
||||
: localVideoMediaStream && localVideoMediaStream.getVideoTracks()[0];
|
||||
const audioTrack =
|
||||
hasAudioTrack(stream) && localAudioTrackChange
|
||||
? stream.getAudioTracks()[0]
|
||||
: localAudioMediaStream.getAudioTracks()[0];
|
||||
: localAudioMediaStream && localAudioMediaStream.getAudioTracks()[0];
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/MediaStream
|
||||
if (useVideo || isScreenStreaming) {
|
||||
@@ -5349,7 +5421,7 @@ async function refreshMyLocalStream(stream, localAudioTrackChange = false) {
|
||||
}
|
||||
} else {
|
||||
console.log('Refresh my local media stream AUDIO');
|
||||
if (audioTrack) {
|
||||
if (useAudio && audioTrack) {
|
||||
tracksToInclude.push(audioTrack);
|
||||
localAudioMediaStream = new MediaStream([audioTrack]);
|
||||
getMicrophoneVolumeIndicator(localAudioMediaStream);
|
||||
@@ -5380,6 +5452,7 @@ async function refreshMyLocalStream(stream, localAudioTrackChange = false) {
|
||||
* @returns boolean
|
||||
*/
|
||||
function hasAudioTrack(mediaStream) {
|
||||
if (!mediaStream) return false;
|
||||
const audioTracks = mediaStream.getAudioTracks();
|
||||
return audioTracks.length > 0;
|
||||
}
|
||||
@@ -5390,6 +5463,7 @@ function hasAudioTrack(mediaStream) {
|
||||
* @returns boolean
|
||||
*/
|
||||
function hasVideoTrack(mediaStream) {
|
||||
if (!mediaStream) return false;
|
||||
const videoTracks = mediaStream.getVideoTracks();
|
||||
return videoTracks.length > 0;
|
||||
}
|
||||
@@ -5462,7 +5536,7 @@ function startStreamRecording() {
|
||||
|
||||
try {
|
||||
audioRecorder = new MixedAudioRecorder();
|
||||
const audioStreams = getAudioStreamFromVideoElements();
|
||||
const audioStreams = getAudioStreamFromAudioElements();
|
||||
console.log('Audio streams tracks --->', audioStreams.getTracks());
|
||||
|
||||
const audioMixerStreams = audioRecorder.getMixedAudioStream([audioStreams, localAudioMediaStream]);
|
||||
@@ -5551,7 +5625,7 @@ function startDesktopRecording(options, audioMixerTracks) {
|
||||
}
|
||||
|
||||
// Add audio mixer tracks to combinedTracks if available
|
||||
if (Array.isArray(audioMixerTracks)) {
|
||||
if (useAudio && Array.isArray(audioMixerTracks)) {
|
||||
combinedTracks.push(...audioMixerTracks);
|
||||
}
|
||||
|
||||
@@ -5575,6 +5649,22 @@ function startDesktopRecording(options, audioMixerTracks) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MediaStream containing audio tracks from audio elements on the page.
|
||||
* @returns {MediaStream} A MediaStream containing audio tracks.
|
||||
*/
|
||||
function getAudioStreamFromAudioElements() {
|
||||
const audioElements = document.querySelectorAll('audio');
|
||||
const audioStream = new MediaStream();
|
||||
audioElements.forEach((audio) => {
|
||||
const audioTrack = audio.srcObject.getAudioTracks()[0];
|
||||
if (audioTrack) {
|
||||
audioStream.addTrack(audioTrack);
|
||||
}
|
||||
});
|
||||
return audioStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MediaStream containing audio tracks from video elements on the page.
|
||||
* @returns {MediaStream} A MediaStream containing audio tracks.
|
||||
@@ -6115,6 +6205,8 @@ function appendMessage(from, img, side, msg, privateMsg, msgId = null) {
|
||||
// check if i receive a private message
|
||||
let msgBubble = getPrivateMsg ? 'private-msg-bubble' : 'msg-bubble';
|
||||
|
||||
const isValidPrivateMessage = getPrivateMsg && getMsgId != null && getMsgId != myPeerId;
|
||||
|
||||
let msgHTML = `
|
||||
<div id="msg-${chatMessagesId}" class="msg ${getSide}-msg">
|
||||
<img class="msg-img" src="${getImg}" />
|
||||
@@ -6127,7 +6219,7 @@ function appendMessage(from, img, side, msg, privateMsg, msgId = null) {
|
||||
<hr/>
|
||||
`;
|
||||
// add btn direct reply to private message
|
||||
if (getPrivateMsg && getMsgId != null && getMsgId != myPeerId) {
|
||||
if (isValidPrivateMessage) {
|
||||
msgHTML += `
|
||||
<button
|
||||
class="${className.msgPrivate}"
|
||||
@@ -6169,7 +6261,9 @@ function appendMessage(from, img, side, msg, privateMsg, msgId = null) {
|
||||
setTippy(getId('msg-delete-' + chatMessagesId), 'Delete', 'top');
|
||||
setTippy(getId('msg-copy-' + chatMessagesId), 'Copy', 'top');
|
||||
setTippy(getId('msg-speech-' + chatMessagesId), 'Speech', 'top');
|
||||
setTippy(getId('msg-private-reply-' + chatMessagesId), 'Reply', 'top');
|
||||
if (isValidPrivateMessage) {
|
||||
setTippy(getId('msg-private-reply-' + chatMessagesId), 'Reply', 'top');
|
||||
}
|
||||
}
|
||||
chatMessagesId++;
|
||||
}
|
||||
@@ -6810,7 +6904,9 @@ function setMyHandStatus() {
|
||||
* @param {boolean} status of my audio
|
||||
*/
|
||||
function setMyAudioStatus(status) {
|
||||
myAudioStatusIcon.className = status ? className.audioOn : className.audioOff;
|
||||
const audioClassName = status ? className.audioOn : className.audioOff;
|
||||
audioBtn.className = audioClassName;
|
||||
myAudioStatusIcon.className = audioClassName;
|
||||
// send my audio status to all peers in the room
|
||||
emitPeerStatus('audio', status);
|
||||
setTippy(myAudioStatusIcon, status ? 'My audio is on' : 'My audio is off', 'bottom');
|
||||
@@ -7138,8 +7234,10 @@ function handleScreenStop(peer_id, peer_use_video) {
|
||||
if (remoteVideoAvatarImage && remoteVideoStream && !peer_use_video) {
|
||||
remoteVideoAvatarImage.style.display = 'block';
|
||||
remoteVideoStream.srcObject.getVideoTracks().forEach((track) => {
|
||||
track.enabled = false;
|
||||
track.stop();
|
||||
// track.enabled = false;
|
||||
});
|
||||
remoteVideoStream.style.display = 'none';
|
||||
} else {
|
||||
if (remoteVideoAvatarImage) {
|
||||
remoteVideoAvatarImage.style.display = 'none';
|
||||
|
||||
Reference in New Issue
Block a user