scottschiller / SoundManager2

A JavaScript Sound API supporting MP3, MPEG4 and HTML5 audio + RTMP, providing reliable cross-browser/platform audio control in as little as 12 KB. BSD licensed.
http://www.schillmania.com/projects/soundmanager2/
Other
4.99k stars 768 forks source link

HTML5 bugs when providing initial position through `from` #179

Open 3nvi opened 7 years ago

3nvi commented 7 years ago

Hey, for starters thanks for providing us with such an awesome fully featured audio library. I have been using it for quite a while and i believe there is a long-standing bug that occurs when using HTML5. The bug only appears when you explicitly define a from prop on a certain sound either through the base .setup ( .. ) or through the .createSound( .. ) methods.

What happens is that the SMSound .load and ._setup_html5 get called twice, once with empty configuration and once with the proper configuration inherited. This results into 1 sound being fired instantly (as if the from was the default value) and another one being fire the at from-milliseconds after the first got fired. Eventually you can 2 sounds playing at the same time.

I was able to combat that by commenting-out the extra load in following code, located in line 2048 of the basic soundManager.js file:

....

// HTML5 needs to at least have "canplay" fired before seeking.
if (s.isHTML5 && !s._html5_canplay) {

    // this hasn't been loaded yet. load it first, and then do this again.
     sm2._wD(fN + 'Beginning load for non-zero offset case');

            // s.load({
            //   // note: custom HTML5-only event added for from/to implementation.
            //   _oncanplay: onready
            // });

          }
....

Up until now this seems to have resolved the issue and hasn't caused any problems, but since i'm not fully aware whether it may cause issues under some specific conditions i cannot issue a PR for it. Could you please inform me whether this duplicate-sound is actually a bug or am i simply missing something?

Thanks in advance

Steps to reproduce

Setup soundManager with HTML5:

soundManager.setup({
useHTML5Audio: true 
});

Create a sound with autoLoad, autoPlay & from:

soundManager.createSound({ 
    url: media.file, 
    autoLoad: true,
    autoPlay: true,
    from: 1000
});

Relevant Issues

https://stackoverflow.com/questions/17550685/soundmanager2-autoplay-loads-file-twice

scottschiller commented 7 years ago

Ah-ha, thanks for the detail - indeed, there are some wrinkles with autoLoad and autoPlay also combined with from.

The issue is that to start playback, SM2 must at first attempt to load the sound to determine if it can be played.

The first restriction here is, a sound cannot have its position set until the sound has had its HTML5 canplay fire. If SM2 attempts to set position and "seek" to 1 second in before the sound has established that it can be played, the browser will throw an error.

The second wrinkle here is most mobile devices, and a growing number of desktop browsers which are now starting to block auto-play - i.e., load or play will be blocked unless the call originates immediately from a user gesture like touch or click. For the purpose of this issue, we'll assume you're calling from a gesture and thus the browser isn't going to block you.

I think if you omit autoLoad and autoPlay and call play({ from: 1000}) on the SMSound object, things may work. However, you've likely found a case where the combination of the auto + from properties are causing a double-load of some sort.

3nvi commented 7 years ago

Indeed what you suggested worked perfectly. Cheers and thanks for the quick reply :)

Update: While it worked on my mac, there is still an issue on windows machines