Plugins
What plugins are
Plugins are optional modules that add features on top of the core wavesurfer.js waveform player. Each plugin is a separate file you import only when you need it, so your bundle stays small if you use just a subset.
The eight official plugins are:
- Regions — highlight and loop segments of audio
- Timeline — a time ruler above or below the waveform
- Spectrogram — a frequency-over-time visualization
- Minimap — a small overview waveform for navigation
- Hover — show a vertical line and timestamp under the cursor
- Zoom — scroll-wheel / pinch zoom
- Record — record audio from the microphone
- Envelope — draw a volume / fade curve over the waveform
Importing
ESM (bundler or <script type="module">)
Each plugin ships as an ES module at dist/plugins/<name>.esm.js:
import WaveSurfer from 'wavesurfer.js'
import RegionsPlugin from 'wavesurfer.js/dist/plugins/regions.esm.js'
import TimelinePlugin from 'wavesurfer.js/dist/plugins/timeline.esm.js'
The same paths work with a CDN that serves npm packages:
import RegionsPlugin from 'https://unpkg.com/wavesurfer.js@7/dist/plugins/regions.esm.js'
UMD (plain <script> tag)
Load the core library first, then each plugin’s .min.js file. Every plugin attaches itself to the WaveSurfer global under a capitalised key:
<script src="https://unpkg.com/wavesurfer.js@7/dist/wavesurfer.min.js"></script>
<script src="https://unpkg.com/wavesurfer.js@7/dist/plugins/regions.min.js"></script>
<script src="https://unpkg.com/wavesurfer.js@7/dist/plugins/timeline.min.js"></script>
<script>
// Globals: WaveSurfer.Regions, WaveSurfer.Timeline, WaveSurfer.Spectrogram,
// WaveSurfer.Minimap, WaveSurfer.Hover, WaveSurfer.Zoom,
// WaveSurfer.Record, WaveSurfer.Envelope
const regions = WaveSurfer.Regions.create()
const timeline = WaveSurfer.Timeline.create()
</script>
Registering
At construction time — the plugins option
Pass an array of plugin instances to WaveSurfer.create():
const regions = RegionsPlugin.create()
const timeline = TimelinePlugin.create()
const ws = WaveSurfer.create({
container: '#waveform',
url: '/audio.mp3',
plugins: [regions, timeline],
})
All plugins in the array are initialised immediately when the WaveSurfer instance is created.
After construction — ws.registerPlugin()
Call registerPlugin at any point after create(). It initialises the plugin right away and returns the plugin instance:
const ws = WaveSurfer.create({ container: '#waveform', url: '/audio.mp3' })
// Register later — perhaps in response to a user action
const regions = ws.registerPlugin(RegionsPlugin.create())
Both approaches produce an identical result; the plugins option is just a convenience that calls registerPlugin for each entry internally.
Getting an instance back
Keep the reference
The simplest approach is to hold on to the reference returned by RegionsPlugin.create() or ws.registerPlugin():
// Option A: created with the plugins option
const regions = RegionsPlugin.create()
const ws = WaveSurfer.create({ container: '#waveform', plugins: [regions] })
regions.addRegion({ start: 1, end: 3 })
// Option B: registered after creation
const regions = ws.registerPlugin(RegionsPlugin.create())
regions.addRegion({ start: 1, end: 3 })
ws.getActivePlugins()
If you no longer have the original reference, you can retrieve all currently registered plugins:
const allPlugins = ws.getActivePlugins()
// Returns an array of GenericPlugin instances in registration order
Pitfalls
Register each plugin instance only once. Calling ws.registerPlugin() with the same instance twice is safe — wavesurfer.js silently skips the duplicate — but creating a new RegionsPlugin.create() and registering it again while the old one is still active will attach a second set of event listeners and DOM elements, leaking memory. Always call plugin.destroy() before replacing a plugin. See Performance for more on memory management.
React StrictMode mounts components twice in development, which causes WaveSurfer.create() — and therefore all plugins — to initialise twice. The second initialisation runs before the first one is cleaned up, so you can end up with duplicate plugin instances. Always return a cleanup function from useEffect that calls ws.destroy(), and guard the effect with a ref so creation only happens once. See Frameworks for a complete React example.
The plugins
| Plugin | Description |
|---|---|
| Regions | Add coloured, draggable, and resizable regions to mark segments of audio |
| Timeline | Render a time ruler with tick marks above or below the waveform |
| Spectrogram | Visualise audio frequency content as a colour-mapped spectrogram |
| Minimap | Display a small thumbnail waveform for scrolling and navigation |
| Hover | Show a vertical line and elapsed-time label that follows the mouse cursor |
| Zoom | Zoom in and out with the scroll wheel or a pinch gesture |
| Record | Record audio directly from the microphone and render it as a waveform |
| Envelope | Draw a volume-automation curve over the waveform with draggable points |