XamarinCommunityToolkit icon indicating copy to clipboard operation
XamarinCommunityToolkit copied to clipboard

[Bug] on iOS 15, CameraView fails to capture audio with video if a MediaElement starts to play after camera.Shutter() is called the first time.

Open jgold6 opened this issue 3 years ago • 0 comments

Description

With a MediaElement and a CameraView on the same page, if you call CameraView.Shutter() to start the video recording, and then call MediaElement.Play(), the video will get recorded with no Audio.

If instead MediaElement.Play() is called and then CameraView.Shutter(), then the video will get recorded with audio, but the MediaElement playback will stop when CameraView.Shutter() is called.

This only seems to happen on iOS 15. I was not able to test on any iOS 13 or 14 devices as I had no access, but this issue does not occur on a device with iOS 12. I suspect Apple changed something in iOS 15 that changed how Audio Sessions with CategoryPLayback are handled as I can resolve this issue by building the XCT with a change to one line when the MediaElementRenderer creates the AudioSession: https://github.com/xamarin/XamarinCommunityToolkit/blob/2.0.0/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/iOS/MediaElementRenderer.ios.cs#L286

var err = audioSession.SetCategory(AVAudioSession.CategoryPlayback);

If the above is changed to: var err = audioSession.SetCategory(AVAudioSession.CategoryPlayAndRecord);

Then it works as expected on iOS 15

Stack Trace

n/a

Link to Reproduction Sample

Testing1234-main.zip

Steps to Reproduce

  1. Load solution and launch app to iOS device running iOS 15 or later
  2. Accept camera and mic permissions
  3. Click "Record"
  4. Talk while recording
  5. Press "Record" again to stop recording
  6. Accept Photo library access permission so Video can get saved to Photos
  7. Go to Photos app and play Video, making sure to UNMUTE the audio (sometimes playback starts with audio muted)

Expected Behavior

Video will have audio

Actual Behavior

Video does not have audio

Basic Information

  • Version with issue: All

  • Last known good version: none that I found.

  • IDE: Visual Studio 2022

  • Platform Target Frameworks:

    • iOS: 15.2
  • Nuget Packages: Xamarin.Forms and the XCT

  • Affected Devices: iOS 15 devices

Workaround

This can be worked around with a custom renderer for the MediaElement by overriding the Play() method:

[assembly: ExportRenderer(typeof(MediaElement), typeof(MyMediaElementRenderer))]
namespace Testing1234.iOS
{
	public class MyMediaElementRenderer : MediaElementRenderer
	{
		IMediaElementController Controller => Element;
		bool isFirstCall = true;
		protected override void Play()
		{
			if (isFirstCall)
            {
				isFirstCall = false;
				var audioSession = AVAudioSession.SharedInstance();
				var err = audioSession.SetCategory(AVAudioSession.CategoryPlayAndRecord);

				if (err != null)
					System.Diagnostics.Debug.WriteLine("MediaElement: Failed to set AVAudioSession Category {0}", err.Code);

				audioSession.SetMode(AVAudioSession.ModeVideoRecording, out err);
				if (err != null)
					System.Diagnostics.Debug.WriteLine("MediaElement: Failed to set AVAudioSession Mode {0}", err.Code);

				err = audioSession.SetActive(true);
				if (err != null)
					System.Diagnostics.Debug.WriteLine("MediaElement: Failed to set AVAudioSession Active {0}", err.Code);

            }
            

			if (avPlayerViewController.Player != null)
			{
				avPlayerViewController.Player.Play();
				Controller.CurrentState = MediaElementState.Playing;
				UpdateSpeed();
			}

			if (Element.KeepScreenOn)
				SetKeepScreenOn(true);
		}

		void UpdateSpeed()
		{
			if (avPlayerViewController.Player != null)
				avPlayerViewController.Player.Rate = (float)Element.Speed;
		}
	}
}

jgold6 avatar Jan 28 '22 19:01 jgold6