nightlybuilds-net / nightly.xam.audiorecorder

Xamarin Forms audio recorder library
MIT License
8 stars 1 forks source link

Mp4Aar audio recorded by iOS doesn't play on Android and other devices #4

Closed ederjbezerra closed 1 year ago

ederjbezerra commented 3 years ago

Everything seems to work as expected until you need to play the file recorded by iOS on other devices(inverse works properly). I'm using SimpleAudioPlayer to play the recorded audio.

Recording code:

//initializing the plugin using Mp4Aar and Samplig rate of 24k

NightlyRecorderService Rec = new NightlyRecorderService(new RecorderSettings
{
    DroidRecorderSettings = new DroidMp4Aar() { SamplingRate = 24000 },
    IosRecorderSettings = new IosMp4Aar() { SampleRate = 24000 },
}); // have try also with other options and the default config.

// assuming we have mic/storage permissions(I have it on my real project), let's record an audio of 5 secs

Stream audioStream = await Rec.RecordAsync();

//After 5 secs
Rec.Stop();

//save the audio stream to a temp file, then upload it to file server:

string audioTemp = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string localPath = Path.Combine(audioTemp, "audioTemp");

using (FileStream writeStream = new FileStream(localPath, FileMode.CreateNew, FileAccess.Write))
{
    try
    {
        ReadWriteStream(audioStream, writeStream);
    }
    finally
    {
        if (File.Exists(localPath))
            await Task.Run(() => UploadFile("upload.php", localPath));

        writeStream.Dispose();
    }
}

private void ReadWriteStream(Stream readStream, Stream writeStream)
{
    int Length = 256;
    Byte[] buffer = new Byte[Length];
    readStream.Seek(0, SeekOrigin.Begin);
    int bytesRead = readStream.Read(buffer, 0, Length);
    // write the required bytes
    while (bytesRead > 0)
    {
        writeStream.Write(buffer, 0, bytesRead);
        bytesRead = readStream.Read(buffer, 0, Length);
    }
    readStream.Close();
    writeStream.Close();
}

Playing code:

//assuming the upload was a success and we have the url to the file at fileserver: 

try
{
    Stream AudioStream = await Task.Run(() =>
    {
        System.Net.WebRequest webRequest = System.Net.WebRequest.Create("https://....audio.mp4");
        System.Net.WebRequest.DefaultCachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable);
        return webRequest.GetResponse().GetResponseStream();
    });

    if (AudioStream != null)
    {
        Plugin.SimpleAudioPlayer.ISimpleAudioPlayer player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.CreateSimpleAudioPlayer();
        if (await player.Load(AudioStream))
            player.Play();
    }
}
catch (Exception e)
{
    Console.WriteLine("Erro ao tentar carregar audio da internet ===>" + e.Message);
         // #1 we are falling here 
}

Exception/message by player.Load():

#1 Exception message: "Prepare failed.: status=0x1"

Console output:

[MediaPlayer] getDuration_l
[MediaPlayer] Attempt to call getDuration in wrong state: mPlayer=0x70e0901680, mCurrentState=0
[MediaPlayer] message received msg=100, ext1=-38, ext2=0
[MediaPlayer] error (-38, 0)
[MediaPlayer] callback application
[MediaPlayer] back from callback
[MediaPlayer-JNI] getDuration: 0 (msec)

Tested on Android 7, Android 11, iOS 14.4.1

Current behavior:

If recorded by Android -> Plays on Android and iOS

If recorded by iOS -> Only plays on iOS

Two samples of recorded audio by android and ios. Not even quicktime and windows media player are able to play audio recorded by iOS.

markjackmilian commented 3 years ago

thanks for reporting. i will look into it as soon as possible

SandroBenevides commented 3 years ago

@ederjbezerra any solution? I am experiencing similar issue here!

ederjbezerra commented 3 years ago

@ederjbezerra any solution? I am experiencing similar issue here!

Not yet. Mark is the author of this plugin, I think he will bring us a solution in few days.

ederjbezerra commented 3 years ago

