Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
1 of 3 tasks
fobos531 opened this issue Jan 11, 2024 · 22 comments · Fixed by #1266
Closed
1 of 3 tasks

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

fobos531 opened this issue Jan 11, 2024 · 22 comments · Fixed by #1266
Labels
bug Something isn't working react-native React Native SDK issues

Comments

@fobos531
Copy link
Contributor

fobos531 commented Jan 11, 2024

Which package/packages do you use?

  • @stream-io/video-react-sdk
  • @stream-io/video-react-native-sdk
  • @stream-io/video-client

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

  • @stream-io/video-react-native-sdk 0.3.7

React Native

  • OS: iOS
  • Device: real iPhone 14 Pro

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

@fobos531 fobos531 added the bug Something isn't working label Jan 11, 2024
@fobos531
Copy link
Contributor Author

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
Copy link
Member

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

@fobos531
Copy link
Contributor Author

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
Copy link
Member

khushal87 commented Jan 16, 2024

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

@fobos531
Copy link
Contributor Author

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
Copy link
Member

khushal87 commented Jan 16, 2024

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
Copy link
Member

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
Copy link
Contributor Author

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
Copy link
Member

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 😄

@oliverlaz oliverlaz added the react-native React Native SDK issues label Jan 19, 2024
santhoshvai added a commit that referenced this issue Feb 12, 2024
## Goal

Adds a parameter to device manager to enable automatically stopping
streams when call is left

fixes #1236
@efstathiosntonas
Copy link

efstathiosntonas commented Apr 25, 2024

@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
Copy link

efstathiosntonas commented Apr 25, 2024

this also happens on dogfood example @oliverlaz ^^

device: iPhone 15 Pro Max on iOS 17.4.1

@efstathiosntonas
Copy link

video demo of dogfood:

VID_20240425_145540_720.mp4

@oliverlaz
Copy link
Member

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

@khushal87
Copy link
Member

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

@efstathiosntonas
Copy link

efstathiosntonas commented Apr 25, 2024

@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
Copy link
Member

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

@efstathiosntonas
Copy link

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

@efstathiosntonas
Copy link

efstathiosntonas commented Apr 25, 2024

@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
Copy link
Member

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
Copy link

@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
Copy link
Member

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

@khushal87
Copy link
Member

This will be fixed in #1345

khushal87 added a commit that referenced this issue May 13, 2024
…ronously (#1345)

This PR focuses on removing the `mediaDevicesInitialState` prop from the
`StreamCall` component to control the initial state of the camera and
mic.

Instead, to voluntarily apply the mute status on the camera and mic, you
can simply call `call.camera.enable()/call.camera.disable()` for the
camera and `call.microphone.enable()/call.microphone.disable()` for the
mic.

Eg:
```
initialAudioMuted={true} would change as call.microphone.disable();
initialCameraMuted={false) would change as call.camera.enable()
```

You can also apply the functions mentioned above on top of our backend
settings. We apply our backend settings through the hook
`useApplyDefaultMediaStreamSettings,` which you can override if you have
a custom use case or use directly if you just want the default backend
settings to be respected.

```
  useEffect(() => {
    call?.camera.disable();
    call?.microphone.disable();
  }, [call]);
```

This PR fixes the issue pointed out in #1236 as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working react-native React Native SDK issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants