Search Unity

Load MP3 files saved locally to AudioClip

Discussion in 'iOS and tvOS' started by Simon75012, Mar 22, 2020.

  1. Simon75012

    Simon75012

    Joined:
    Sep 15, 2016
    Posts:
    79
    Hi, i'm facing a new issue to load a mp3 file locally saved.
    It was working untill now and it sudenly don't work anymore on ios platform.

    ✅If the audio file is not saved locally, i'm downloading from the url, convert it to audio clip and save it locally
    ❌If the audio file exist localy, trying to load it from local path

    Code (CSharp):
    1.  
    2. string url = "https://myurl.com/"+filename+".mp3";
    3. string strLocalPath = Application.persistentDataPath + "/"+filename+".mp3";
    4. if(System.IO.File.Exists(strLocalPath)){
    5.    ///This part is not working since few weeks. Trying to download the localy saved mp3 file and convert it to AudioClip
    6.     WWW www = new WWW("file:///" +strLocalPath); //load the file
    7.     yield return www;
    8.     audioClip=www.GetAudioClip();//Get audio clip
    9. }else{
    10.    //This part is working, downloading the mp3 files from url and convert it to audioclip.
    11.     using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.UNKNOWN))
    12.     {
    13.         yield return uwr.Send();
    14.         if (uwr.isNetworkError){
    15.                Debug.Log(uwr.error);
    16.         } else {
    17.              System.IO.File.WriteAllBytes (strLocalPath, uwr.downloadHandler.data); //save localy the audio file
    18.              audioClip = DownloadHandlerAudioClip.GetContent(uwr);
    19.          }
    20. }
    21.  
    Error :
    -[NSURLResponse allHeaderFields]: unrecognized selector sent to instance 0x283c83000
    2020-03-22 10:40:04.834588+0700 pause[15301:4408918] Uncaught exception: NSInvalidArgumentException: -[NSURLResponse allHeaderFields]: unrecognized selector sent to instance 0x283c83000"

    I also try to load the bytes array then convert it to an AudioClip doing :
    Code (CSharp):
    1. byte[] bytes = System.IO.File.ReadAllBytes(strLocalPath);
    2. WAV wav = new WAV(bytes);
    3.             Debug.Log("Wav loaded");
    4.             AudioClip audioClip = AudioClip.Create("testSound", wav.SampleCount, 1,wav.Frequency, false, false);
    5.             audioClip.SetData(wav.LeftChannel, 0);
    But it doesn't seems to work properly, most of help i found online are working with WAV files. Not sure if that's correct for mp3 files...
    Thanks!
     
    daniherculano and B-Erolskiy like this.
  2. aihodge

    aihodge

    Joined:
    Nov 23, 2014
    Posts:
    163
    You appear to be using the current UnityWebRequestMultimedia.GetAudioClip() API when downloading from a URL, but you're continuing to use the deprecated WWW.GetAudioClip() API when attempting to load a file for the local persistent data path. Try using UnityWebRequestMultimedia.GetAudioClip() there as well. For example, here's a script I wrote which does this exact thing:

    Code (CSharp):
    1.     IEnumerator LoadMusic(string songPath) {
    2.         if(System.IO.File.Exists(songPath)) {
    3.             using (var uwr = UnityWebRequestMultimedia.GetAudioClip("file://" + songPath, AudioType.AUDIOQUEUE))
    4.             {
    5.                 ((DownloadHandlerAudioClip)uwr.downloadHandler).streamAudio = true;
    6.  
    7.                 yield return uwr.SendWebRequest();
    8.  
    9.                 if (uwr.isNetworkError || uwr.isHttpError)
    10.                 {
    11.                     Debug.LogError(uwr.error);
    12.                     yield break;
    13.                 }
    14.  
    15.                 DownloadHandlerAudioClip dlHandler = (DownloadHandlerAudioClip)uwr.downloadHandler;
    16.  
    17.                 if (dlHandler.isDone)
    18.                 {
    19.                     AudioClip audioClip = dlHandler.audioClip;
    20.  
    21.                     if (audioClip != null)
    22.                     {
    23.                         _audioClip = DownloadHandlerAudioClip.GetContent(uwr);
    24.  
    25.                         Debug.Log("Playing song using Audio Source!");
    26.                        
    27.                     }
    28.                     else
    29.                     {
    30.                         Debug.Log("Couldn't find a valid AudioClip :(");
    31.                     }
    32.                 }
    33.                 else
    34.                 {
    35.                     Debug.Log("The download process is not completely finished.");
    36.                 }
    37.             }
    38.         }
    39.         else
    40.         {
    41.             Debug.Log("Unable to locate converted song file.");
    42.         }
    43.     }
     
    yOh_, Ne0mega, mgear and 1 other person like this.
  3. Simon75012

    Simon75012

    Joined:
    Sep 15, 2016
    Posts:
    79
    That worked! Thanks, i tried with UnityWebRequestMultimedia but my script wasn't working properly like your.
    Thanks @aihodge
     
    aihodge likes this.
  4. aihodge

    aihodge

    Joined:
    Nov 23, 2014
    Posts:
    163
    No problem! Glad I could help.
     
  5. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    This doesn't work because it's not correct. Application.persistentDataPath is an absolute path, meaning it includes a slash at the start. By prepending file:/// you end up with 4 slashes after file:, which implies network directory, but isn't in correct format either.
    In short, you need to prepend file:// to absolute paths on UNIX-like systems. The simplest way to do it correctly cross-platform is new System.Uri(path).AbsoluteUri. If you use UnityWebRequest, then you can pass an Uri object to it as an argument (more efficient).