The issue
I've created a javascript/jQuery/HTML5 audio player that works very well, save a few exceptions...
- Sometimes the audio loads, but doesn't start playing, even though audio.play() is included in the script
- Sometimes the player returns a duration of 'Infinity:0NaN'
- Sometimes the audio doesn't load all the way, but the player plays anyway (i.e. - a song is 90 sec. long, but only loads, displays the duration of, and plays something like 6 seconds)
I would greatly appreciate any insight that can be offered. Thanks in advance!
You can test the action here: http://goo.gl/Aw2OaY
A few details
I'm dynamically loading each mp3 via a div that stores the mp3's location in a 'data' attribute. When clicked, a script loads a single html5 audio player located at the bottom of my page with the new mp3.
Here is a representation of the loader:
<div class="song-link" data="/song-url.mp3"><p class="song-title"> My Song</p></div>
The player
<!-- audioPlayer.js -->
<audio id="music">
<source id="mp3Source" src="" type="audio/mpeg" />
</audio>
<div id="audioPlayerWrap">
<div id="currentSong"></div>
<div id="audioplayer">
<button id="pButton" class="play"></button>
<div id="timeline">
<div id="playhead"></div>
</div>
<div id="time"></div>
<div id="exitPlayer">X</div>
</div>
</div>
The script
jQuery(document).ready(function() {
//
// Store elements
//
var audioPlayerWrap = document.getElementById('audioPlayerWrap');
var audio = jQuery('audio');
var music = document.getElementById('music');
var mp3Source = jQuery('#mp3Source');
var pButton = document.getElementById('pButton');
var timeline = jQuery('#timeline');
var playhead = document.getElementById('playhead');
var songLink = jQuery('.song-link');
var currentSong = jQuery('#currentSong');
var exitPlayer = jQuery('#exitPlayer');
//
// Event Listeners
//
// Play audio on songLink click
songLink.click(function() {
// Get song URL from data attribute
var songURL = jQuery(this).attr('data');
// Set song URL as audio player source
mp3Source.attr('src', songURL);
// Get song name
var songName = jQuery(this).text();
// Set current song text
currentSong.text('Now playing: ' + '"' + songName + '"');
// Load music
music.load();
//Load meta data and play
music.addEventListener("loadedmetadata", function(event) {
var duration = music.duration;
// Play music
playAudio();
});
// Bind song time to timeline
jQuery('#music').bind('timeupdate', updateTime);
// Bind song end to time
jQuery('#music').bind('ended', songEnded);
// Show audio player
audioPlayerWrap.style.opacity = 1;
});
// Add play/pause function pButton click
pButton.addEventListener('click', function() {
playAudio();
});
// Make Timeline clickable
timeline.click(function(e) {
// Store click position X and timeline width in px
var offsetLeft = jQuery(this).parent().offset().left;
var positionX = (e.pageX - offsetLeft) - 40; // 40 makes up for width of playhead
var timelineWidth = timeline.width();
// Update audio position
var songDuration = Math.floor(music.duration);
var clickPercentage = positionX / timelineWidth;
var clickInSeconds = clickPercentage * songDuration;
music.currentTime = clickInSeconds;
});
// Close audio player on click
exitPlayer.click(function() {
audioPlayerWrap.style.opacity = 0;
// Remove audio player once it's invisible
setTimeout(function() {
audioPlayerWrap.style.display = 'none';
}, 500);
music.pause();
// remove pause, add play
pButton.className = "";
pButton.className = "play";
});
//
// Functions
//
//Play/Pause function
function playAudio() {
// start music
if (music.paused) {
music.play();
// remove play, add pause
pButton.className = "";
pButton.className = "pause";
audioPlayerWrap.style.display = 'block'; // Make sure player can be seen
} else { // pause music
music.pause();
// remove pause, add play
pButton.className = "";
pButton.className = "play";
}
}
// time function
var updateTime = function() {
// Timeline width
timeline.css({'width': '100%'});
var playheadPosition = Math.floor((this.currentTime / this.duration) * 100);
playhead.style.marginLeft = playheadPosition + '%';
// Update timer
time.innerHTML = readableDuration(Math.floor(this.currentTime)) + ' / ' + readableDuration(Math.floor(this.duration));
}
// Convert time to readable format
function readableDuration(seconds) {
sec = Math.floor( seconds );
min = Math.floor( sec / 60 );
min = min >= 10 ? min : '0' + min;
sec = Math.floor( sec % 60 );
sec = sec >= 10 ? sec : '0' + sec;
return min + ':' + sec;
}
// song end function
var songEnded = function() {
if (music.currentTime >= music.duration) {
music.pause();
// remove pause, add play
pButton.className = "";
pButton.className = "play";
music.currentTime = 0;
}
}
});