15

I'm trying to create WebRTC video chat. Now I'm stacked on creating media-tracks buttons (mute video to enable or disable video sending, and mute audio to make the same with audio). Here is my code.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
  <script type="text/javascript" src="http://cdn.peerjs.com/0.3/peer.min.js"></script>
  <script>
  navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

  var myStream;
  var peer = new Peer({key: 'PeerJS key'});
  var setOthersStream = function(stream){
    $('#others-video').prop('src', URL.createObjectURL(stream));
  };

  var setMyStream = function(stream){
    myStream = stream;
    $('#video').prop('src', URL.createObjectURL(stream));

  };

  peer.on('open', function(id){
    $('#peer-id').text(id);
  });

  peer.on('call', function(call){
    call.answer(myStream);
    call.on('stream', setOthersStream);
  });

  $(function(){
    navigator.getUserMedia({audio: true, video: true}, setMyStream, function(){});

    $('#call').on('click', function(){
      var call = peer.call($('#others-peer-id').val(), myStream);
      call.on('stream', setOthersStream);
    });
  });

  peer.on('error', function(e){
    console.log(e.message);
  });

Can anyone guide me please?

tagaism
  • 624
  • 2
  • 7
  • 26

3 Answers3

21

The video and audio tracks in your stream have an enabled attribute you can modify. E.g.:

function muteMic() {
  myStream.getAudioTracks().forEach(track => track.enabled = !track.enabled);
}

function muteCam() {
  myStream.getVideoTracks().forEach(track => track.enabled = !track.enabled);
}
jib
  • 40,579
  • 17
  • 100
  • 158
  • This will stop both video and audio streams. That's not what the question asked. – Nafiu Lawal Jun 13 '21 at 15:56
  • 1
    @NafiuLawal It merely pauses (mutes) them, but yes, I've updated the answer to mute camera and microphone independently. Thanks! – jib Jun 13 '21 at 19:11
  • This approach doesn't work for me, webcam LED is still on – Lev Kostychenko Feb 01 '23 at 20:27
  • @LevKostychenko If you use Firefox this doesn't happen. If you're using Chrome, this is https://crbug.com/642785. – jib Feb 10 '23 at 21:07
  • @jib but how google solved this problem for google meet e.g.& – Lev Kostychenko Feb 11 '23 at 19:06
  • @LevKostychenko I believe they use this answer for microphone, but probably `stop()` the camera track and call `getUserMedia` to get camera again on unmute to avoid the light. This should work in most modern browsers (even Firefox has a 60 minute grace period). I also found Firefox has the same [bug](https://bugzil.la/1694304) on Windows now. – jib Feb 13 '23 at 16:17
  • @jib yep, calling getUserMedia should help in this case but for me even when I call getUserMedia, an interlocutor still gets the previous stream (I decided so, looking at stream id) what causes the error? Maybe you know how to pass the newly created stream into existing peer? I've already asked this question: https://stackoverflow.com/questions/75315537/the-video-stops-and-does-not-resume-after-track-stop – Lev Kostychenko Feb 13 '23 at 16:25
  • @LevKostychenko you can try [replaceTrack](https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpSender/replaceTrack). – jib Feb 14 '23 at 23:09
15

finally I got it work! The first answer for question from this "webrtc video stream stop sharing" guided me to the right direction. I created two new functions to mute video and audio, and bound them to appropriate buttons in html file. And finally it became look like this:

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

var myStream;
var peer = new Peer({key: 'PeerJS key'});

var setOthersStream = function(stream){
  $('#others-video').prop('src', URL.createObjectURL(stream));
};

var setMyStream = function(stream){
  myStream = stream;
  $('#video').prop('src', URL.createObjectURL(stream));
};

peer.on('open', function(id){
  $('#peer-id').text(id);
});

peer.on('call', function(call){
  call.answer(myStream);
  call.on('stream', setOthersStream);
});

$(function(){
  navigator.getUserMedia({audio: true, video: true}, setMyStream, function(){});
  $('#call').on('click', function(){
    var call = peer.call($('#others-peer-id').val(), myStream);
    call.on('stream', setOthersStream);
  });
});

peer.on('error', function(e){
  console.log(e.message);
});

//create button to toggle video
var video_button = document.createElement("video_button");
video_button.appendChild(document.createTextNode("Toggle hold"));

video_button.video_onclick = function(){
  myStream.getVideoTracks()[0].enabled = !(myStream.getVideoTracks()[0].enabled);
}

var audio_button = document.createElement("audio_button");
video_button.appendChild(document.createTextNode("Toggle hold"));

audio_button.audio_onclick = function(){
  myStream.getAudioTracks()[0].enabled = !(myStream.getAudioTracks()[0].enabled);
}

Hope it will help to someone.

Community
  • 1
  • 1
tagaism
  • 624
  • 2
  • 7
  • 26
  • Hello, I am coming here after reading [The evolution of webRTC](https://blog.mozilla.org/webrtc/the-evolution-of-webrtc/) and failing to make it work. While this thing is just simpler, and just works. Can someone please confirm which is the standard way, and which one should i use! Thanks a ton :D – Himanshu Mittal Apr 08 '21 at 17:37
8

Use MediaStreamTrack.enabled.

let mic_switch = true;
let video_switch = true;

function toggleVideo() {
  if(localStream != null && localStream.getVideoTracks().length > 0){
    video_switch = !video_switch;

    localStream.getVideoTracks()[0].enabled = video_switch;
  }

}

function toggleMic() {
  if(localStream != null && localStream.getAudioTracks().length > 0){
    mic_switch = !mic_switch;

    localStream.getAudioTracks()[0].enabled = mic_switch;
  }     

Same for remote stream also.

Sankar Behera
  • 831
  • 10
  • 10