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

Audio Music not looping in WebGL... tried everything

Discussion in 'Audio & Video' started by IllTemperedTunas, Apr 10, 2020.

  1. IllTemperedTunas

    IllTemperedTunas

    Joined:
    Aug 31, 2012
    Posts:
    608
    I've seen forcing to 44k hurtz might work, i've tried streaming, i've tried all the different settings.

    Does anyone know how to get music tracks to naturally loop in WEBGL builds?
     
  2. IllTemperedTunas

    IllTemperedTunas

    Joined:
    Aug 31, 2012
    Posts:
    608
    I may try a system that checks the music runtime in the future rather than relying on loop settings in the audio. But this is a tad more difficulty in my project as the player can freely move between areas with different music tracks.

    Lots of other things to do in the meantime, hoping this might get fixed in the future though.

    I'm still over the moon that the web build works at all. Still amazed every time I see my game plays in a browser even though it's a bit of a drag there are these sound issues.
     
  3. ron-bohn

    ron-bohn

    Joined:
    Oct 5, 2015
    Posts:
    225
    44khz or 44.1 khz ...just asking because if you're indeed using 44khz you might try 44.1khz. If you want to send me the file, I could take a look at it.

    Also, mp3's cause a delay when looping so just in case, you should use ogg or let unity compress a wav into an ogg.
     
    IllTemperedTunas likes this.
  4. Carrotpie

    Carrotpie

    Joined:
    Sep 25, 2014
    Posts:
    29
    The bug is still present in 2021.1.1f1
     
  5. ron-bohn

    ron-bohn

    Joined:
    Oct 5, 2015
    Posts:
    225
    Are you sure about this? I first looped audio way back in 5.3 (pre official unity webgl release). What kind of file are you using? Does your web host allow streaming? Many basic web hosting packages specifically do not allow hosting video or audio streaming. If the audio is not cached in the browser and you are trying to loop audio, then that's a massive amount of bandwidth.

    That being said if all of the above are non-issues, there are so many work-arounds, but again if it's not caching in the browser, then you are going to eat up so much bandwidth that you're gonna have bigger problems, particularly at any kind of scale beyond a few users.
     
  6. Carrotpie

    Carrotpie

    Joined:
    Sep 25, 2014
    Posts:
    29
    Well I went on and built my own workaround by checking when the audio ends and playing audio with PlayScheduled.
    That said, the bug is still a bug. If there's a loop check mark, it should do as per what docs say.

    Did not check if it's caching or not. Any method you could propose to check that? The audio plays as it should, the problem is only with looping. Loop problems persist in localhost, no access restrictions to audio file types. If it's important, audio files are MP3...
     
  7. ron-bohn

    ron-bohn

    Joined:
    Oct 5, 2015
    Posts:
    225
    mp3's are notorious for NOT looping cleanly... Unless you are fading in your loop at the beginning and fading it out at the end, don't use mp3 because there will be a slight delay at the beginning whether you are on WebGL or any platform to my knowledge. You should use ogg instead (this is the default of what Unity converts .wav files to for compression). As someone who makes a lot of audio loops, steer clear of mp3.

    If your web host has access to a bandwidth monitoring tool, you can see if your loop is re-downloading the audio each time it plays. You could also check in your browser itself and/or your temp files. Might need to clear it first. If you can open on a mobile device, you could also see the affect on your mobile data if you have enough available...A few ways to check that.

    I'll need to download the exact version of Unity you are using and test it on a live website and see what the deal is. Rest assured, I will not be using mp3 though :) Just need to do that before submitting a formal bug report for this.
     
  8. UnityMaru

    UnityMaru

    Community Engagement Manager Unity Technologies

    Joined:
    Mar 16, 2016
    Posts:
    1,227
    Appreciate your inputs on this. A formal bug report would be much appreciated on this so if you do get round to submitting one @ron-bohn, let me know the ID for it so I can flag with the team.
     
  9. ron-bohn

    ron-bohn

    Joined:
    Oct 5, 2015
    Posts:
    225
    @UnityMaru 2019 LTS works fine, tested live on the web and no bug. https://www.bohnstudios.com/3D/unity/WebGLaudio/ 2019 LTS webGL is awesome, it's come a long way! Very fast. Highly recommended!

    I did the exact same process on 2021.1.2f1 and the scene wouldn't even load. https://www.bohnstudios.com/3D/unity/WebGLaudio/2021-1-2f1/

    I get this error: "Unable to parse Build/testbuilds.framework.js.gz! This can happen if build compression was enabled but web server hosting the content was misconfigured to not serve the file with HTTP Response Header "Content-Encoding: gzip" present. Check browser Console and Devtools Network tab to debug."

    I used the exact same process as in Unity 2019.4 LTS... So yeah, I didn't even get far enough to see if the looping situation on the newest Unity version 2021.1.2f1 . I also test just a blank project and got the same thing.

    Note: I might not leave these links up forever, but just to be clear... the first link works and the second one does not.
     
  10. kevinMantao

    kevinMantao

    Joined:
    Dec 7, 2020
    Posts:
    1
    Hi CarrotPie, would you be ok sharing your script here ? It seems like a great workaround for this problem.
     
  11. Carrotpie

    Carrotpie

    Joined:
    Sep 25, 2014
    Posts:
    29
    There is an exactly same bug reported already. And it's closed for some reason, though clearly it is still there, people have commented under it that it is not fixed as it sais that it is.
    https://issuetracker.unity3d.com/issues/playschedule-does-not-loop-audio-in-webgl-build

    Well I went on and converted everything to ogg just to be sure I tried, though all of the previous problems still persist.

    Sure. Might be too late, but here you go.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Audio;
    5.  
    6. public class SoundTrackCoordinator : Singleton<SoundTrackCoordinator> {
    7.  
    8.     public AudioClip menuSoundTrack;
    9.     public AudioClip scoreSoundTrack;
    10.     public List<AudioClip> matchSoundTracks;
    11.     List<AudioClip> randomizedList;
    12.     int matchTrackIndex;
    13.     int flip;
    14.     float loadDelay = 2f;
    15.     public float targetPitchDown = 0.7f;
    16.     public float targetVolumeDown = 0.05f;
    17.     float normalVolume = 0.4f;
    18.     public AudioSource[] players;
    19.     int playCount = 1;
    20.  
    21.     void Awake() {
    22.         normalVolume = Instance.players[0].volume;
    23.         loadDelay = ConstantsBucket.PlayfieldFadeTime;
    24.         randomizedList = matchSoundTracks.Shuffle();
    25.     }
    26.     public static void PlayMenu() {
    27.         ScheduleAndPlay(Instance.menuSoundTrack, 0.5f);
    28.     }
    29.     public static void PlayScores() {
    30.         Instance.ScheduledPlay(Instance.scoreSoundTrack, 0.2f);
    31.     }
    32.     public static void PlayNext() {
    33.         ScheduleAndPlay(Instance.randomizedList[Instance.matchTrackIndex]);
    34.         Instance.matchTrackIndex++;
    35.         if (Instance.matchTrackIndex >= Instance.randomizedList.Count) {
    36.             Instance.matchTrackIndex = 0;
    37.         }
    38.     }
    39.  
    40.     static void ScheduleAndPlay(AudioClip clip) {
    41.         ScheduleAndPlay(clip, Instance.loadDelay);
    42.     }
    43.     static void ScheduleAndPlay(AudioClip clip, float delayTime) {
    44.         Instance.playCount++;
    45.         Instance.flip = 1 - Instance.flip;
    46.         Instance.ScheduledPlay(clip, delayTime);
    47.         Instance.StartCoroutine(Instance.LoopPlayer(clip, delayTime));
    48.         //Debug.Log("ScheduleAndPlay:" + clip + "  time:" + AudioSettings.dspTime + delayTime + "  flip:" + (1 - Instance.flip));
    49.         Instance.players[1 - Instance.flip].SetScheduledEndTime(AudioSettings.dspTime + delayTime);
    50.         Instance.StartToneDown(Instance.players[1 - Instance.flip], delayTime);
    51.     }
    52.     public void ScheduledPlay(AudioClip clip, float delayTime) {
    53.         players[Instance.flip].clip = clip;
    54.         players[Instance.flip].PlayScheduled(AudioSettings.dspTime + delayTime);
    55.         players[Instance.flip].pitch = 1f;
    56.         players[Instance.flip].volume = normalVolume;
    57.     }
    58.     IEnumerator LoopPlayer(AudioClip clip, float delayTime) {
    59.         int initialCount = playCount;
    60.         float length = (clip.samples * 1f) / clip.frequency;
    61.         yield return new WaitForSecondsRealtime(length + delayTime - 0.08f);
    62.         if (initialCount == playCount) {
    63.             ScheduledPlay(clip, 0);
    64.             StartCoroutine(LoopPlayer(clip, 0));
    65.         }
    66.     }
    67.     public void StartToneDown(AudioSource source, float timeToDie) {
    68.         StartCoroutine(ToneDown(source, timeToDie));
    69.     }
    70.     IEnumerator ToneDown(AudioSource source, float timeToDie) {
    71.         if (source.isPlaying) {
    72.             float currenVolume = source.volume;
    73.             float currenPitch = source.pitch;
    74.             float timeCount = 0;
    75.             while (timeToDie > timeCount) {
    76.                 timeCount += Time.deltaTime;
    77.                 float timePart = timeCount / timeToDie;
    78.                 source.pitch = Mathf.Lerp(currenPitch, targetPitchDown, timePart);
    79.                 source.volume = Mathf.Lerp(currenVolume, targetVolumeDown, timePart);
    80.                 yield return null;
    81.             }
    82.         }
    83.         yield return null;
    84.     }
    85. }
     
    IllTemperedTunas likes this.