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

Autoloads even if autoLoad = false #184

Open vincentwinkel opened 7 years ago

vincentwinkel commented 7 years ago

Hi, soundManager seems autoloads the last sound created, even if autoLoad = false jsFiddle

Tested with the last version (V2.97a.20170601). This behaviour didn't appear with the old version I used before (V2.97a.20131201)

scottschiller commented 7 years ago

Interesting. This is probably from your use of forceUseGlobalHTML5Audio: true, where SM2 creates and uses only one Audio() instance internally.

SM2 must be assigning the URL in this case to the global Audio() instance, though it shouldn't be. Thanks for the note.

scottschiller commented 7 years ago

Ha. Alright, in the case of using forceUseGlobalHTML5Audio: true on desktop, I can repro this. If I append '?r=' + Math.random() to bust cache every time, I can see Chrome making a request for the second sound on every page load.

It looks like it's down to this line in soundmanager2.js:

 // standard ('none' is also an option.)
 a.preload = 'auto';

If you change that to a.preload = 'none'; or just comment the line out, you should see no preload-type request for the file.

Preload behaviour is controlled by the client, the property is a "suggestion" at best. The client may not auto-load at all (i.e., mobile device), or because bandwidth is limited, etc. Conversely, desktop might happily preload the entire thing.

Quoting from MDN:

preload This enumerated attribute is intended to provide a hint to the browser about what the author thinks will lead to the best user experience. It may have one of the following values: none: indicates that the audio should not be preloaded; metadata: indicates that only audio metadata (e.g. length) is fetched; auto: indicates that the whole audio file could be downloaded, even if the user is not expected to use it; the empty string: synonym of the auto value. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio

I'm fine with removing preload = 'auto' from SM2, to be more conservative by default and use a user-provided autoLoad property if set.

vincentwinkel commented 7 years ago

Sorry to answer late and thanks! In my case, I load a page containing several players (1 player <=> 1 SMSound).

1. With a.preload = 'auto';

The last sound is preloaded:

track-2: loadstart
track-2: durationchange (144065.30000000002)
track-2: loadedmetadata
track-2: loadeddata
track-2: canplay
track-2: onload()
track-2: progress, 100% loaded
track-2: suspend

It is the same result if I remove the line a.preload = 'auto';.

2. With a.preload = 'none';

The last sound is maybe not preloaded but still focused:

track-2: loadstart
track-2: suspend

This behaviour is negligible in some cases but in mine, I can reload the page using Ajax, or load another page (still using Ajax) containing the same player. If this player is played, the side effect is that the sound is stopped. Here is a stack trace using a playlist starting by the player track-1 and finishing by track-2:

# Load page
soundManager.createSound(): track-1
soundManager.createSound(): ... (some players)
soundManager.createSound(): track-2
track-2: loadstart
track-2: suspend

# Play player 1
track-1: play(): Attempting to load
track-1: load (http://.../.mp3?v=0.955885655649306)
track-1: abort
track-1: waiting
track-1: loadstart
track-1: suspend
track-1: durationchange (144065.30000000002)
track-1: loadedmetadata
track-1: loadeddata
track-1: canplay
track-1: canplay: Setting position to 0
track-1: playing ♫
track-1: onload()
track-1: waiting
track-1: progress, 2% loaded
track-1: suspend
track-1: playing ♫
track-1: progress, 6% loaded
track-1: suspend
track-1: progress, 9% loaded
track-1: suspend

# Reload page using Ajax (the player 1 is still played)
soundManager.createSound(): ... (some players except track-1)
track-1: stop()
track-1: setPosition(0)
soundManager.createSound(): ... (some other players)
soundManager.createSound(): track-2
track-2: loadstart
track-2: suspend

But indeed if I set forceUseGlobalHTML5Audio: false it works like a charm. The problem now is that's not compatible with mobiles...

HellYeahOmg commented 4 years ago

Found a similar problem. In mobile version when i destroy SMObject and create a new one it tries to play. ignoreMobileRestrictions doesnt seems to make any effort:

  soundManager.setup({
          ignoreMobileRestrictions: true,
          ...
        })

image