Stimulus - Adding Markers to a Wavesurfer Element

Use Stimulus value callbacks to interact with a wavesurfer element and add markers.

View Solution on Patreon
Stimulus - Adding Markers to a Wavesurfer Element

Premise

It had to happen. Many of you will already know that Iā€™m an audio and music buff (and for those who donā€™t know yet, look at my Znibbles YouTube channel, for example).

Weā€™ll be looking at integrating an audio visualization library - Wavesurfer - with Stimulus by leveraging its internal event system and Stimulus values.

This touches upon many topics we have discussed before:

Have fun!

Starting Point

Markup

Letā€™s look at the markup first. The whole affair is wrapped in a <div> to which a peaks Stimulus controller is attached:

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=index.html%3AL42

Wavesurfer itself expects a container element and (optionally) an <audio> element containing the source (I have used a small snippet of my own to avoid any copyright issues šŸ˜…):

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=index.html%3AL43

Then, thereā€™s a play button thatā€™s already wired up to the playPause action:

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=index.html%3AL53

And an <input> field to add descriptions for markers:

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=index.html%3AL63

The respective button is connected to the addMarkerAtCurrentTime action. Last but not least, thereā€™s a list target to hold textual descriptions of the markers:

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=index.html%3AL78

JavaScript

The PeaksController already has the Wavesurfer boilerplate configured for you:

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=controllers%2Fpeaks_controller.js%3AL22

Thatā€™s also the case for the Regions plugin, which is required to store and manipulate markers (which are simply regions without an end timestamp):

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=controllers%2Fpeaks_controller.js%3AL34

The logic to handle the addition of regions to a Wavesurfer instance is also provided:

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=controllers%2Fpeaks_controller.js%3AL66

Challenge

To warm up, letā€™s look at what has to happen when the play/pause button is pressed. Wavesurfer triggers an internal event (example here), which you should listen for and update the playing value accordingly. Note that the playingValueChanged listener to update the button label is already in place.

Add your event handling logic here: https://stackblitz.com/edit/stimulus-wavesurfer-1?file=controllers%2Fpeaks_controller.js%3AL36

Next, letā€™s implement adding a marker. Weā€™ll do this by adding an item to the markers value and handle the respective callback accordingly. First, when the ā€œAdd Markerā€ button is pressed, youā€™ll have to add a new item to this.markersValue and clear the input field:

https://stackblitz.com/edit/stimulus-wavesurfer-1?file=controllers%2Fpeaks_controller.js%3AL63

Then, you need to compare the new and old values in the callback to filter out the additions, and call #handleAddition on each:

Finally, we also want to add items to the listTarget so we have a rundown of all the markers. My recommendation would be to again utilize the regions pluginā€™s event system, i.e. the region-created event to add such an item. Hint: Use this.regions.on('...').

Below is a rendering of the result:

Waveform display with markers being added

Teasers

  • How - and where in the client side logic - would you trigger persisting the markers?
  • Letā€™s say another user can add markers too, and these are morphed into the data-peaks-markers attribute. Is your code ready to display those too?

More from

Faceted Search with Stimulus and Turbo Frames
10 December 2024

Harness the power of Stimulus and Turbo Frames to drive a simple but powerful faceted search solution

Stimulus - Video Progress Tracker with LocalStorage
29 October 2024

Store ephemeral user state like video playback progress in localStorage

Stimulus - Image Upload Previews with `URL.createObjectURL`
17 September 2024

Create client-side previews of files using URL.createObjectURL

Cookies
essential