jitsi / jitsi-meet

Jitsi Meet - Secure, Simple and Scalable Video Conferences that you use as a standalone app or embed in your web application.
https://jitsi.org/meet
Apache License 2.0
22.96k stars 6.69k forks source link

Hide self-view in tile view #8477

Closed murchu27 closed 2 years ago

murchu27 commented 3 years ago

Describe the solution you'd like Would like to have the option to hide, or at the very least minimise my own camera/video input in the tile view.

Seeing my own video can be very distracting, as I find my eyes are drawn to what I'm doing rather than the person I'm speaking to. Also, depending on the number of people, removing your own video can be more space efficient - e.g., at certain resolutions, 4 videos fill up the screen nicely, but a 5th video forces every video to be much smaller.

The focus/spotlight view (showing one person at a time) already does this by putting my video up in the top right corner - this is exactly the kind of thing I'm looking for, except in the tile view instead.

Google Meet's "grid" view also does this, for reference.

Describe alternatives you've considered The spotlight view is an okay alternative when I really don't want to see myself, but there are certain meetings where being able to see everyone at once is much better - e.g. playing role-playing games where you want to be able to see everyone's reactions.

saghul commented 3 years ago

We are currently not considering adding this capability. That might change in the future.

jucor commented 3 years ago

Flagging that hiding self-view is one of the most recommended "self-care" points to avoid "Zoom fatigue". See press coverage in:

and even relayed in multiple corporate advice internal and external websites such as

Note: these articles reflect not just the most recent research advertised this month. Some of these links date from early 2020 too.

Using spotlight view is not a good workaround, as seeing every participant is very important in "strategic multi-stakeholders" meetings.

May I suggest reconsidering adding this feature, please?

saghul commented 3 years ago

Thanks for putting together these resources, it certainly helps make your case. We'll take a look.

jucor commented 3 years ago

Thanks @saghul , appreciate it :) And thanks for the great work on Jitsi!

psychoslave commented 3 years ago

Hello dear Jitsi team,

Here is the scenario that led me here: a videoconference with two friends.

Expected default display: each of my friend taking mostly half of the window split vertically, my own face in a disableable thumbnail in some corner to enable a control that the webcam is well positioned.

Actual result: my own face taking up half the height of the window, and my friends’ video being tiled down to meet the remaining half top of the window space.

This is all the more critical on a smaller screens. The previously referenced session was used on a laptop (14”) plugged to a larger screen. The session was started on the larger screen, and this was less annoying though not really the best experience. But at some point we talked about some organizational point that led me to open some project management window, so the Jitsi window was thrown on the smaller screen (an alternative possibility would have been to use half the screen for each application window, the point on smallest window space staying the same). Once scaled down to such a small size, all display videos were looking more like incidental thumbnails than the main focus points.

This scenario is surely rather common. And even more common might be the scenario of people who actually only have a single small screen available.

And by the way, thank you for delivering such a great FLOSS tool to the world.

saghul commented 3 years ago

We are going to be looking into new layouts, but can't provide an ETA yet.

jjtiziou commented 3 years ago

+1 for this feature –

Being able to toggle self-view on and off feels pretty key for reasons well enumerated above (layout efficiency, alleviating self-consciousness & zoom fatigue, removing distraction & improving focus)

I'd love to see this feature prioritized.

Thanks to all for your work on this great offering! -jj

tg295 commented 3 years ago

Have there been any developments on this? thanks!

saghul commented 3 years ago

Nothing to report, sorry.

tstrijdhorst commented 3 years ago

+100

chrisfromredfin commented 3 years ago

I wonder if for at least those using a browser (not Electron app), this could be accomplished with a browser extension or Greasemonkey type script?

andreas1107 commented 2 years ago

+1 on this, would be really useful

WillowP commented 2 years ago

Major plus 1 to this. I have a very hard time participating in calls with self-view on.

In regards to this comment:

I wonder if for at least those using a browser (not Electron app), this could be accomplished with a browser extension or Greasemonkey type script?

FWIW, a very simple workaround. In tile view, Jitsi has the "self view" in a span with id="localVideoContainer. I made a style for Stylish that hides it. Does not fix the screen space problem, but at least lets you breathe a sigh of relief at not looking in the mirror while on calls.

I've only tested on Firefox.

  1. Install stylish plugin. https://addons.mozilla.org/en-US/firefox/addon/stylish/
  2. Select "Create New Style" from breadcrumb dropdown.
  3. Paste in this CSS and save:
    #localVideoContainer {
    display: none;
    }

    You'll get a warning about not using ids in selectors, but it still seems to work fine.

tbutter commented 2 years ago

@WillowP That workaround now leaves an empty spot in the UI were the video was.

murchu27 commented 2 years ago

