GetStream / stream-video-js

GetStream JavaScript Video SDK
https://getstream.io/video/sdk/
Other
70 stars 24 forks source link

Video/audio tracks not properly closed when the stream is unmounted on iOS. #1236

Closed fobos531 closed 9 months ago

fobos531 commented 10 months ago

Which package/packages do you use?

Describe the bug After a stream is ended/unmounted, the video/audio tracks are still active. This can be observed by seeing that the indicator for camera/microphone on the phone is active (yellow/green indicator light). It seems like for a split second the tracks are really stopped since the indicator turns off, but after a second it seems like they become active again.

To Reproduce Steps to reproduce the behavior:

  1. Open Sample app/Dogfooding app (but this happens in my own app as well)
  2. Start a livestream
  3. Leave the livestream
  4. Observe that the camera/microphone active indicators are still present, even after leaving the livestream.

Expected behavior After leaving the livestream, the camera/microphone active indicators should immediately stop.

Screenshots N/A

Version

React Native

Additional context This issue does NOT appear on Android. It seems to only affect iOS.

fobos531 commented 10 months ago

I have found that I have success by using the useMicrophoneState and useCameraState hooks from useCallStateHooks and then disabling the camera/microphone from there. That's great, but shouldn't the call.microphone.disable() and call.camera.disable() work the same way? So, to reiterate, if I disable the camera/mic from the specific hooks, then it seems to work, but if I access it via the call object from useCall, then it doesn't seem to work.

khushal87 commented 10 months ago

Hey @fobos531, thanks for reporting the issue to us. We are looking into it, and we will get back to you soon. 😄

fobos531 commented 10 months ago

Hey @fobos531, thanks for reporting the issue to us. We are looking into it, and we will get back to you soon. 😄

Thank you! I've also received reports from my users that even with the useMicrophoneState and useCameraState hooks the microphone/camera are not always closed.

khushal87 commented 10 months ago

Hey @fobos531, for the viewer side of the livestream I believe you don't want the camera access at all, right?

fobos531 commented 10 months ago

Hey @fobos531, for the viewer I believe you don't want the camera access at all, right?

Yes, but I dont want the microphone either. I tried passing the prop for initial disabling of camera and mic to the stream video component - the camera was properly disabled right from the start, but the microphone was still being turned on even though the initial prop was set to off.

But for me the bigger issue is when I do not pass the initial prop, and then stop/end/leave the call. Thats when the mic and camera remain being accessed.

khushal87 commented 10 months ago

Yes, but I don't want the microphone either. I tried passing the prop for initial disabling of camera and mic to the stream video component - the camera was properly disabled right from the start, but the microphone was still being turned on even though the initial prop was set to off.

For a host, the Microphone is expected to be on(forever). From the Webrtc 118 version, when audio is muted, the track is not stopped/released every time on mute, but the track.enabled is toggled; hence, the mic will always be accessed. Through this mechanism, we achieve speaking while muted or related features. Google Meet and other applications have the same behaviour 😄

For Viewer, you can disable the camera and microphone by passing:

mediaDeviceInitialState={{
        initialAudioEnabled: false,
        initialVideoEnabled: false,
      }}

to StreamCall.

khushal87 commented 10 months ago

But for me the bigger issue is when I do not pass the initial prop, and then stop/end/leave the call. Thats when the mic and camera remain being accessed.

For this, please add after await call.leave().

      await camera.disable();
      await microphone.disable();
fobos531 commented 10 months ago

But for me the bigger issue is when I do not pass the initial prop, and then stop/end/leave the call. Thats when the mic and camera remain being accessed.

For this, please add after await call.leave().

      await camera.disable();
      await microphone.disable();

Hey @khushal87

Thank you for the tip. While this mostly works, I discovered it doesn't work 100% of the time. For example, I cold-start the app, start the call, end the call and both the camera and microphone are properly stopped. Then I start the call again and end it, and the camera is disabled, but microphone still runs. See screenshot (camera, recently means the camera was properly stopped, while the microphone appears to be running): IMG_2659

Then I do that again, and then both are disabled. So it seems to work most of the time, with ocassional deviation from the pattern. Is there anything in GetStream's implementation that would cause this behavior?

khushal87 commented 10 months ago

But for me the bigger issue is when I do not pass the initial prop, and then stop/end/leave the call. Thats when the mic and camera remain being accessed.

For this, please add after await call.leave().

      await camera.disable();
      await microphone.disable();

Hey @khushal87

Thank you for the tip. While this mostly works, I discovered it doesn't work 100% of the time. For example, I cold-start the app, start the call, end the call and both the camera and microphone are properly stopped. Then I start the call again and end it, and the camera is disabled, but microphone still runs. See screenshot (camera, recently means the camera was properly stopped, while the microphone appears to be running): IMG_2659

Then I do that again, and then both are disabled. So it seems to work most of the time, with ocassional deviation from the pattern. Is there anything in GetStream's implementation that would cause this behavior?

Hey @fobos531, we will give it a look for possibilities that might cause this bug. Thanks for reporting 😄

efstathiosntonas commented 7 months ago

@santhoshvai I still encounter this on version 0.6.11, when the video call hangs up the green light (camera) stays on.

Sometimes instead of the RingingCallContent being unmounted on hung up I see just the background on both iOS and Android with no way to close this screen unless I kill the app.

I believe there's a race condition somewhere or there's an error (thus exiting early) preventing the screen to unmount properly.

efstathiosntonas commented 7 months ago

this also happens on dogfood example @oliverlaz ^^

device: iPhone 15 Pro Max on iOS 17.4.1

efstathiosntonas commented 7 months ago

video demo of dogfood:

https://github.com/GetStream/stream-video-js/assets/717975/deb1e6cf-1d58-4562-b4ea-16810ec8f37a

oliverlaz commented 7 months ago

hi @efstathiosntonas, thanks for providing your input. We'll check this and get back to you. cc: @khushal87

khushal87 commented 7 months ago

Hey @efstathiosntonas, do you see this issue everytime on our DF app or it occurs sometimes?

efstathiosntonas commented 7 months ago

@khushal87

steps:

  1. Open apps, no fast refresh
  2. made 10 calls from Android device and hangup on iOS
  3. The green light stayed on. It turns off for a fraction of the second and then turns on again

repeated steps 2 and 3 but I answered the call on iOS, same thing happens.

Did it the other way around, iOS called Android, same thing.

edit: upon answering the call, the green light turns off for a fraction of the second and then turns on.

khushal87 commented 7 months ago

Okay, so after some testing I see this problem for a call from android to iOS but not the other way around.

efstathiosntonas commented 7 months ago

@khushal87 I did not kill the apps before testing the other way around so I guess you're correct.

efstathiosntonas commented 7 months ago

@khushal87 you're right, tested it on my app and it's only Android -> iOS.

When I hang up on Android though I saw an empty screen, for some reason it fails to unmount. In other words, the device being "called" does not unmount the screen on hang up.

khushal87 commented 7 months ago

When I hang up on Android though I saw an empty screen, for some reason it fails to unmount. In other words, the device being "called" does not unmount the screen on hang up.

Not able to triage it on our DF app.

efstathiosntonas commented 7 months ago

@khushal87 hi, is there any progress in this? I just installed "@stream-io/video-react-native-sdk": "0.6.13" and I'm still encountering this.

khushal87 commented 7 months ago

Hey @efstathiosntonas, this is already on our task list. We will try to get back on this soon.

khushal87 commented 6 months ago

This will be fixed in #1345