For the LiveWeb this week I explored the MediaRecorder constructor.
MediaRecorder let’s you record “media” webcam, audio, screen etc, and work with it in the browser it was recorded in or save to a file system.
I thought it would be fun to create a “message roulette.”
Everyone records a ten second video and when done you are shown a “roulette” button. Which when pressed will cycle through stills of everyone participating and randomly stop on a message. You can spin again to hear another message or record a new one.
First I needed to have stills in addition to the video, building off the example code, I passed my video stream into a canvas and initially tried to just use our old dataToURL method. That saved files but I was unable to see them in preview or the browser.
After some searching I ended up saving the canvas as a Blob just like the MediaRecorder, with the canvas.toBlob method.
With that I still needed to do a bit of post work on the image to have it saved in a readable format. Luckily this stackoverflow had a good way of stripping off some the base64 meta data and allowed me to save the images as readable image files. I then emit them to the server for storage.
I needed my still images and videos to be named the same (later I create the video msg elem from the stopped image name) so I set the name of the still to a variable (tempFilename) and use that for the video name as well.
To get at my image files from the server I needed to expose the /stills/ dir. To do this I used the serve-index npm package. I’m not sure if this is the most secure way of doing this, but it served my purpose and this directory didn’t have much sensitive data.
message roulette record
I also wanted to give the user a better idea of when they were being recorded. So I found a count down button example here. It used jQuery, I modified it to just be vanilla js.
record button count down
I also needed to dynamically create the DOM element(s) to rotate in the the roulette spinner. I used a simple AJAX script modified for my needs.
I wrapped that in a function call which dynamically created my content when the roulette button is clicked.
To make the roulette functionality I found this example - roulette.js. It is written using jQuery which I have been trying to get away from, but after a little bit of trying to move to vanilla js it was having a bunch of problems. I ended up just leaving as jQuery because I actually needed it for the AJAX call anyway.
The one main problem I had, that I wasn’t able to get sorted was caused by loading the content dynamically. The demo used the height of the DOM element(s) that are going to spin to set various thresholds. Creating the content dynamically and then trying to calculate those heights with js didn’t seem to work. The only way I could stop it from spinning of to infinity was by setting a hard coded height.
roulette to infinity
Still going… roulette still going inspector gif
Hardcoding a totalHeight dimension made it work but is not exactly the way I want. If there are too few submissions the roulette looks weird. If there are too many you may never see them.
To hack it to stop on the correct value even if it’s “higher” than the height set, I am doing a final css transform when the spin finishes.
Then I take the image name and created my video element from that.