loading...
Cover image for Audio Player with Wavesurfer.js & React πŸ„πŸ½β€β™‚οΈ

Audio Player with Wavesurfer.js & React πŸ„πŸ½β€β™‚οΈ

jamland profile image Andy Burkovetsky ・2 min read

Recently I was in need to set a simple view that can show audio file waveform and play its audio using React.JS. After some googling, I found this Wavesurfer.js package. It has pretty exciting use examples, except it lucks of React.JS example, which as we know lives in its own virtual world, what force you write code in its specific way. So, I share my example here with some main points.

Here is the final result (with some soundcloud-like style)

Code In Details

🌊 Reference to DOM

We can import package and use the module as usual.

import WaveSurfer from "wavesurfer.js";

WaveSurfer.create({ container: someDiv });

Most tricky things happen when React rerenders component replacing DOM elements and old ones lost. WaveSurfer.js doesn't expect these changes, so we need to provide an alias to a needed HTML element within React.

We can do it setting ref to some element and passing this ref to WaveSurfer object on creating.

const waveformRef = useRef(null);

useEffect(() => {

  WaveSurfer.create({ 
    container: waveformRef.current
  });

}, []);

return <div ref={waveformRef} />;

🐟 Reference to Audio Player

A similar thing we need to do to access Wavesurfer instance from our React component. Again, because of React nature, on each rerender React component born in a new body (function) and it doesn't have access to variables from previous live. So we need to save it between rerenders with similar ref technique.

const wavesurfer = useRef(null);

useEffect(() => {

    wavesurfer.current = WaveSurfer.create(options);

    // Removes events, elements and disconnects Web Audio nodes.
    // when component unmount
    return () => wavesurfer.current.destroy();
  }, [url]);

And, when component life is over or when we want to create a new instance we need to destroy the previous one manually, otherwise, you will have multiply copies displayed on the screen and you won't have access to them.

Lastly, at this stage, we need to destroy the old instance and create a new one each time we will have url property changed. Based on docs, looks like you can use the same instance over-and-over, but for me, it wasn't updated properly so I did it this way.

useEffect(() => {
  ...
}, [url]);

🦦 That's all.

That is actually all you need to do specific to React - Wavesurfer.js communication. Next, you can follow Wavesurfer.js docs on how to use it. For example:

wavesurfer.current.load(url);

wavesurfer.current.on("ready", function() {
  // https://wavesurfer-js.org/docs/methods.html
  wavesurfer.current.setVolume(0.5);
  wavesurfer.current.play();
});

Posted on by:

Discussion

markdown guide