@WillowP That workaround now leaves an empty spot in the UI were the video was.

They already mentioned that in their comment:

FWIW, a very simple workaround. In tile view, Jitsi has the "self view" in a span with id="localVideoContainer. I made a style for Stylish that hides it. Does not fix the screen space problem, but at least lets you breathe a sigh of relief at not looking in the mirror while on calls.

jbg commented 2 years ago

Nasty nasty hack, but joining with #config.iAmRecorder=true removes your local video (ref). It will almost certainly have other undesirable side-effects though.

Since removing the local participant for Jibri is already implemented, it seems like the patch to add a config option for this should be relatively simple, something like:

diff --git a/config.js b/config.js
index 1c1dfe71d..412e2d108 100644
--- a/config.js
+++ b/config.js
@@ -995,6 +995,9 @@ var config = {
     // If true, tile view will not be enabled automatically when the participants count threshold is reached.
     // disableTileView: true,

+    // If true, the local participant thumbnail will be hidden.
+    // hideLocalThumbnail: false,
+
     // Controls the visibility and behavior of the top header conference info labels.
     // If a label's id is not in any of the 2 arrays, it will not be visible at all on the header.
     // conferenceInfo: {
diff --git a/react/features/base/config/configWhitelist.js b/react/features/base/config/configWhitelist.js
index 0992fd70b..85f0aae17 100644
--- a/react/features/base/config/configWhitelist.js
+++ b/react/features/base/config/configWhitelist.js
@@ -122,6 +122,7 @@ export default [
     'disableSimulcast',
     'disableThirdPartyRequests',
     'disableTileView',
+    'hideLocalThumbnail',
     'displayJids',
     'doNotStoreRoom',
     'doNotFlipLocalVideo',
diff --git a/react/features/filmstrip/components/web/Filmstrip.js b/react/features/filmstrip/components/web/Filmstrip.js
index 77ad566d2..7154da5dc 100644
--- a/react/features/filmstrip/components/web/Filmstrip.js
+++ b/react/features/filmstrip/components/web/Filmstrip.js
@@ -65,9 +65,9 @@ type Props = {
     _filmstripHeight: number,

     /**
-     * Whether this is a recorder or not.
+     * Whether the local thumbnail is hidden.
      */
-    _iAmRecorder: boolean,
+    _hideLocalThumbnail: boolean,

     /**
      * Whether the filmstrip button is enabled.
@@ -241,14 +241,14 @@ class Filmstrip extends PureComponent <Props> {
      * @returns {Object}
      */
     _calculateIndices(startIndex, stopIndex) {
-        const { _currentLayout, _iAmRecorder, _thumbnailsReordered } = this.props;
+        const { _currentLayout, _hideLocalThumbnail, _thumbnailsReordered } = this.props;
         let start = startIndex;
         let stop = stopIndex;

         if (_thumbnailsReordered) {
             // In tile view, the indices needs to be offset by 1 because the first thumbnail is that of the local
             // endpoint. The remote participants start from index 1.
-            if (!_iAmRecorder && _currentLayout === LAYOUTS.TILE_VIEW) {
+            if (!_hideLocalThumbnail && _currentLayout === LAYOUTS.TILE_VIEW) {
                 start = Math.max(startIndex - 1, 0);
                 stop = stopIndex - 1;
             }
@@ -302,7 +302,7 @@ class Filmstrip extends PureComponent <Props> {
     _gridItemKey({ columnIndex, rowIndex }) {
         const {
             _columns,
-            _iAmRecorder,
+            _hideLocalThumbnail,
             _remoteParticipants,
             _remoteParticipantsLength,
             _thumbnailsReordered
@@ -311,13 +311,13 @@ class Filmstrip extends PureComponent <Props> {

         // When the thumbnails are reordered, local participant is inserted at index 0.
         const localIndex = _thumbnailsReordered ? 0 : _remoteParticipantsLength;
-        const remoteIndex = _thumbnailsReordered && !_iAmRecorder ? index - 1 : index;
+        const remoteIndex = _thumbnailsReordered && !_hideLocalThumbnail ? index - 1 : index;

-        if (index > _remoteParticipantsLength - (_iAmRecorder ? 1 : 0)) {
+        if (index > _remoteParticipantsLength - (_hideLocalThumbnail ? 1 : 0)) {
             return `empty-${index}`;
         }

-        if (!_iAmRecorder && index === localIndex) {
+        if (!_hideLocalThumbnail && index === localIndex) {
             return 'local';
         }

@@ -558,7 +558,7 @@ class Filmstrip extends PureComponent <Props> {
  */
 function _mapStateToProps(state) {
     const toolbarButtons = getToolbarButtons(state);
-    const { testing = {}, iAmRecorder } = state['features/base/config'];
+    const { testing = {}, iAmRecorder, hideLocalThumbnail } = state['features/base/config'];
     const enableThumbnailReordering = testing.enableThumbnailReordering ?? true;
     const { visible, remoteParticipants } = state['features/filmstrip'];
     const reduceHeight = state['features/toolbox'].visible && toolbarButtons.length;
@@ -626,7 +626,7 @@ function _mapStateToProps(state) {
         _currentLayout,
         _filmstripHeight: remoteFilmstripHeight,
         _filmstripWidth: remoteFilmstripWidth,
-        _iAmRecorder: Boolean(iAmRecorder),
+        _hideLocalThumbnail: Boolean(iAmRecorder || hideLocalThumbnail),
         _isFilmstripButtonEnabled: isButtonEnabled('filmstrip', state),
         _remoteParticipantsLength: remoteParticipants.length,
         _remoteParticipants: remoteParticipants,
diff --git a/react/features/filmstrip/components/web/ThumbnailWrapper.js b/react/features/filmstrip/components/web/ThumbnailWrapper.js
index 1e4d2a7f2..299c3cc17 100644
--- a/react/features/filmstrip/components/web/ThumbnailWrapper.js
+++ b/react/features/filmstrip/components/web/ThumbnailWrapper.js
@@ -113,27 +113,27 @@ function _mapStateToProps(state, ownProps) {
         const { columns, rows } = gridDimensions;
         const index = (rowIndex * columns) + columnIndex;
         let horizontalOffset;
-        const { iAmRecorder } = state['features/base/config'];
-        const participantsLenght = remoteParticipantsLength + (iAmRecorder ? 0 : 1);
+        const { iAmRecorder, hideLocalThumbnail } = state['features/base/config'];
+        const participantsLength = remoteParticipantsLength + ((iAmRecorder || hideLocalThumbnail) ? 0 : 1);

         if (rowIndex === rows - 1) { // center the last row
             const { width: thumbnailWidth } = thumbnailSize;
-            const partialLastRowParticipantsNumber = participantsLenght % columns;
+            const partialLastRowParticipantsNumber = participantsLength % columns;

             if (partialLastRowParticipantsNumber > 0) {
                 horizontalOffset = Math.floor((columns - partialLastRowParticipantsNumber) * (thumbnailWidth + 4) / 2);
             }
         }

-        if (index > participantsLenght - 1) {
+        if (index > participantsLength - 1) {
             return {};
         }

         // When the thumbnails are reordered, local participant is inserted at index 0.
         const localIndex = enableThumbnailReordering ? 0 : remoteParticipantsLength;
-        const remoteIndex = enableThumbnailReordering && !iAmRecorder ? index - 1 : index;
+        const remoteIndex = enableThumbnailReordering && !(iAmRecorder || hideLocalThumbnail) ? index - 1 : index;

-        if (!iAmRecorder && index === localIndex) {
+        if (!(iAmRecorder || hideLocalThumbnail) && index === localIndex) {
             return {
                 _participantID: 'local',
                 _horizontalOffset: horizontalOffset
diff --git a/react/features/video-layout/functions.js b/react/features/video-layout/functions.js
index 1161dae58..dbf095221 100644
--- a/react/features/video-layout/functions.js
+++ b/react/features/video-layout/functions.js
@@ -103,8 +103,8 @@ export function getTileViewGridDimensions(state: Object) {

     // When in tile view mode, we must discount ourselves (the local participant) because our
     // tile is not visible.
-    const { iAmRecorder } = state['features/base/config'];
-    const numberOfParticipants = getParticipantCountWithFake(state) - (iAmRecorder ? 1 : 0);
+    const { iAmRecorder, hideLocalThumbnail } = state['features/base/config'];
+    const numberOfParticipants = getParticipantCountWithFake(state) - ((iAmRecorder || hideLocalThumbnail) ? 1 : 0);

     const columnsToMaintainASquare = Math.ceil(Math.sqrt(numberOfParticipants));
     const columns = Math.min(columnsToMaintainASquare, maxColumns);

(updated patch to fix layout as well rather than leaving empty space)

saghul commented 2 years ago

Fixed in https://github.com/jitsi/jitsi-meet/pull/10531

murchu27 commented 2 years ago

Awesome, looking forward to trying it out, thanks!

murchu27 commented 2 years ago

Just had a call on the public jitsi instance, and the feature works beautifully! Thanks to all who worked on this 🤎

demitrav commented 2 years ago

There is an unintended bug introduced in this functionality. If you have the "Settings" button hidden from the toolbar, once you "Hide Self View", you can never "un-hide" yourself.

Any suggestions other than having to show the settings menu?

damencho commented 2 years ago

Yep, or disable hide self-view option, as it doesn't make sense when you cannot revert back.

demitrav commented 2 years ago

When I add disableSelfViewSettings: true in the config overwrite, it still shows the option in the kabob menu.

damencho commented 2 years ago

https://github.com/jitsi/jitsi-meet/blob/7bcf7bb6864dbe88446b21b9333891485d33f54e/config.js#L97

damencho commented 2 years ago

O no this is like selecting it ... hum I just tested disableSelfViewSettings and it works for me.

AndreiCercel commented 2 years ago

Well, a colleague hides my thumbnail. And... seems that I don't have any options on my side to revert it. Once he clicked on "hide self-view", I cannot put myself back. There is a coding trick to put myself back?

Thank you :D

damencho commented 2 years ago

Try under Settings -> More.

AndreiCercel commented 2 years ago
Screenshot 2022-05-10 at 17 52 11

I don't have such an option

damencho commented 2 years ago

If you want to workaround it you can open the welcomepage and edit the localstorage. But if you have disabled settings on the deployment, you better disable and hide self-view to avoid this situation.

AndreiCercel commented 2 years ago

yes, but how I can turn my thumbnail back? It's kind of complicated because I have to talk to the devs who are in charge with Jitsi for our company

damencho commented 2 years ago

Edit here and set disableSelfView to false and close the tab, better do it on the welcompage ... and hope it works, as the app can override it during unload ...

image

AndreiCercel commented 2 years ago

Hello and thank you for your suggestion, but it doesn't work. The parameter remains false indeed in that session but nothing changed. Also when I closed the meeting and started again, the parameter turn back to "true".

AndreiCercel commented 2 years ago

A noice friend and dev from our company easily found the solution and works. On Chrome (because I'm using chrome), go to Privacy and security, than click on "See cookies and site data", and on my side (because we use Jitsi in our app) I deleted the "conference.(ourapp).com". And works, the settings are back :

Screenshot 2022-05-11 at 08 52 26

D

sergiomb2 commented 2 years ago

Hi, after click on hide self view , we can not enable (easily) self view again because option disappears , and it is very annoying , and not user friendly

saghul commented 2 years ago

So you have any suggestions on how to improve it? The tile is gone so we had to put the control elsewhere.

sergiomb2 commented 2 years ago

yes , title instead gone should change to "show self view" . The control is always available on settings -> more -> last item , but is hard to find , TBH I just found it after lose my patience and google on internet

saghul commented 2 years ago

That would be too large of a control, specially in tile view.

One of the main points behind the feature was to have more space for other tiles.

sergiomb2 commented 2 years ago

I don't think change "hide self view" to "show self view" will occupy more space

saghul commented 2 years ago

You miss the point. Where would that menu go? There is no tile for the loca participant, which is where the menu was.

b90g commented 2 years ago

So you have any suggestions on how to improve it? The tile is gone so we had to put the control elsewhere.

Yes, anywhere Startup-Screen, Settings, deactivate after hangup, choose your fighter - , but an option to revert that choice would be preferable.

Thank you for your patience. :)

saghul commented 2 years ago

It's already in the settings.

b90g commented 2 years ago

Sorry, the server i'm using doesnt seem to use the current version, will check against meet.jit.si in the future before i start typing (:

w-sky commented 1 year ago

I'm at a loss, my own video has disappeared from all views somehow and I can't activate it again. All the suggestions above don't work, there is no option under "more" in the settings and I can't find any site setting to change this. The only way I can actually see that my own video is working is when I click the camera button.

sergiomb2 commented 1 year ago

image

sergiomb2 commented 1 year ago

IMHO, at least self view option , should be under devices tab

w-sky commented 1 year ago

Sorry I have expressed myself wrong: I do not have a "More" tab at settings. I only have the Devices, Profile and Moderator tabs. Maybe it's an older version on our server?!

CristAdela commented 5 months ago

So you have any suggestions on how to improve it? The tile is gone so we had to put the control elsewhere.

Hello, unfortunatly I used the button "Hide self view" and I can't find any setting to "Unhide self view". How can I see self :) back? PS. I do note have technical, coding background.

Many thanks for your solution.

saghul commented 5 months ago

Open the Settings dialog and there is a way to unhide it in the General section.

CristAdela commented 5 months ago

Open the Settings dialog and there is a way to unhide it in the General section.

manyyyy thants. I find it. I was searching in the video call , never thought to check settings before attenting video call. Higly appreciated your fast reply !!!!

saghul commented 5 months ago

Glad I could help!

bgstack15 commented 5 months ago

My jitsi instance is running docker image jitsi/web:stable-9258 and I was unable to find the checkbox to re-enable self view anywhere in the web app. I checked before joining a call, and during a call. I was able to modify my localstorage key-value pair in developer tools and reload the page to get it to work, though.