0.0.4 • Published 4 years ago

react-audio-viz v0.0.4

Weekly downloads
6
License
MIT
Repository
github
Last release
4 years ago

react-audio-viz

A delightfully simple yet impressively extendable audio visualization framework for React

demo

Check out the live demo at http://react-audio-viz.surge.sh/

Development

Run yarn to install dependencies then yarn dev to start up the demo at localhost:1234 where you can test any changes made to the core library in src/lib.

Sample Usage

import { useVisualizer, models } from 'react-audio-viz'

const AUDIO_SRC = '...'

const App = () => {
  const mediaElementRef = React.useRef(null)
  const [ReactAudioViz, initializeVisualizer] = useVisualizer(mediaElementRef)

  return (
    <div>
      <h1>react-audio-viz</h1>
      <audio
        controls={true}
        onPlay={initializeVisualizer}
        ref={mediaElementRef}
        src={AUDIO_SRC}
      />
      <div style={{ width: '400', height: '400' }}>
        {ReactAudioViz && <ReactAudioViz model={models.polar()} />}
      </div>
    </div>
  )
}

API

const [ReactAudioViz, initializer] = useVisualizer(mediaElementRef)

useVisualizer accepts a single argument which is a ref object (i.e. React.useRef result) that corresponds to the <audio /> or <video /> element you are trying to render a visualization of.

It returns a tuple containing a ReactAudioViz component and an initializer function, both of which may be null if an error occurs (e.g. the mediaElementRef doesn't point to a valid media element).

ReactAudioViz

A React component which accepts a single model prop which the framework uses to render each frame. You can use an existing model exported by this library (e.g. models.polar(options)) or build your own custom model.

When rendered, the ReactAudioViz component creates a single <canvas /> element that the visualization is performed on. The canvas will automatically resize to reflect the size of its parent (using this cross-browser ResizeObserver polyfill) so you can simply place <ReactAudioViz /> in a container element sized to your needs.

initializer

Modern browsers protect users from code that may tap into audio/video sources without their consent. As a result, the "tapping into the media source" code has to execute as a result of a user action. Invoke this function (without any arguments) in response to a user action that makes sense for your application. I suggest the onPlay prop of your <audio /> or <video /> element.

Building a Custom Visualization Model

In simplest terms, a visualization model is a function that decides the color of each pixel on the canvas. To build one, simply create a function that implements the VisualizationModel type signature (shown below), then pass it into the model prop of <ReactAudioViz />.

type Pixel = {
  r: number
  g: number
  b: number
  // alpha is optional, defaults to 255
  a?: number
}

type VisualizationModel = (
  x: number,
  y: number,
  width: number,
  height: number,
  frequencyData: Uint8Array,
  // The ID of the animation frame this invokation of the model corresponds to
  // i.e. frameID will change every (width * height) invokations of this function
  frameID: number
) => Pixel

To better illustrate this, take a look at the polar model (or more accurately, model factory) that this library ships with. models.polar is a model factory ((options: PolarVisualizationModelOptions) => VisualizationModel) which lets you generate a "polar"-shaped visualization model which may be customized at run-time (see the live demo).

The polar model factory returns a VisualizationModel which converts the x and y values to the proper radial distance from center of canvas (based on the width and height values), then colors that pixel with the magnitude of the frequency corresponding to that radial distance.

Tips for Building a Visualizer Model

Memoize repetitively used data in a factory

The visualization model is the primary bottleneck for performance. For example, if your canvas is 400x400 and the user has a 60FPS refresh rate, it will be called 400x400x(60 FPS) = 9,600,000 times every second. If you're building a custom model, make sure the model function is highly performant. Consider leveraging a model factory for performing any performance optimizations (e.g. see the pulse model factory for an example of memoizing repetitively used data by the frameID)