rtc-web-archive
rtc-web-archive copied to clipboard
Mute/unmute audio will unmute video
Hi,
when I mute/unmute audio on localStream, it will unmute video too. Why? How can I toggle audio without unmuting video?
(Same issue with enable/disable too)
Thanks, Fabio.
could you pls provide your logs and code snippet? usually muting audio should not affect video
Ok, hope I can help. Starting from Agora-Web-Tutorial-1to1-React example, I've simply added:
const [isVideoMuted, setVideoMute] = useState(false);
const [isAudioMuted, setAudioMute] = useState(false);
...
const muteVideo = () => {
if (isVideoMuted) {
setVideoMute(false);
console.log("Enable video");
localStream.unmuteVideo();
} else {
setVideoMute(true);
console.log("Disable video");
localStream.muteVideo();
}
};
const muteAudio = () => {
if (isAudioMuted) {
setAudioMute(false);
console.log("Enable audio");
localStream.unmuteAudio();
} else {
setAudioMute(true);
console.log("Disable audio");
localStream.muteAudio();
}
};
...
<button onClick={muteVideo} disabled={!localStream}>muteVideo</button>
<button onClick={muteAudio} disabled={!localStream}>muteAudio</button>
Then simply run the app and click on the buttons, first on muteVideo, and then on muteAudio. As you can see in the console log, video is muted (log line: 112-113), but when I click on muteAudio (log line: 114-115), video is unmuted (log line: 131)
are you sure you are not calling localStream.enableVideo somewhere else? the console logs indicates you are calling this api somewhere in your code. could you pls set a breakpoint in our minified sdk and check the call stack?
TLDR: I think the problem is in the agora-stream-player
component, not in this one.
Here the stacktrace:
AgoraRTCSDK.min.js:8 debug
Ae.t.enableVideo @ AgoraRTCSDK.min.js:8
push../node_modules/agoran-awe/lib/promisify.js.exports.promisifyStream @ promisify.js:91
apply @ enhance.js:18
_this._handleStreamSideEffects @ index.js:103
componentDidUpdate @ index.js:129
commitLifeCycles @ react-dom.development.js:19835
commitLayoutEffects @ react-dom.development.js:22803
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
commitRootImpl @ react-dom.development.js:22541
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11039
commitRoot @ react-dom.development.js:22381
finishSyncRender @ react-dom.development.js:21807
performSyncWorkOnRoot @ react-dom.development.js:21793
(anonymous) @ react-dom.development.js:11089
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11039
flushSyncCallbackQueueImpl @ react-dom.development.js:11084
flushSyncCallbackQueue @ react-dom.development.js:11072
discreteUpdates$1 @ react-dom.development.js:21893
discreteUpdates @ react-dom.development.js:806
dispatchDiscreteEvent @ react-dom.development.js:4168
AgoraRTCSDK.min.js:2 17:45:09:302 Agora-SDK [WARNING]: [4125375363] Stream.enableVideo is deprecated and will be removed in the future. Use Stream.unmuteVideo instead
to be precise, the issue is here
_this._handleStreamSideEffects @ index.js:103
that is
100 // check video
101 if (xor($prev.videoOn, _this.props.video)) {
102 if ($stream.hasVideo()) {
103 _this.props.video ? $stream.enableVideo() : $stream.disableVideo();
104 }
105 }
of the agora-stream-player
component.
Hey @Fakkio Did you find any soulution for this . even i am getting this issue
Hey @Fakkio Did you find any soulution for this . even i am getting this issue
@samitabhishek I used this worlaround:
const muteAudio = () => {
if (isAudioMuted) {
setIsAudioMute(false);
localStream?.unmuteAudio();
} else {
setIsAudioMute(true);
localStream?.muteAudio();
}
// Since for a bug muting and unmuting the audio re-enables the video,
// we need to deactivate the video in case it should be disabled
if (isVideoMuted) {
setTimeout(() => {
localStream?.muteVideo();
}, 10);
}
};
I Hope it could help
Thanks @Fakkio for workaround. I had the same issue and now I'm using this workaround. Can u tell me why are you using setTimeout? Cuz it gives like a flash of video starting and stopping.
Thanks @Fakkio for workaround. I had the same issue and now I'm using this workaround. Can u tell me why are you using setTimeout? Cuz it gives like a flash of video starting and stopping.
I don't remember exactly, I think I needed to wait the dom to update and then mute the video, otherwise it didn't work for some reason. I didn't have this flash issue though. You can try with a 1ms timeout or even with 0ms.
TL;DR;
Just add autoChange={false} when you are creating the <StreamPlayer>
. Look at the example at the end.
Hehe BOI, I found an actual solution to this problem. So after I wrote above comment I downloaded the source code to see why the error is coming. I found that they are updating the state of audio and video inside componentDidUpdate(). Which is calling 2 function which checks for if state of previous audio is off than turn on it and if state of previous video is off than turn on it and vice versa.
Now the problem is coming when we are updating only video or audio. So if we update state of any one from audio or video. These 2 functions are called. Now that is a big problem of logic here.
Assume your condition here where initially video and audio both on. Now you update just video state from on to off. So far so good. Because after calling both the functions we are not changing anything except video's function.
Ok, so keeping video disabled now we are going to change audio from on to off. Here comes the problem. After calling both functions the function for audio triggers expected result as the previous state of audio was on. So it is gonna try to turn it off. But what we don't want is to call the function for video. Because if it runs than it change state of the video to on. As it is the function which simply set the value to negate value of the original one.
Here is the function which i was talking about and which is called inside componentDidUpdate()
handleStreamSideEffects = () => {
if (!this.props.autoChange) {
return;
}
// deal with side effect
let $prev = this._snapshot;
let $stream: Stream = (this.props.stream: any);
// check video
if (xor($prev.videoOn, this.props.video)) {
if ($stream.hasVideo()) {
this.props.video ? $stream.enableVideo() : $stream.disableVideo();
}
}
// check audio
if (xor($prev.audioOn, this.props.audio)) {
if ($stream.hasAudio()) {
this.props.audio ? $stream.enableAudio() : $stream.disableAudio();
}
}
}
Imagine this both functions inside this function called on every update. So that is our main problem. Now as you can see in the same function there is one flag checking. So if we somehow managed to set that flag we can bypass this whole function call.
So in order to so that i.e, change the value of this.props.autoChange
you need to pass it as an option to <StreamPlayer>
.
Below is an example of doing so
<StreamPlayer stream={localStream} fit="contain" autoChange={false} />
As you can see I made autoChange to false. And bam the things now works as expected.
I have using flutter agora for live streaming app. When I use void _onToggleMute() { setState(() { muted = !muted; }); _engine.muteLocalAudioStream(muted); }
The above code... When I click mute button... It mute both audio and video streaming on the website...When I refresh the Webpage... Then the video stream was continued... I don't want to refresh the Webpage when I mute the audio...the video stream should be continue....
Pls respond as soon as possible...