0

Is there an event I can listen for, a value I can inspect, or a set of things I can combine, to know when the media has finished loading?

Some background:

My web-based music player plays audio using an html5 Audio object. I would like to pre-load the next track (into a different, hidden Audio object) before the first has finished playing, but after the first track has finished loading.

I want to do this because the backend, which serves the media, has to transcode on the fly and this is slow to start, causing a multi-second gap between tracks. The backend is also slow to transcode so ideally we don't want multiple songs transcoding simultaneously -- it's not ok to start the transcode of track 2 immediately after we start loading track 1.

This question is perhaps similar (if a bit unclear what is being asked) but none of the answers work for my use case.

What I've tried:

  1. Listen for canplaythrough event. This happens as soon as it's predicted that the song can play all the way through, but if we then start the second song transcoding and uploading, it slows the progress of the first one, the prediction fails and playback stalls.

  2. Check periodically for the player's networkState. This goes to NETWORK_IDLE when the song has finished loading, but it also happens long before this if there is network latency or if the player builds up enough of a buffer etc. In testing I found it to happen often within the first few seconds of playing the first song -- much too early for my purpose.

  3. Listen for dataloaded event -- but this means it has loaded some data, not all of it.

  4. Check the player's duration, hoping that this might only be set when the song had loaded. It's not, it's set long before on Firefox (and updates as more data is loaded), and apparently never(!) on Chrome.

  5. Check the player's readyState. This gives essentially the same information as canplay and canplaythrough.

My current almost-good-enough solution:

I listen for "suspend" events. In the handler, I check whether the audio has started playing (currentTime > 0) and, if so, assume it's a good time to start pre-loading the next track. I haven't tested it all that much but it seems like it might work. Still interested in a better solution!

Mark Smith
  • 791
  • 6
  • 21
  • 1
    why not working on track duration ? to set a timed function to run before the end of mp3 with a specified amount like start loading next song before 20sec of track end =) – Burham B. Soliman Jan 30 '21 at 15:05
  • @BurhamB.Soliman: The track duration isn't known immediately -- the track has to be downloaded first. The value shown in the Audio player, and as indicated by `player.duration`, changes as the track downloads. – Mark Smith Jan 30 '21 at 15:15
  • [Track duration](https://www.w3schools.com/tags/av_prop_duration.asp) you can get the current track duration in seconds through JS and set a variable to use math to run effect after track.duration - 20 – Burham B. Soliman Jan 30 '21 at 15:22
  • Please see my previous response and explanation in the question about why this doesn't work. Track duration changes as the track loads - it starts at 0, and the audio loads, it gets longer. Eventually it reaches the full duration. You can see this, using Firefox, if you throttle the bandwidth of the server serving the file, so that it takes, say, 120 seconds to load a 240s-long song. – Mark Smith Jan 30 '21 at 15:29

0 Answers0