How to Create a Custom Howler.js Plugin

This article provides a straightforward guide on how to extend the capabilities of howler.js, a popular JavaScript audio library, by creating custom Howl plugins and extensions. You will learn how to tap into the Howler prototype to add custom methods, manipulate audio states, and build reusable audio components for your web applications.

Understanding the Howler.js Architecture

Howler.js is built around two primary global objects:

To create a plugin or extension, you must extend the prototype of either Howl (for instance-specific methods) or Howler (for global controls) using standard JavaScript prototype inheritance.

Extending the Howl Prototype

The most common way to create a plugin is to add new methods to the Howl.prototype. This makes your custom functions available to every new audio instance you instantiate.

Here is the standard boilerplate structure for a howler.js plugin:

(function() {
  // Ensure Howler.js is loaded before executing the plugin
  if (typeof Howl === 'undefined') {
    console.error('Howler.js must be loaded before the custom plugin.');
    return;
  }

  // Extend the Howl prototype with a custom method
  Howl.prototype.myCustomMethod = function() {
    // 'this' refers to the active Howl instance
    var self = this;

    // Custom logic goes here
    console.log('Playing source:', self._src);

    // Always return 'this' to maintain method chaining compatibility
    return self;
  };
})();

Creating a Practical Example: A Fade-and-Stop Plugin

To demonstrate how this works in practice, let’s build a custom extension called fadeAndStop. This method will fade out an active track over a specified duration and automatically stop the playback once the fade is complete, resetting the volume back to its original state.

(function() {
  if (typeof Howl === 'undefined') return;

  Howl.prototype.fadeAndStop = function(duration) {
    var self = this;
    var currentVolume = self.volume();

    // Start fading to 0
    self.fade(currentVolume, 0, duration);

    // Listen for the fade completion event
    self.once('fade', function() {
      self.stop();               // Stop the playback
      self.volume(currentVolume); // Reset volume to original state for next play
    });

    return self;
  };
})();

How to Use the Custom Plugin

Once your plugin code is loaded into your project (either in a separate file after howler.js or within the same bundle), you can call the method directly on any Howl instance.

// Initialize a sound
var sound = new Howl({
  src: ['audio.mp3']
});

// Play the sound
sound.play();

// Use the custom extension to fade out and stop over 2000 milliseconds
sound.fadeAndStop(2000);

Extending the Global Howler Object

If you want to create helper functions that affect all sounds globally, you can attach your custom methods directly to the global Howler object instead of the Howl prototype.

For example, this extension adds a master fade-out feature:

(function() {
  if (typeof Howler === 'undefined') return;

  Howler.globalFade = function(from, to, duration) {
    var currentVol = Howler.volume();
    // Logic to step volume down or up globally over a set duration
    // Howler.volume(newVolume);
  };
})();

By utilizing these prototype extension patterns, you can cleanly organize your audio logic, keep your codebase DRY (Don’t Repeat Yourself), and build robust audio features on top of the howler.js core engine.