Contents
Introduction
Moth Player is a vanilla JavaScript library to implement custom HTML5 audio players in websites.
Note: In this text, Moth Player is also referred to as "MP" or "the library".
Features
- Free: gratis and open source.
- No dependencies.
- Playlist.
- Multiple players on a single page.
- Controls (all optional): Play/Pause, Stop, Next, Previous, Repeat (playlist), Shuffle, Volume Up/Down buttons, Volume Slider, Mute/Unmute, Progress & Seek bar.
- Information display (all optional): artist (global), artist (per track), album, track number, track title, load and play state, track progression, track current/remaining time, track duration, volume level, image (global), image (per track) and lyrics.
- Custom appearance via HTML & CSS; design flexibility.
- Lightweight: around 9 kB minimized.
Limitations
- Audio format support is browser-dependent.
- Playlist definition required, even for a single track.
- The display of track information must be implemented manually.
Requirements
To deploy and configure Moth Player, we should feel comfortable working with HTML and CSS. JavaScript knowledge is not required but it makes the explanation about the script easier to follow.
How to set up
There is a plain demo (also included in the download package) that presents two players on a single webpage. One simulates a music album and the other features a mixed playlist. Between the two they cover most of the library's capabilities.
There are also custom skins, which further display styling possibilities. These are up for grabs; use and adapt them in any way you see fit.
Bare-bones approach
To start from scratch, we need an audio file, the JavaScript library —which, irrespective of the version number, should be something like moth.player.1.0.0.min.js
— and an HTML file.
For this minimal example, we place all the files in the same folder. We load the library from the head of our HTML:
<head>
...
<script src="moth.player.1.0.0.min.js"></script>
...
</head>
The HTML must include a custom script with the playlist and track information, to be placed after the library inclusion, either in the head or the body of the document. There will be more on the script later, but here is the minimum that it needs to run. Assuming our audio file is hm01.mp3
:
<script>
mp_plist.audio01 = {
tracks: [{file: 'hm01.mp3'}]
};
</script>
The HTML elements must have specific classes so that Moth Player can put everything where it belongs. We'll describe those in a moment; for now, let's just include the essential elements inside the <body>
:
<div class="moth-player">
<audio id="audio01" class="mp-audio">
Your browser doesn't seem to support HTML5 audio.
</audio>
<ul class="mp-playlist"></ul>
</div>
That's it. If nothing went wrong, when we open the HTML file in the browser we should see a lonely list item:
We can click on it to play and pause the associated audio file. You can find this minimal setup here.
HTML
Moth Player reads data from the custom script (covered below) and injects it in a set of HTML elements with mp-
prefixed classes —except for the parent element, with class moth-player
to drive the point home.
Note: The demo and the skins include unprefixed classes. They help to structure the page and are ignored by MP.
To instance the player we must define the player's <div>
and its associated audio element:
<div class="moth-player">
<audio id="audio01" class="mp-audio">
Your browser doesn't support HTML5 audio.
</audio>
<!-- ... player elements go here... -->
</div>
The player (container element) should be of moth-player
class and the audio element must have a unique id of your choice —in this case, audio01
— and a class mp-audio
.
To include a second player in the same page, we only need to change the new audio element's id to another unique name —say, audio02
:
<div class="moth-player">
<audio id="audio01" class="mp-audio">
Your browser doesn't support HTML5 audio.
</audio>
<!-- ... player elements go here... -->
</div>
<div class="moth-player">
<audio id="audio02" class="audio-element">
Your browser doesn't support HTML5 audio.
</audio>
<!-- ... player elements go here... -->
</div>
Follow this pattern to have as many players as you need in a single webpage.
Note: Only one player will emit sound at any given time, as the library automatically pauses the others.
The audio element's id can be anything, but it's a value to remember: we'll have to use it in the script.
The player's elements (playlist, controls, data) must be children of the parent div moth-player
, and can be created in any order according to our design needs.
Controls
All of the player's controls are optional. They should be HTML elements with a certain class, as shown in this table:
Control | Class |
---|---|
Play | mp-play |
Pause | mp-pause |
Stop | mp-stop |
Previous | mp-prev |
Next | mp-next |
Mute | mp-mute |
Unmute | mp-unmute |
Volume Max | mp-vol-max |
Volume Up (10%) | mp-vol-up |
Volume Down (10%) | mp-vol-down |
Repeat | mp-loop |
Shuffle | mp-shuffle |
Play and Pause need to be defined separately; Moth Player will merge them into one toggle button. The same goes for Mute/Unmute.
Here's an example setup with text buttons:
<div class="controls">
<button class="mp-play">play</button>
<button class="mp-pause">pause</button>
<button class="mp-prev">previous</button>
<button class="mp-next">next</button>
<button class="mp-mute">mute</button>
<button class="mp-unmute">unmute</button>
</div>
Instead of text labels, we could use images (not provided by MP) to render media icons:
<div class="controls">
<button class="mp-play">
<img src="img/play.png" alt="play button" />
</button>
...
</div>
Note: We can choose any HTML element that makes sense for our player design: <button>, <div>, <span>, <li>
... Moth Player only cares about their class.
We can also add progress/seek and volume bars. If so, they must have a container element and a bar element:
Control | Class |
---|---|
Prog/Seek container | mp-seek-cnt |
Prog/Seek bar | mp-seek-bar |
Volume container | mp-vol-cnt |
Volume bar | mp-vol-bar |
-bar
elements must be children of -cnt
elements.
<div class="mp-seek-cnt">
<div class="mp-seek-bar"></div>
</div>
...
<div class="mp-vol-cnt">
<div class="mp-vol-bar"></div>
</div>
Unlike <button>
tags, browsers won't render the bars without CSS rules. A crude example:
.mp-seek-cnt,
.mp-vol-cnt {
border: 1px solid #999;
cursor: pointer;
margin-bottom: 1rem;
}
.mp-seek-bar,
.mp-vol-bar {
height: 1rem;
background-color: #999;
}
Aside: Beware of mobile
Mobile devices may disregard volume controls on websites, leaving your volume-related controls rendered but useless.
By default, Moth Player uses a platform sniffer to remove all the volume controls when running on a mobile device. We can override this behavior by adding the property mobile_volume: true
to the custom script (see Script.)
When laying out the player, it's wise to place all volume-related controls in places where the design won't break if they vanish. By "volume-related", understand the elements with the following classes:
mp-mute
mp-unmute
mp-vol-max
mp-vol-up
mp-vol-down
mp-vol-cnt
mp-vol-bar
mp-vol-text
mp-vol-number
Data
Moth Player can display some information about the media if it's provided in the custom script. To show a particular bit, we must include the corresponding HTML element with a predefined class. All are optional.
Info type | Class |
---|---|
Album title | mp-album |
Artist (global) | mp-artist |
Artist (single track) | mp-track-artist |
Track number | mp-track-number |
Track title | mp-track-title |
Text while paused [1] | mp-text-pause |
Text while playing [2] | mp-text-play |
Track current/remaining time [3] | mp-track-time |
Track duration | mp-track-length |
Track progress (%) | mp-track-percent |
Volume number [4] | mp-vol-number |
Volume label [5] | mp-vol-text |
- Custom message to be displayed when the media is paused. Forms a "toggle" message with "Text while playing."
- Custom message to be dislpayed when the media is playing. Forms a "toggle" message with "Text while paused."
- Mouse click toggles between current and remaining track time (more in No Pointer?)
- Volume's current value shown as a number (more in Script.)
- Custom label for the volume value (e.g, "Volume: ".)
Typically, we include the elements that we wish to display devoid of content, as the library will fill them for us:
<div class="mp-album"></div>
<div class="mp-artist"></div>
...
However, "Text while paused", "Text while playing" and "Volume label" require custom content or nothing will show. For example:
<span class="mp-text-pause">Track selected: </span>
<span class="mp-text-play">Now playing: </span>
<span class="mp-track-title"></span>
Or (from the demo):
<div class="volume-info">
<div class="mp-vol-text">Volume</div>
<div class="mp-vol-number"></div>
</div>
Images
Moth Player can display a poster (an album cover) and a different image for each selected track. Normally we would have one or the other, but nothing stops us from rendering both. Just include the element with the appropriate class, mp-poster
for global, mp-track-image
for single tracks.
<div class="mp-poster"></div>
...
<div class="mp-track-image"></div>
Lyrics
In order to include songs' lyrics, we write a parent element with class mp-lyrics
and as many child elements as lyrics we wish to transcribe, each with its own class:
<div class="mp-lyrics">
<div class="lyr01">
She loves you, yeah, yeah, yeah...
</div>
<div class="lyr02">
I can't get no satisfaction...
</div>
<div class="lyr03">
Sittin' in the mornin' sun...
</div>
</div>
Moth Player will display the lyrics of the currently selected track and hide the rest.
Classes for each of the lyrics elements ("lyr01", "lyr02"…) don't need to follow the mp-
prefix convention; they can be named arbitrarily, but, once again, we should be aware of our choice; we need to reference them in the script.
Playlist
The playlist is required for the player to work. The HTML is simple; just define an empty (ordered or unordered) list element with class mp-playlist
:
<ul class="mp-playlist">
</ul>
As far as the HTML is concerned, you're done.
Each list item features one track. Users can click on them to play or pause the associated media. Each list item is programmatically generated from the track information that we provide in our custom script —see the next section, but here's a taste:
...
tracks: [
{
title: 'Hollow Monkey', // optional but recommended
artist: 'Space Weirdo', // optional
extra: 'Pop/Electronica', // optional
file: 'hm01.mp3',
},
],
...
If provided, the library will render for each track the track title, the track artist and a general field called "extra" where we can add any piece of arbitrary information. All these are optional but, unless we plan to hide the playlist, we should at least include the title.
Note: "file" is the only mandatory property, as it points Moth Player to the audio file's name. More on this later.
Since Moth Player generates the list's HTML at runtime, we normally can't see it unless we use the browser's devtools (the demo has a button labeled "computed source" that shows it as well.) Here's what a couple of compiled list elements might look like:
<ul class="mp-playlist">
<li class="mp-plist-current">
<span class="mp-plist-title">Hollow Monkey</span>
<span class="mp-plist-artist">Space Weirdo</span>
<span class="mp-plist-extra">Pop/Electronica</span>
</li>
<li>
<span class="mp-plist-title">The Exact Problem</span>
<span class="mp-plist-artist">T.e.P.</span>
<span class="mp-plist-extra">Rock</span>
</li>
...
</ul>
The first <li>
element has the class mp-plist-current
, marking it as the active track, either playing or ready to go. Then it shows the track's title, artist and extra info (in the example, extra
is used to show the track's genre.)
Remember: everything inside the ul
element is created by the library; we don't have to write any of it.
To give us design flexibility, Moth Player creates specific classes for playlist data, in order to differentiate them from the classes that we use in out custom HTML.
Info type | Playlist class | HTML class |
---|---|---|
Track number | mp-plist-number | mp-track-number |
Track title | mp-plist-title | mp-track-title |
Track artist | mp-plist-artist | mp-track-artist |
Extra info | mp-plist-extra | mp-track-extra |
Track duration | mp-plist-length | mp-track-length |
Thus, we can choose via CSS to hide one item in the playlist but render it somewhere else on the page (or vice-versa.)
The class mp-plist-number
for playlist numbers is generated automatically if we define a special property outside the tracks
array, like so:
...
plist_numbers: true,
tracks: [
{
title: 'Hollow Monkey',
artist: 'Space Weirdo',
extra: 'Pop/Electronica',
file: 'hm01.mp3',
},
], ...
This provides an easy way to render the numbers and style them with CSS, as the library inserts a <span>
element with class mp-plist-number
inside the playlist's item:
<ul class="mp-playlist">
<li class="mp-plist-current">
<span class="mp-plist-number">1</span>
<span class="mp-plist-title">Hollow Monkey</span>
<span class="mp-plist-artist">Space Weirdo</span>
<span class="mp-plist-extra">Pop/Electronica</span>
</li>
...
</ul>
However, we may prefer to use an ordered list, which renders by default natural numbers followed by a point:
In a similar way, the class mp-plist-length
is generated by the library if we define a plist_duration
property:
...
plist_duration: true,
tracks: [
{
title: 'Hollow Monkey',
artist: 'Space Weirdo',
extra: 'Pop/Electronica',
file: 'hm01.mp3',
},
], ...
Moth Player gets the tracks' duration when checking the viability of the audio files. If we include the plist_duration
property, MP inserts that information into the playlist:
<ul class="mp-playlist">
<li class="mp-plist-current">
<span class="mp-plist-title">Hollow Monkey</span>
<span class="mp-plist-artist">Space Weirdo</span>
<span class="mp-plist-extra">Pop/Electronica</span>
<span class="mp-plist-length">0:29</span>
</li>
...
</ul>
If, for some reason, we don't wish to display the playlist at all, the easiest way would be to obliterate it with CSS:
.mp-playlist {
display: none;
}
But remember, even if we don't want it to show, we must write the list in the HTML and the tracks
property in the script. Moth Player relies on the playlist object to acquire the tracks' information and feed it to the audio element.
Script
Introduction
We must provide a JavaScript object (the playlist object) with information about our audio tracks and the data that we wish to display in the player or the playlist.
Note: Technically, an empty mp_plist
object is created by the library. Here we're adding properties to it.
We place it inside a <script>
element in the HTML file, that needs to come —either in the head or the body of the document— after the library inclusion.
We populate the playlist object with properties that Moth Player will manipulate and write into our custom HTML code. So, if we don't need the player to display, e.g., the album title, there's no need to define either an album
property in the script or an element with class mp-album
in the HTML.
However, as we've seen in our Bare-bones setup, there are some required properties; if they're missing, MP won't work.
Testing Audio
Any prudent HTML-based media player will check if the browser can find and play all the provided audio files.
Accepted file types vary between browsers and their OS implementations. We might have smooth sailing on a Windows PC using Chrome just to crash and sink on an iOS hand-held gizmo using Safari.
A commonly accepted solution is to load each file into an <audio>
element and report an error if something's amiss. However, this process may take time, especially with long playlists, and the frozen message "Loading player..." while the seconds tick away might erode the user's patience.
Moth Player errs on the side of caution and checks all the tracks by default —or, more accurately, all the tracks that it needs to build a playlist.
Let's see how that goes.
Free Mode vs. Supplied Mode
When the browser loads Moth Player, the library reads the custom script and checks if it can find and load the listed audio files. We can choose one of two modes of operation:
- Supplied Mode (Recommended): Define a
supplied
property with the file types of your audio files:
This mode assumes that, for each of the declared types, we have a complete set of the playlist's audio files. In our example, we indicate that all the tracks are provided in mp3 and ogg files.supplied: 'mp3, ogg',
- Free Mode: Without a
supplied
property, Moth Player is in Free Mode; it lets you make a mixed-format playlist in which each track can be from a different file type.
In Supplied Mode the number of accepted formats is limited but safer in terms of probable browser compatibility. These are: wav, flac, mp3, ogg, oga, opus, aac, mp4, webm
.
In Supplied Mode we don't need to write the file extensions when we list the audio files in the script (see below) so there's less typing and slightly cleaner code.
In Free Mode we can try to use any audio type to make a mixed-format playlist, but less common formats might be unsupported by some browsers. Additionally, we need to write file extensions for each file.
Supplied Mode takes a couple of extra steps to check the suitability of a format, either throwing an error or logging an event for every step (see Troubleshooting.) This gives us better information in case something happens:
free mode supplied mode | ↓ | are supplied formats | supported by Moth Player? | ↓ | does the browser think it | can play the media types? | ↓ ------------> can audio element play audio files? ↓ create playlist, display player
If a file type fails in Supplied Mode, Moth Player will try another one until it succeeds or runs out of formats to try. The library picks the first format to pass the test and, at that point, (a) stops checking files, (b) ignores the rest of the supplied
types and (c) renders the player.
In Free Mode, chances are that a few tracks will fail in some environments —and we probably won't be there to see it; in early versions of Moth Player, failing to load a single file threw a fatal error and halted execution. Now the library simply removes the track from the playlist, in the hopes that at least a few files will make the cut and the user can listen to something.
List of properties
Note: If you're new to JavaScript, be advised that the script's punctuation (commas, quotation marks, colons, braces, etc.) must be exact.
Let's suppose that we have a playlist with three songs, all part of the same album by the same artist. We have an album cover but also single illustrations for each track. The script (this is a daunting, unrealistic property-stuffed example) might look something like this:
<script>
mp_plist.audio01 = {
album: 'Cosmonaut',
artist: 'Space Weirdo',
poster: 'cosmonaut_cover.png',
media_path: 'media/',
img_path: 'img/',
mobile_volume: true,
volume: 0.5,
volume_format: '2, 2',
plist_duration: true,
plist_numbers: true,
leading_zero: true,
supplied: 'mp3, ogg', // if not present, MP enters Free Mode
tracks: [
{
title: 'Channel 9',
img: 'channel9.png',
caption: 'When TV ruined your life.',
lyrics: 'lyrics01',
extra: 'Pop/Rock',
file: 'Channel 9', // if Free Mode, add extension.
}, {
title: 'She Saw Me',
img: 'she_saw_me.png',
caption: 'Whom did she see?',
lyrics: 'lyrics02',
extra: 'Instrumental',
file: 'She Saw Me', // if Free Mode, add extension.
}, {
title: 'One Small Step',
img: 'one_small_step.png',
caption: 'And look at mankind now.',
lyrics: 'lyrics03',
extra: 'Scientific Rock',
file: 'One Small Step', // if Free Mode, add extension.
},
],
};
</script>
Firstly, we have declared the property mp_plist.audio01
, which tells Moth Player that (1) this is a playlist, and (2) it belongs to the audio element with id="audio01"
. If we instance a second player, we have to create another property and point it to the id of the second audio element: supposing the new audio element has id="audio02"
, the reference in the object would be mp_plist.audio02
.
It doesn't matter how we "id" the audio elements, as long as the id matches the property in the playlist object.
So, whatever's in here (HTML):
<audio id="myCoolId"... >
… must be reflected here (script property):
mp_plist.myCoolId = {
...
};
Secondly, we have a list of properties that relate to this particular playlist. Some are global and some are specific for each track. All track-related properties are contained inside the tracks
property.
album: 'title'
. Optional. The album's title. It renders into an HTML element with class mp-album
(if present.)
artist: 'name'
. Optional. The artist's name for an album or a same-artist compilation. It renders into an HTML element with class mp-artist
(if present.)
poster: 'image.xxx'
. Optional. Here we can specify an image to serve, e.g., as the album cover art. It renders into an HTML element with class mp-poster
(if present.)
media_path: 'path'
. Optional. It indicates the path to the local or cloud folder containing our audio files. This property exists for convenience. We could ignore it and include the whole path before each file name (see file
property below) —which would be the required technique if each file has a different provenance— but if all the files are stored in the same folder, media_path
saves us from needless repetition.
Note: if we include a media_path
property, repeating the path in the audio file name will produce an error, as Moth Player will concatenate the two.
We can do this:
media_path: 'media/',
tracks: [
{
file: 'Channel 9',
},
Or this:
// no media_path property
tracks: [
{
file: 'media/Channel 9',
},
But not this:
media_path: 'media/',
tracks: [
{
file: 'media/Channel 9',
},
// Moth Player will look for 'media/media/Channel 9'
img_path: 'path'
. Optional. Like media_path
, this property stores the path to our poster or track images. Again, we could add the path to the poster
or img
properties, but if it's the same in all cases, using img_path
makes for shorter, cleaner code.
Note: if we include an img_path
property, repeating the path in the image file name will produce an error, as Moth Player will concatenate the two.
mobile_volume: true
. Optional. If present, Moth Player won't remove by default the volume controls in mobile devices. (See end note in Controls.)
volume: number
. Optional. If present, it sets the player's initial volume level, in a number between 0 and 1. If not present, the default volume will be 0.3. Volume levels can be changed later by the user if we define volume controls.
volume_format: 'a, b'
. Optional. If present, it sets the number of digits before and after the decimal point when we display the volume level in mp-vol-number
. Thus, volume_format: '2, 1'
would render something like "50.2", and volume_format: '1, 2'
would render the same level as "5.02". We can omit the second number if we don't want the fractional part to show —e.g., volume_format: '2'
will render just "50". If we omit this property, it defaults to volume_format: '0, 2'
, displaying the volume level as "0.50".
plist_duration: true
. Optional. It tells Moth Player to render the tracks' duration in the playlist, inside a <span>
element with class mp-plist-length
.
plist_numbers: true
. Optional. It tells Moth Player to render playlist numbers in the playlist, inside a <span>
element with class mp-plist-number
.
leading_zero: true
. Optional. It tells Moth Player to pad track numbers 1 - 9 in mp-track-number
and mp-plist-number
with a leading zero —"1" will be shown as "01".
supplied: 'file type(s)...'
. Optional/Recommended. Activates "Supplied Mode." Alternative to "Free Mode" (if undeclared.) This is where we indicate the file format(s) —we must at least provide one— that we feed to Moth Player, in a comma-separated list (if we write only one, there's no need for commas.)
Some browsers prefer some file types over others, so having different versions of our audio tracks seems wise. At the time of writing, mp3
is the most widely accepted format, so my unsolicited recommendation is to use your favorite audio format for quality and include a backup set of mp3
files.
Moth Player checks this property and will try formats one by one following the defined sequence. If a format is found wanting, a message is logged in the console and the iteration will continue until MP either finds a suitable format or runs out of formats to try.
MP respects the list order: if we write supplied: 'flac, ogg, mp3'
, the library understands that we'd like to use flac files; if that's not possible, then use ogg files; if that's not possible, then use mp3 files.
Once a format is chosen, Moth Player will append the file extension automatically to all the file names given in the file
property. Meaning, MP assumes that all the files are provided in that particular format.
Conversely, Free Mode is useful when we need to set up a mixed playlist with different audio formats. If a file can't be loaded, MP will silently remove it from the playlist.
Free Mode requires that we write the extensions to all the file names given in the file
property.
tracks: [array of objects]
. Required. Here is where we specify all the information pertaining to individual tracks. All properties are optional with the exception of file
. We must at least define one track.
-
title: 'track title'
. Optional. The track's title. It renders into an HTML element with classmp-track-title
(if present.) It will also be injected in the playlist inside a<span>
element with classmp-plist-title
.While technically we could omit it, it's recommended to add this property to our script. If there is no
title
property, Moth Player will read the value contained in thefile
property instead (see below.) -
artist: 'track artist'
. (Not shown in the example code.) Optional. The artist of the given track. It renders into an HTML element with classmp-track-artist
(if present.) It will also be injected in the playlist inside a<span>
element with classmp-plist-artist
.This field is provided for mixed playlists, in case we want to feature the name of each track's performer in the playlist and/or our custom HTML. Conceptually, it seems incompatible with the global
artist
property, ideal for same-artist albums or compilations.That said, Moth Player will let us declare both. There are no conflicts: as regards to the HTML, the global artist property will be assigned to an element with class
mp-artist
and the track artist property to an element with classmp-track-artist
. As regards to the playlist, only track artist properties will be shown. -
extra: 'string'
. Optional. It renders into an HTML element with classmp-track-extra
(if present.) It will also be injected in the playlist inside a<span>
element with classmp-plist-extra
.This is a non-descript category where we can add a string with an arbitrary piece of information.
-
img: 'image.xxx'
. Optional. Here we specify the file name (with extension) of an image to be displayed when the track is selected. Moth Player will render it into an HTML element with classmp-track-image
(if present.)Note: if we include an
img_path
property, repeating the path in the image file name will produce an error, as Moth Player will concatenate the two. -
caption: 'string'
. Optional. It will be read by Moth Player and rendered into an HTML element with classmp-track-caption
(if present.) Useful if we want to associate short custom texts with track images. -
lyrics: 'lyrics_class'
. Optional. If we wish to display a song's lyrics, here's where we specify the class name of the HTML element that contains the lyrics to the current track.Reminder: In the HTML file, all the individual lyrics elements must be children of an element with class
mp-lyrics
. See Lyrics.Note: While intended for lyrics, we can put anything in the HTML element with the specified class. When a track is active Moth Player reads the value of the property —e.g., "lyr01"—, displays the HTML element with
class="lyr01"
and hides the rest. -
file: 'file_name'
. Required. Declares the audio file's name. In Supplied Mode, we omit the file extension, as Moth Player picks one from thesupplied
property (if we add an extension to the file name, there will be an error.) Conversely, writing the file extension is compulsory in Free Mode.If there is no
title
property for the track, Moth Player will read instead the value of thefile
property and inject it into the playlist (<span>
element with classmp-plist-title
) and the HTML element with classmp-track-title
(if present).Note: if we include a
media_path
property, repeating the path in the audio file name will produce an error, as Moth Player will concatenate the two.
CSS
If we're not using a skin, we must style every element of Moth Player with CSS rules that target the relevant class selectors.
The included CSS file in the demo renders a couple of austere players, but it records most of Moth Player's styling quirks, described below.
Hidden selectors
In order to perform certain actions, Moth Player silently adds and removes a few CSS selectors. We should be aware of them, because they warrant some styling as well.
.mp-plist-current
: When a track loads or plays, it receives the class mp-plist-current
. This allows us to address it with some CSS rules and make it stand out from the rest in the playlist. In Moth Player there's always a "loaded" ("active", or "selected") track, even if it's paused.
.mp-looped
: The repeat button (HTML element with class mp-loop
) is a toggle control; it's either "on" or "off" —default is "off". When we click it and turn it "on", it acquires the mp-looped
class, which lets us apply a different style to it and thus signify the event.
Note: Repeat affects the whole playlist, not single tracks.
.mp-shuffled
: Akin to Repeat, the shuffle button (HTML element with class mp-shuffle
) is a toggle control. When "on" it has the mp-shuffled
class.
.mp-time-left
: This class gets added/removed to the element with .mp-track-time
class when users click on it. Bear in mind that .mp-track-time
is never removed.
.mp-warning
: When Moth Player runs, it checks that the audio files reside where they should and that they can be played by the browser. During this process, the player is hidden and a div
with class mp-warning
is created in case something fails and the library needs to display an error message.
Playlist
As seen in the HTML section, Moth Player generates playlist items by reading the corresponding properties declared in the script. The library creates <span>
elements with specific classes for each property and injects them into the <li>
elements. There are five optional fields that, if present, are displayed in this order: number, title, artist, extra and duration.
Suppose we define the following properties in the script:
...
plist_duration: true, // optional
plist_numbers: true, // optional
tracks: [
{
title: 'Channel 9', // optional but recommended
artist: 'Space Weirdo', // optional
extra: 'Pop/Rock', // optional
file: 'Channel 9',
},
],
...
Moth Player would generate a playlist item in the HTML:
<li>
<span class="mp-plist-number">1</span>
<span class="mp-plist-title">Channel 9</span>
<span class="mp-plist-artist">Space Weirdo</span>
<span class="mp-plist-extra">Pop/Rock</span>
<span class="mp-plist-length">4:00</span>
</li>
These fields are rendered inline with no characters between them, not even spaces. The above example, without styling, would display:
This madness attempts to give us options when laying out playlists (separator characters, positioning, etc.) rather than force some default behavior that can't be formatted to our liking. To add proper legibility, we need to write CSS rules and put some ::after
and ::before
selectors to work.
Let's say for instance that we want the artist field to read "by Space Weirdo" in a new line, with a smaller font:
.mp-plist-artist {
display: block;
font-size: .875rem;
}
.mp-plist-artist::before {
content: 'by ';
}
No id's?
Moth Player targets class
attributes, not id
attributes (with the exception of the audio element, which doesn't render on the screen.)
That leaves the possibility of adding id
attributes where we need them for other purposes, including design. If there's more than one player in the page, We could add unique identifiers to their parent elements:
<div class="moth-player" id="player-1">
...
</div>
<div class="moth-player" id="player-2">
...
</div>
… and then all of their respective children can be singled-out in CSS:
#player-1 .mp-play {
...
}
#player-2 .mp-play {
...
}
No pointer?
An element with class mp-track-time
renders, by default, the track's current time. With a mouse click, it changes to show the track's remaining time. Convention dictates that, when something exciting may happen if you click on an element, the cursor should change its appearance to mark the fact; but you may choose to ignore convention and Moth Player doesn't assume.
We need to explicitly declare a CSS rule for this to happen:
.mp-track-time {
cursor: pointer;
}
Troubleshooting
So, Moth Player doesn't work. Let's see what we can do about that.Basic Checklist
Most problems are syntax-related or come from typos. Please check:
- File names and paths of your media and image files are correct.
- All the punctuation in the custom script is correct.
- Does the first line
mp_plist.audio_id
in the custom script point to theaudio_id
of the audio element?
Devtools & Console
Mainstream browsers offer Web Development Tools (a.k.a. Devtools). Here we can access the DOM tree —which shows nodes and classes created by Moth Player at runtime, such as the playlist items— and a JavaScript console that reports any error encountered during code execution.
Moth Player will log messages in the console to mark some events in the code flow and to document known incidents. Use this information in combination with error messages to pinpoint the cause of the problem.
Most messages are preceded by Player audio_id ([Supplied/Free]):
, which shows the id
of the player under scrutiny (useful if there's more than one) and whether it's in Free or Supplied mode.
Supplied array is [ext1,ext2...].
(Supplied Mode.) Moth Player has read the file types in the supplied
property and put them in an array (a list of variables), so that they can be checked one by one.
Moth Player checks each format for compatibility, first against an internal list of accepted formats, then against the browser's opinion about the MIME type. If a file type fails a test, it's removed from the list and this message appears again to tell us which formats are still in play.
File type "ext" unsupported by Moth Player. Pruning from array.
(Supplied Mode.) A file type in the supplied
array isn't part of the internal list of accepted formats (see Free Mode vs. Supplied Mode.) Moth Player will remove it from the list.
Browser reports it [can probably / can maybe / can't] play the media type MIME_type.
(Supplied Mode.) Moth Player reports the browser's response regarding its ability to play the supplied media type.
The browser may say "probably" or "maybe" (in which case we accept the format and move on) or say nothing (passive-aggressively meaning "no"). If "no", see the next message.
File type "ext" unsupported by the browser. Pruning from array.
(Supplied Mode.) Moth Player has asked the browser if it can play the supplied media type (MIME type) and the browser said no. The library will remove it from the list.
file.ext could NOT be loaded.
(Supplied Mode.) Moth Player fed a media file to an audio element and encountered a problem. Check if the media file exists in the given location.
This occurence also triggers an error message. There may be more formats to try, in which case Moth Player moves on to the next. If any format is successful, the player will load and we'll never see the error message.
file.ext could NOT be loaded. Removing from playlist.
(Free Mode.) Moth Player fed a media file to an audio element and encountered a problem. The library will remove the track from the playlist and continue.
file.ext: metadata has been loaded.
Moth Player fed the audio file to an audio element and the browser was able to find it and load its metadata (for audio files, "metadata" at the browser level means the track's duration.)
Choosing file extension "ext".
(Supplied Mode.) Minding the order in the supplied
property, Moth Player managed to load all the files of a particular type. The libary picks that format to build the playlist and ignores the rest.
All tracks for Player audio_id seem ready.
: The library has found and checked all the audio files that it needs and is ready to build the player.
Error Messages
While Moth Player loads, the player doesn't show on the screen; instead, there is a placeholder for error messages.
Loading player...
This is the default state at the beginning and is not an error per se.
You may see this for a moment before the player appears (it may take a while if there are a lot of files to check), which means that everything worked as it should, or you may be stuck with this message forever, which means that some unforeseen error took place. See if the JavaScript Console offers some clue.
All supplied file types failed.
(Supplied Mode.) (a) Moth Player failed to match all supplied
formats against the internal list of accepted file types; (b) the browser rejected all MIME types; or (c) a combination of both. This is a fatal error. We need to provide a supported audio format.
file.ext could NOT be loaded.
(Supplied Mode.) Same as the log event: Moth Player fed a media file to an audio element and encountered a problem. Check if the media file exists in the given location. There may be more file types to try and Moth Player will keep at it until one succeeds —the player loads and this message is never seen— or they all fail —a fatal error.
None of the audio files could be loaded.
(Free Mode.) If the library can't load an audio file in Free Mode, it removes it from the playlist and continues on to the next file. This message appears when all the audio files have failed to load and building a playlist becomes impossible. This is a fatal error.
If the player doesn't load and you see the error messages:
- Are the path, file names and extensions correctly spelled?
- Are the audio files in the specified location?
- Are the audio files corrupt (do they work, say, on a desktop player?)
- Supplied Mode: Check that the file extensions specified in the
supplied
property actually match the extensions of your media files. - Free Mode: maybe the browser can't play any of the provided media types.
Final words
I'd like to thank you for trying Moth Player. I hope that it proves useful (or fun) to you.
If you find this document confusing or in dire need of improvement, feel free to share your thoughts via email and I'll do my best to address your concerns.
Bug reports are welcome (you'd be doing me a huge favor.)
If you'd like to contribute to Moth Player (code, skins, anything that comes to mind) I'll be very surprised. In a good way. We can talk about it.
Moth Player is licensed under the MIT license.
Cheers.
References
Cross-browser audio basics, at developer.mozilla.org.
HTML5 Audio Player w/ Responsive Playlist, at github. The original article by John Hall "How to Create a Playlist for HTML5 Audio" (link) is now defunct and only accesible through the wayback machine.
jPlayer, The jQuery HTML5 Audio / Video Library.
A helpful free audio converter that I use (not a sponsor): fre:ac.