miroslavpejic85 / mirotalk

🚀 WebRTC - P2P - Simple, Secure, Fast Real-Time Video Conferences Up to 8k and 60fps, compatible with all browsers and platforms.
https://p2p.mirotalk.com
GNU Affero General Public License v3.0
3.03k stars 558 forks source link

Disabling video does not block access to the webcam #152

Closed l4rm4nd closed 1 year ago

l4rm4nd commented 1 year ago

Describe the bug

If a user decides to disable his video feed of the webcam, the webcam is still active or accessible by MiroTalk. This is a privacy issue, as the webcam should not be accessible as it was disabled by the user as an active choice.

Also the status lights of webcams will continue to blink or breathe, which gives doubts about privacy.

To Reproduce

Steps to reproduce the behavior:

  1. Log into a web meeting with an enabled webcam
  2. Disbable the web cam or video feed by hitting the respective button in the frontend
  3. Although the video feed is not streamed anymore to participants, the webcam is still accessed and enabled in browser by MiroTalk. The status light, if available, blinks or breaths .. indicating a still ongoing access to the webcam.

Expected behavior

If a user stops the webcam video, the webcam should not be accessed or be enabled anymore.

miroslavpejic85 commented 1 year ago

This is because I currently pause the video or audio stream instead of turning it off altogether.

stream.getVideoTracks()[0].enabled = false // or true
stream.getAudioTracks()[0].enabled = false // or true

To close the video-audio stream completely you should use instead

stream.getTracks().forEach((track) => {
    track.stop();
});
HariKrishna-28 commented 1 year ago

Hello! Can I work on this issue??

miroslavpejic85 commented 1 year ago

Hello! Of course, you can work on the issue, Thank you.

ketansaresa commented 1 year ago

@miroslavpejic85 is this issue still un-assigned ?

miroslavpejic85 commented 1 year ago

If my understanding is correct, he was starting with @HariKrishna-28? If that's the case, I'll delegate it to him. Alternatively, you can also consider examining it. Thank you guys!

HariKrishna-28 commented 1 year ago

Hello @miroslavpejic85. I have started working on this issue. I will try to get it done within tomorrow.

miroslavpejic85 commented 1 year ago

Hello @miroslavpejic85. I have started working on this issue. I will try to get it done within tomorrow.

Good! Take all the time you need, there's no rush at all. Thank you so much for the update! 😊

ketansaresa commented 1 year ago

Thanks for the heads up guys. @miroslavpejic85 @HariKrishna-28

miroslavpejic85 commented 1 year ago

Hey @HariKrishna-28,

Thank you for the contribution, it seems like you've found the right method to make the change but it's not enough.

The objective of this task entails managing the behavior of a webcam's indicator light when the "stop camera" button is pressed. The challenge is further complicated by the existence of two distinct video streams within the system. These streams are referred to as initStream, which represents the initial video feed, and localMediaStream, which is never deactivated but can be paused and resumed as needed. One of the primary concerns is that, due to the persistent activation of localMediaStream, the LED indicator light in the room remains illuminated even when video transmission is halted.

To address this issue effectively, a more intricate and nuanced solution is required. The proposed solution should involve a mechanism for synchronizing the webcam's indicator light with the status of the active video streams. When the "stop camera" button is pressed, the indicator light should be turned off, signifying that video transmission has ceased. However, this action should be executed in a way that does not interfere with the availability of localMediaStream for potential reactivation.

In summary, the task demands approach to manage the webcam's indicator light behavior, ensuring it accurately reflects the status of video streaming while maintaining the readiness of localMediaStream for future use without keeping the LED light illuminated unnecessarily.

To Reproduce

Steps to reproduce the behavior:

  1. Log into a web meeting with an enabled webcam
  2. Disbable the web cam or video feed by hitting the respective button in the frontend
  3. Although the video feed is not streamed anymore to participants, the webcam is still accessed and enabled in browser by MiroTalk. The status light, if available, blinks or breaths .. indicating a still ongoing access to the webcam.

A quick fix can be:

/**
 * Handle Video ON - OFF
 * @param {object} e event
 * @param {boolean} init on join room
 * @param {null|boolean} force video off (default null can be true/false)
 */
async function handleVideo(e, init, force = null) {
    if (!useVideo) return;
    // https://developer.mozilla.org/en-US/docs/Web/API/MediaStream/getVideoTracks

    const videoStatus = force !== null ? force : !myVideoStatus;
    const videoClassName = videoStatus ? className.videoOn : className.videoOff;

    force != null
        ? (e.className = videoClassName)
        : (e.target.className = videoClassName);

    videoBtn.className = videoClassName;

    if (init) {
        initVideoBtn.className = videoClassName;
        setTippy(initVideoBtn, videoStatus ? 'Stop the video' : 'Start the video', 'top');
        initVideo.style.display = videoStatus ? 'block' : 'none';
        initVideoSelect.disabled = !videoStatus;
        lS.setInitConfig(lS.MEDIA_TYPE.video, videoStatus);
    }

    if (!videoStatus) {
        // stop the init/local video track (camera led off)
        await stopVideoTracks(initStream);
        await stopVideoTracks(localMediaStream);
    } else {
        if (init) {
            // resume the init video track (camera led on)
            await refreshLocalMedia();
            await changeInitCamera(initVideoSelect.value);
        } else {
            // resume the video track (camera led on)
            await setupLocalMedia();
            await refreshLocalMedia();
        }
    }

    myVideoStatus = videoStatus;

    setMyVideoStatus(videoStatus);
}

/**
 * Stop video track from MediaStream
 * @param {MediaStream} stream
 */
async function stopVideoTracks(stream) {
    if (!stream) return;
    stream.getTracks().forEach((track) => {
        if (track.kind === 'video') track.stop();
    });
}

These proposed changes are worth considering, however, they should undergo thorough testing to ensure they work seamlessly and do not adversely affect other functionalities.

Thank you and have a great day!

HariKrishna-28 commented 1 year ago

Hello! @miroslavpejic85, thank you the suggestions. I will make sure to implement them. And apologies for the delay as I had to take some time to go through the code and the overall flow.