Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Bug AudioClip.Length is incorrect when loading from WebRequest GetAudioClip

Discussion in 'Audio & Video' started by ickydime, Mar 25, 2021.

  1. ickydime

    ickydime

    Joined:
    Nov 20, 2012
    Posts:
    110
    I think this is a potential bug to report, but I want to sanity check that I am not doing anything wrong first.

    I have a bunch of mp3 files in the StreamingAssets folder (trying to keep the build size down for Android).

    When I load them via:


    Code (CSharp):
    1. var webRequest = UnityWebRequestMultimedia.GetAudioClip(fileUrl, AudioType.MPEG);
    2.             yield return webRequest.SendWebRequest();
    The clip length is 2x the actual length.

    When I put them in Resources and load via:
    Code (CSharp):
    1.  var clip = Resources.Load<AudioClip>(fileUrl.Substring(0, fileUrl.Length-4));
    The clip length is correct.

    I've tried AudioType.MPEG and AudioType.UNKNOWN.

    I've tried to sequence these audio clips by either checking clip.length and waiting that amount of time or by checking AudioSource.IsPlaying but even the IsPlaying returns true for the double amount.

    Sooooo. Is this a bug? Should I be using a different method here either for loading or for storing?

    I've attached a zip file of the mp3 in case the compression/etc isn't supported. It comes up as Vorbis under Unity's compression format.
     

    Attached Files:

    achimmihca likes this.
  2. cova8bitdots

    cova8bitdots

    Joined:
    Sep 30, 2019
    Posts:
    8
    I also face same issue.
    I try to download audioclip via UnityWebRequestMultimedia.GetAudioClip
    The result of AudioClip.samples and AudioClip.length are twice than those that I expected.

    It seems that this behaviour is WebRequest Bug.

    Code (CSharp):
    1.  public static async UniTask<AudioClip> GetAudioClipFromWWW(string uri, CancellationToken token = default)
    2.         {
    3.             AudioType type = AudioType.WAV;
    4.             if (uri.Contains(".ogg"))
    5.             {
    6.                 type = AudioType.OGGVORBIS;
    7.             }
    8.             else if (uri.Contains(".mp3"))
    9.             {
    10.                 type = AudioType.MPEG;
    11.             }
    12.  
    13.             using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(uri, type))
    14.             {
    15.                 await www.SendWebRequest();
    16.                 if (www.isNetworkError || www.isHttpError )
    17.                 {
    18.                     Debug.Log(www.error);
    19.                     return null;
    20.                 }
    21.                 else
    22.                 {
    23.                     AudioClip myClip = DownloadHandlerAudioClip.GetContent(www);
    24.                     Debug.Log(
    25.                         $"[Audio] ClipData Fs:{myClip.frequency}[Hz], {myClip.channels}[ch] Sample:{myClip.samples}, Len:{myClip.length}");
    26.                     return myClip;
    27.                 }
    28.             }
    29.          
    30.         }
    This bug can be reproduced Unity2019.4.9f1 and Unity2018.4.22f1
     
  3. UnityMaru

    UnityMaru

    Community Engagement Manager Unity Technologies

    Joined:
    Mar 16, 2016
    Posts:
    1,227
    Hey folks,

    We'd suggest making a bug report on this issue so the team can begin the process of looking into this for you :) Let me know the bug report ID so I can flag internally.

    https://unity3d.com/unity/qa/bug-reporting
     
  4. cova8bitdots

    cova8bitdots

    Joined:
    Sep 30, 2019
    Posts:
    8
  5. gdosu

    gdosu

    Joined:
    Aug 24, 2020
    Posts:
    13
    Same Issue on 2020.3.15f2 and 2020.3.16f1.
     
  6. DaveA_VR

    DaveA_VR

    Joined:
    May 26, 2022
    Posts:
    29
    I'm seeing lenth = zero in 2021.3.0f1
     
  7. FGFFFF00

    FGFFFF00

    Joined:
    Oct 9, 2020
    Posts:
    2
    same in 2020.3.30f1
     
  8. ickydime

    ickydime

    Joined:
    Nov 20, 2012
    Posts:
    110
    This bug is still active and its fun to deal with. I had to go back into the project and update some audio files. Seems as though the updated files are not double length but the old ones are and I'm not sure what is difference as the frequency/channels are the same. Bitrate on the mp3 files are different so that could be something to do with it? Just not sure how to catch that on the unity side as all properties seem to be the same.

    https://issuetracker.unity3d.com/is...imedia-dot-getaudioclip-from-firebase-storage
     
  9. ThendonExe

    ThendonExe

    Joined:
    Feb 27, 2019
    Posts:
    6
    for me in 2021.2.3f1 the length seems to be roughly 1/3rd of the source file
     
  10. achimmihca

    achimmihca

    Joined:
    Feb 13, 2016
    Posts:
    266
    Last edited: Jul 13, 2023
    DaveA_VR likes this.
  11. GleetchDev

    GleetchDev

    Joined:
    Mar 18, 2021
    Posts:
    5
    Just discovered this bug in 2022.3.4f1

    The generated audioclip Lenght and Samples value is always 0 on the WebGL build
     
    Last edited: Jul 14, 2023
  12. achimmihca

    achimmihca

    Joined:
    Feb 13, 2016
    Posts:
    266
    > Will open a new bug report.

    Unity just confirmed the bug (IN-47586). Hopefully they will fix it in a future release.
     
  13. SeventhString

    SeventhString

    Unity Technologies

    Joined:
    Jan 12, 2023
    Posts:
    290
    I recently fixed this bug, it should makes it way soon in the latest and LTS versions.

    It was a fun weird ass codec bug...

    Cheers!
     
    akingdom and achimmihca like this.
  14. Ordinary1107

    Ordinary1107

    Joined:
    May 24, 2020
    Posts:
    1
    You are a savior. I had fixed this manually, but I faced another issue.

    Code (CSharp):
    1. public IEnumerator GetAudioClipUniversal(string fullPath, float percentageOffset, bool isLooping, bool playImmediately)
    2.     {
    3.         using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip($"file://{fullPath}", AudioType.MPEG))
    4.         {
    5.             yield return www.SendWebRequest();
    6.  
    7.             if (www.error == null)
    8.             {
    9.                 UnloadMainSong();
    10.                 song = DownloadHandlerAudioClip.GetContent(www);
    11.                 int channels = song.channels;
    12.                 int frequency = song.frequency;
    13.                 float[] allSamples = new float[song.samples * channels];
    14.                 song.GetData(allSamples, 0);
    15.                 song.UnloadAudioData();
    16.  
    17.                 // Audio clip is downloaded with a lot of leading zeros, we remove them manually...
    18.                 int lastIndex = Array.FindLastIndex(allSamples, b => b != 0);
    19.                 song = AudioClip.Create("song2", (lastIndex + 1) / channels, channels, frequency, false);
    20.                 song.SetData(allSamples[0..lastIndex], 0);

    Turns out creating float[] array = new float[size] creates "Empty fragmented heap space" that does not free up. So every time I load a song, around 100Mb of RAM is lost, after a handful song loads I run out of RAM and app crashes... I'll take a break and wait for the update to roll out.
     
    Last edited: Jul 23, 2023
  15. AlmazAppStudio

    AlmazAppStudio

    Joined:
    Feb 7, 2021
    Posts:
    1
    Were you able to fix it? I came to the conclusion that the problem is in the audio files themselves. But of course, Unity also does not work correctly.
     
  16. SeventhString

    SeventhString

    Unity Technologies

    Joined:
    Jan 12, 2023
    Posts:
    290
    This feels like a garbage collecting issue. Maybe you could TRY to run `GC.Collect()` to clean it up, but I don't think that would be a sustainable solution as this could be a stalling kick in the nuts of your main thread, depending of the amount of work it would have to do then.

    I'm not aware of your loading strategy, but ideally I'd have the mp3 serialized (aka already managed by unity as an asset) and configure it as `Streaming` or maybe even something like this:

    Code (CSharp):
    1. AudioClip myClip = Resources.Load<AudioClip>("MyAudioClip");
    2. myClip.loadType = AudioClipLoadType.Streaming;
    3. myClip.LoadAudioData();
     
  17. cgbrown-mos

    cgbrown-mos

    Joined:
    Oct 17, 2014
    Posts:
    7
    I had a similar issue using MP3 files, but it turns out that it was caused by using a variable bitrate encoding. Re-encoding using a constant bitrate fixed the issue. I know this is mentioned in other threads on this forum, but just posting here in case anyone else finds this thread looking for answers with the same issue I had.
     
  18. jasonkappes656

    jasonkappes656

    Joined:
    Aug 8, 2021
    Posts:
    5
    I managed to find a workaround to this bug. I had the issue where the end of my .mp3 file was being cut off by 'UnityWebRequestMultimedia.GetAudioClip(mp3audioPath, AudioType.MPEG)'

    Using the more primitive method from this forum post worked for me: https://forum.unity.com/threads/how...and-make-it-stay-compressed-in-memory.960910/

    Here's a code example of the solution. In GetMp3Audio I pass it the data for the mp3 then I load it and I can confirm it plays the entire mp3 correctly.

     public void GetMp3Audio(byte[] mp3Audio)
    {
    string filePath = System.IO.Path.Combine(Application.persistentDataPath, "output.mp3");
    System.IO.File.WriteAllBytes(filePath, mp3Audio);
    var path = "file:///" + Application.persistentDataPath + "/output.mp3";
    StartCoroutine(PlayDownloadedAudio(path));
    }

    private IEnumerator PlayDownloadedAudio(string mp3audioPath)
    {
    var dh = new DownloadHandlerAudioClip(mp3audioPath, AudioType.MPEG);
    dh.compressed = true;
    using (UnityWebRequest wr = new UnityWebRequest(mp3audioPath, "GET", dh, null))
    {
    yield return wr.SendWebRequest();
    if (wr.responseCode == 200)
    {
    PlayClip(dh.audioClip);
    }
    else
    {
    Debug.LogError("Error");
    }
    }
    }


    I was stuck on this for hours, so hoping it helps someone :) P.S. If you use Play.HT this is the solution you should use after downloading their audio.

    Using 2022.1.23f1
     
    tony_bean_dong likes this.
  19. akingdom

    akingdom

    Joined:
    Mar 30, 2013
    Posts:
    15
    I'm still seeing this behaviour in 2023.1.3f1. Which version did the fix go live in? Thanks :)
     
  20. SeventhString

    SeventhString

    Unity Technologies

    Joined:
    Jan 12, 2023
    Posts:
    290
    From what I see it has landed in a yet unreleased version (2023.2.xyz) and backports have not started yet. I implore your patience, as it should be available Soon™.
     
  21. akingdom

    akingdom

    Joined:
    Mar 30, 2013
    Posts:
    15
    Thanks for taking time to respond. Much appreciated.

    At present I've hacked a workaround of multipying the length * 0.5f for a list of all my audio files known to have this issue, since I already know what files I'm playing. I mention this in case it helps others.
     
  22. SeventhString

    SeventhString

    Unity Technologies

    Joined:
    Jan 12, 2023
    Posts:
    290
    Be careful with that, as it might not fix the problem every time. The cause problem is that, in the MP3 format, the "bitrate" can vary, even with CBR files (Constant Bit Rate) because of something called "bit reservoir" that allows for increased resolution on transients.

    Now that's the CAUSE of the problem (variable bit rate). Now, since it's a video game engine and that everything has to be lightning fast, shortcuts are used. In this case, the shortcut is that we evaluate the length on the file based on the bitrate and the number of frames of the file and we (used to) only read the first frame's bitrate rather than parsing every frame to have the exact duration of the file.

    The very best workaround is simply to use a different source file format, such as ogg/vorbis.

    Cheers!