The Broad Strokes
Before going into the nitty-gritty, let’s make sure we have a good overall game plan. The first step is to get permission to access the user’s mic and then record audio through the frontend. Next, we have to package and send that data to the backend where it will be associated with a ruby object and persisted in the database. After that, we have to call upon that data to make a JS object in the frontend, and ultimately append it to the page in a user friendly way. This article assumes the knowledge to do all of the above with a simpler data type, such as text.
(THE FIRST FEW STEPS ALL TAKE PLACE IN INDEX.JS UNLESS OTHERWISE NOTED)
Step 1: Getting mic access
To gain access to a user’s mic, we need to ask permission.
- ‘audio: true’ sets a constraint that only audio will be captured
- The code after the first ‘then.’ creates a new MediaRecorder instance once the
getUserMediacall has been completed successfully.
- The code after the second ‘then’ is run if the
getUserMediacall fails for whatever reason.
getUserMedia somewhere inside the following:
Step 2: Setting up the starting HTML
First add an <article> tag to the HTML so that we have somewhere to put the audio players once we append them. Then create a record/stop button on that same index.html (Don’t forget to give both of these elements some id so we can reference it later). We will link this button to a click event that will start recording. Do this inside the “DOMContentLoaded” event listener which should now look like this:
Step 3: The start function
As you can see above, the recording button that exists on the page from the start is linked to a function called ‘start’ that will be in the same file. The ‘start’ function will do four things: Declare a blank array to capture our audio data, start our already instantiated MediaRecorder instance, push the data into the array as it becomes available and set up what happens when we click the ‘stop’ button.
Declaring a blank array is as simple as it sounds. I called mine ‘chunks’.
To start the MediaRecorder, use “mediaRecorder.start()”.
Then as to capture data as it becomes available, use:
Finally, we will set up what happens when the media recorder is stopped:
The above switches the function of the record/stop button to the opposite of what is was before, prompts the user for a title and assigns it to a variable, creates a blob out of the ‘chunks’ array, clears the array for next use, and sends the blob and title to the MeditationApi class to be packaged and sent to the backend via a fetch POST request.
Step 4: Package and send audio to backend with a fetch POST request
The tricky part here is to package the data in a File and then package that File in a Form. Notice how the blob has to be inside and array.
Next, we send a POST request to the backend. DO NOT INCLUDE A HEADER!!!!
Step 5: Set up ActiveStorage and Persist Audio
To properly set up ActiveStorage, follow the same procedure as the first section here, but instead of photos we are doing audio.
In the backend, in the models directory, mimic the picture below in whatever class you would like to attach the audio.
has_one_attached gives us access to the ‘attach’ method which will be used in our create action
Also take notice of:
Step 6: Call upon data and create a JS object
The data will be send back to the frontend using json. The picture in step 4 is relevant here again. We are pretty much looking at everything from .then onwards.
Step 7: Append to page in and <audio> tag
This was the part I thought would be the hardest. Turns out it’s the easiest! All you have to do is create an audio element, set the controls:
add a source (which will be the url we sent back to frontend):
and finally append it to the page the same way you would any other element!
The following links were EXTREMELY helpful:
MediaRecorder - Web APIs | MDN
Creates a new MediaRecorder object, given a MediaStream to record. Options are available to do things like set the…
Uploading Files To Your Rails API
Uploading large number of files from front end (using React) to a separate API backend (using Rails)
The Pragmatic Studio
Gone are the days when you have to use external gems to handle file uploads in Rails. These days Active Storage is…
Using the MediaStream Recording API - Web APIs | MDN
The MediaStream Recording API makes it easy to record audio and/or video streams. When used with…