Producing a Music Video in the Browser
Tags: javascript, html, design
Published: 2020-09-06 12:15:27

This page and associated codepens are meant to share with other developers a means of creating a [Webm](https://www.webmproject.org/) video from a dynamically generated [canvas](https://www.w3schools.com/html/html5_canvas.asp) driven from user input and a audio file. If this sounds interesting, keep reading.

## Introduction

I’m [Jason](https://vizibop.com/about). I’m building [Vizibop](https://vizibop.com), a service currently in beta that allows musicians and podcasters to quickly and easily create a unique MP4 video synched to a audio file. Yes, this is a [thing](https://www.indiehackers.com/product/wavve/revenue).

At its core, Vizibop leverages a HTML Canvas, HTML5 Audio, MediaRecorder, and [P5.js](https://p5js.org/) to generate a WebM file with front end code only. From there, that WebM file is sent through [AWS Elastic Transcoder](https://aws.amazon.com/elastictranscoder/) to convert the Webm file to a MP4 file which can then be shared on sites like Instagram, TikTok, and YouTube.  Here is a basic video created from Vizibop:

{% youtube u6cKF9ZYCh4 %}


## Creating a basic animation

P5.js is a javascript library that make drawing on a canvas relatively straight forward. Even for the mathematically challenged like myself, [particles](https://p5js.org/examples/simulate-particle-system.html) and [flocking](https://p5js.org/examples/simulate-flocking.html) are made easier to implement using P5. I am using P5 [instance](https://github.com/processing/p5.js/wiki/Global-and-instance-mode) mode to keep things tidy. Here is a very basic scaffolding for a p5 animation:

{% codepen https://codepen.io/Vizibop/pen/ZEWXRGm %}

## Playing Music

Audio in the browser is a bit of a rabbit hole. [Howler](https://howlerjs.com/) and [SoundJS](https://createjs.com/soundjs) will make your life a lot easier if you get into building jukeboxes and video games. To keep things simple, let's simply create a hidden audio element and allow a user to click a button to begin playing a song. For Vizibop we allow users to upload their own songs in WAV or MP3 format using [FileReader](https://developer.mozilla.org/en-US/docs/Web/API/FileReader) and [createObjectURL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL).

{% codepen https://codepen.io/Vizibop/pen/qBZPMpv %}

## Wiring Audio to P5

The [P5.sound](https://github.com/processing/p5.js-sound) module makes it super easy to have the variables within your sketch change based on the volume and frequency of a sound. Out of the box you can use [Amplitude](https://p5js.org/reference/#/p5.Amplitude) and [FFT](https://p5js.org/reference/#/p5.FFT) to do some pretty amazing things. The [Coding Train](https://www.youtube.com/watch?v=Pn1g1wjxl_0) has a whole series of videos on sound within P5 that I encourage you to watch.

In this example, we want to do some beat detection to change the background of the canvas. Beat detection also gets a little tricky depending on the song and quality of the underlying audio. In Vizibop we let the user define which frequency bands to key off of to really dial in more accurate beat detection.

{% codepen https://codepen.io/Vizibop/pen/MWyEBew %}

## Customize the animation

The animation above is pretty basic. A better experience allows the users to turn knobs and dials to customize their animation. In our case, I have tried to balance just enough knobs and dials to create a wide range of videos without overwhelming the user with too many options. The possibilities are really unlimited when you combine images, typography, color, motion, and math.

{% codepen https://codepen.io/Vizibop/pen/zYqEJVe %}

## Record a video

We now have the key components to record a music video built entirely in the front end.

Now the fun begins, particularly across browsers and computers. [MediaRecorder and captureStream](https://developers.google.com/web/updates/2016/01/mediarecorder) are the magic that allows us to create a Webm video from the components above. As of the writing of this document, Safari only supports MediaRecorder in experimental mode. Firefox does not support VP9 or H264 codecs. Chrome is our best friend here and clearly outperforms in this use case. With 70% market share between Chrome and Firefox, I was willing to move ahead with this approach betting that eventually Safari will make MediaRecorder generally available.

I am still tweaking the configuration here. It seems that both the VP9 and H264 codecs underperform VP8 for this application. Firefox has its issues. Adjusting both the frame rate of the animation and the captureStream combined with the optional videoBitsPerSecond parameter for the MediaRecorder seem to improve visual lag and artifacts due to compression. It's not perfect but so far I am pleased with the results.

{% codepen https://codepen.io/Vizibop/pen/xxVXLrQ %}

## What's next?

With this technique, there really isn't a limit to the types of videos musicians and podcasters can create in the browser. With that said, by design, Vizibop will not evolve into a full blown video editor. A guiding principle is to keep the user experience simple while maximizing the number of unique videos that can be created. Awesome Factor = Number of Unique Videos / Number of Knobs and Dials. My intent is to create a tool that is [Sesame Street Simple](https://bobsutton.typepad.com/my_weblog/2008/09/sesame-street-simple-ag-lafleys-leadership-philosiphy.html) for people who I believe should be spending more time focused on their core craft.

Your thoughts, feedback, advice, and guidance is always welcome