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:
- Stimulus Value Callbacks
 - Optimistic UI
 - Integrating 3rd Party Libs
 
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:

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-markersattribute. Is your code ready to display those too? 
        
  
        