@markjackmilian hey mark, do you have prevision of looking into this?

markjackmilian commented 3 years ago

Hi, I hope to solve in two of weeks.

SandroBenevides commented 3 years ago

Ohh that sounds amazing. I'm anxious!

AndewScholes commented 3 years ago

@ederjbezerra @SandroBenevides @markjackmilian have you guys figured this out? I'm experiencing same issue and unfortunately I'm on production already.

ederjbezerra commented 3 years ago

@ederjbezerra @SandroBenevides @markjackmilian have you guys figured this out? I'm experiencing same issue and unfortunately I'm on production already.

Not yet. Still waiting.

ederjbezerra commented 3 years ago

Hey guys, I'm going ahead with this plan: will have nightly recorder for recording on android and audio Plugin.AudioRecorder(wave) for recording on iOS. So I decrease almost double of the problem of audio size but will be just amazing if @markjackmilian be able to solve that, cause I know this is really painful and a frequently problem.

markjackmilian commented 3 years ago

this library allows a configuration close to 100% compared to a native implementation. The problem you are reporting seems related to an incorrect configuration. I invite you to try to create a custom configuration following the wiki here: https://github.com/nightlybuilds-net/nightly.xam.audiorecorder#api

I hope to be able to do some testing this week.

ederjbezerra commented 3 years ago

this library allows a configuration close to 100% compared to a native implementation. The problem you are reporting seems related to an incorrect configuration. I invite you to try to create a custom configuration following the wiki here: https://github.com/nightlybuilds-net/nightly.xam.audiorecorder#api

I hope to be able to do some testing this week.

You mean a config problem of the plugin itself? Cause I already took off my own configs, it's just your original code and as I said, it works at same device but others devices aren't able to play it.

michaelonz commented 1 year ago

Hi Guys, I am using https://www.nuget.org/packages/Xam.Plugin.SimpleAudioRecorder plugin (eg not this plugin) to record on IOS and I have exactly the same issue - which is how i ended up here - i was looking for a replacement plugin.....thought i would mention it here as it seems there are multiple plugins having the same outcome. Not sure if that gives and additional clues but i suspect it could be platform specific.

ederjbezerra commented 1 year ago

Hi Guys, I am using https://www.nuget.org/packages/Xam.Plugin.SimpleAudioRecorder plugin (eg not this plugin) to record on IOS and I have exactly the same issue - which is how i ended up here - i was looking for a replacement plugin.....thought i would mention it here as it seems there are multiple plugins having the same outcome. Not sure if that gives and additional clues but i suspect it could be platform specific.

@michaelonz

I solved this problem by creating an interface for converting the recorded audio and in iOS specific code, I'm doing this:

var asset = AVFoundation.AVAsset.FromUrl(Foundation.NSUrl.FromFilename(recorder.GetAudioFilePath()));
var export = new AVFoundation.AVAssetExportSession(asset, AVFoundation.AVAssetExportSession.PresetAppleM4A);

This way I was able to reproduce the audio in any device.

michaelonz commented 1 year ago

@ederjbezerra Thanks for the pointer - I will give this a try and see if it resolves my issue. :)

michaelonz commented 1 year ago

@ederjbezerra - do you have sample code of how you called this - basically i have a stream object back from the recorder - how do i call this and get a stream back with the corrected formats?

ederjbezerra commented 1 year ago

@ederjbezerra - do you have sample code of how you called this - basically i have a stream object back from the recorder - how do i call this and get a stream back with the corrected formats?

I answered my own old question about this at https://stackoverflow.com/questions/67083930/mp4aar-audio-recorded-by-ios-using-plugin-nightlyrecorderservice-doesnt-play-on/75268983#75268983

I hope it helps you and anyone else who is experiencing this issue.

michaelonz commented 1 year ago

@ederjbezerra I followed your instructions and it resolved my problem - thanks for the great detail - legend :)

ederjbezerra commented 1 year ago

@ederjbezerra I followed your instructions and it resolved my problem - thanks for the great detail - legend :)

You're welcome