• Record, Play, Download Microphone Sound With HTML5

    HTML5 has tons of new stuff that are exciting and very interesting. It arrived with features that would replace the need of Flash in browsers. Since the features that were available in Flash is coming into the native JavaScript, soon we won't have to update our Flash player plugin and depend on Adobe for new awesome features.
    More integration with hardware technologies to the Web is the main important thing. We can now access the audio & video hardware of the user's system efficiently with less code.
    In this tutorial, I will introduce you to a small plugin I created to record, play & download the microphone input voice of the user. This is made possible by the Web Audio API.

    UPDATE - 0.3

    Now supports converting WAV audio to MP3 which will help reduce the size of recorded file.

    Introduction

    We will only use HTMLJSCSS. There aren't any server side stuff in this one. We only have one sub folder for the JS files called "cdn".
    As I said before, I have created a jQuery plugin for recording the voice and managing it. It needs RecorderJS for working. You can get it from here. Note that the plugin also needs "recorderWorker.js" which is in the same GitHub repository.
    You can get my Voice plugin from here and name it as "jquery.voice.js" in the "cdn" directory.

    Main Page

    We have only one page to display to the user :
    <!DOCTYPE html>
    <html>
       <head>
        <script src="http://lab.subinsb.com/projects/jquery/core/jquery-2.1.1.js"></script>
        <script src="http://lab.subinsb.com/projects/jquery/voice/recorder.js"></script>
        <script src="http://lab.subinsb.com/projects/jquery/voice/jquery.voice.min.js"></script>
        <script src="cdn/record.js"></script>
       </head>
       <body>
        <div id="content">
          <h2>Record, Play & Download Microphone Voice</h2>
          <audio controls src="" id="audio"></audio>
          <div style="margin:10px;">
            <a class="button" id="record">Record</a>
            <a class="button disabled one" id="stop">Reset</a>
            <a class="button disabled one" id="play">Play</a>
            <a class="button disabled one" id="download">Download</a>
            <a class="button disabled one" id="base64">Base64 URL</a>
            <a class="button disabled one" id="mp3">MP3 URL</a>
          </div>
          <input class="button" type="checkbox" id="live"/>
          <label for="live">Live Output</label>
          <style>
          .button{
            display: inline-block;
            vertical-align: middle;
            margin: 0px 5px;
            padding: 5px 12px;
            cursor: pointer;
            outline: none;
            font-size: 13px;
            text-decoration: none !important;
            text-align: center;
            color:#fff;
            background-color: #4D90FE;
            background-image: linear-gradient(top,#4D90FE, #4787ED);
            background-image: -ms-linear-gradient(top,#4D90FE, #4787ED);
            background-image: -o-linear-gradient(top,#4D90FE, #4787ED);
            background-image: linear-gradient(top,#4D90FE, #4787ED);
            border: 1px solid #4787ED;
            box-shadow: 0 1px 3px #BFBFBF;
          }
          a.button{
            color: #fff;
          }
          .button:hover{
            box-shadow: inset 0px 1px 1px #8C8C8C;
          }
          .button.disabled{
            box-shadow:none;
            opacity:0.7;
          }
          </style>
        </div>
       </body>
    </html>
    As you can see, we only use CSS for styling the button and nothing else. We also don't include the "recorderWorker.js", because it's loaded by the "recorder.js" which we have included in the page.

    record.js

    This file adds event listeners to the buttons to control recording and initiates the functions :
    function restore(){
      $("#record, #live").removeClass("disabled");
      $(".one").addClass("disabled");
      Fr.voice.stop();
    }
    $(document).ready(function(){
      $(document).on("click", "#record:not(.disabled)", function(){
        elem = $(this);
        Fr.voice.record($("#live").is(":checked"), function(){
          elem.addClass("disabled");
          $("#live").addClass("disabled");
          $(".one").removeClass("disabled");
        });
      });
      
      $(document).on("click", "#stop:not(.disabled)", function(){
        restore();
      });
      
      $(document).on("click", "#play:not(.disabled)", function(){
        Fr.voice.export(function(url){
          $("#audio").attr("src", url);
          $("#audio")[0].play();
        }, "URL");
        restore();
      });
      
      $(document).on("click", "#download:not(.disabled)", function(){
        Fr.voice.export(function(url){
          $("<a href='"+url+"' download='MyRecording.wav'></a>")[0].click();
        }, "URL");
        restore();
      });
      
      $(document).on("click", "#base64:not(.disabled)", function(){
        Fr.voice.export(function(url){
          console.log("Here is the base64 URL : " + url);
          alert("Check the web console for the URL");
          
          $("<a href='"+ url +"' target='_blank'></a>")[0].click();
        }, "base64");
        restore();
      });
      
      $(document).on("click", "#mp3:not(.disabled)", function(){
        alert("The conversion to MP3 will take some time (even 10 minutes), so please wait....");
        Fr.voice.export(function(url){
          console.log("Here is the MP3 URL : " + url);
          alert("Check the web console for the URL");
          
          $("<a href='"+ url +"' target='_blank'></a>")[0].click();
        }, "mp3");
        restore();
      });
    });
    The restore() function reverts the action buttons to it's original state ( Record - enabled, other buttons - disabled).

    Configure

    The location of the "recorderWorker.js" should be mentioned in the Fr.workerPath item of "jquery.voice.js" file. This is really necessary for the working. By default, it's value is :
    cdn/recorderWorker.js
    It's a relative path from the file it's ran. If the file location is http://mySite.com/project/index.html and "recorderWorker.js" is in http://mySite.com/project/cdn/recorderWorker.js , then the value should be the above "cdn/recorderWorker.js".
    From version 0.3 onwards, if you're going to use MP3 conversion, you have to configure the value of Fr.mp3WorkerPath item. The default value is :
    cdn/mp3Worker.js
    Also, for MP3 you have to define the path of libmp3lame.min.js in the first line of mp3Worker.js.

    Recording

    We start recording by calling the function Fr.voice.record(); and the user will be asked for authorizing the use of microphone. if the user accepts it, recording will start and if user declined, an alert box will be opened.
    Fr.voice.record(false, callback());
    There is also a feature to live output the recording voice to the speaker. You can do this by making the first parameter of Fr.voice.record() to boolean true.
    The recording is stopped using :
    Fr.voice.stop();
    It doesn't accept any parameters and the return value will be Fr.voice object itself.

    Export

    Fr.voice.export can be used for obtaining the recorded audio URL and the blob data of the recorder audio. Example of obtaining blob data :
    Fr.voice.export(function(blob){
      console.log(blob); // The blob data
    }, "blob");
    It is not necessarily required to make the 2nd parameter value to "blob", because by default it's set as "blob".
    You can also get the blob URL of the recorded audio :
    Fr.voice.export(function(url){
      console.log(url); // The blob URL
    }, "URL");
    An example of making an audio element to play the audio file :
    Fr.voice.export(function(url){
      $("<audio src='"+ url +"'></audio>").appendTo("body");
      $("body audio:last")[0].play();
    }, "URL");

    Base64

    (This feature has been suggested by the user payam in the comments)
    You can obtain the base64 data of the audio with $.voice.export and this data can be used to store the audio in the database.
    Fr.voice.export(function(base64){
      $.post("server.php", {"audio" : base64}, function(){
        // Sent To Server
      });
    }, "base64");
    All you got to do in the server is to store the sent data in the database.
    You can also upload the BLOB file using HTML5's FormData function. Example :
    Fr.voice.export(function(blobURL){
      var data = new FormData();
      data.append('file', blobURL);
      
      $.ajax({
        url: "server.php",
        type: 'POST',
        data: data,
        contentType: false,
        processData: false,
        success: function(data) {
          // Sent to Server
        }
      });
    }, "URL");

    MP3

    Another audio export method you can use is MP3 (from version 0.3) :
    Fr.voice.export(function(mp3){
      console.log(mp3); // The MP3 Data encoded in Base64
    }, "mp3");

    Server

    Save In Database

    Here is an example of the server side script using PDO :
    <?php
    if(isset($_POST['audio'])){
      $audio = $_POST['audio'];
      $sql = $PDO->prepare("INSERT INTO `myTable` VALUES (?)");
      $sql->execute(array($audio));
    }
    Now, the database table will have a value like this :
    data:audio/wav;base64,UklGRiQAAgBXQVZFZm10IBAAAAABAAIARKwAABCxAgAEABAAZGF0YQAAAgAAAAAAAAAAAAAAA.......
    This will be a long long value. So, make sure the database column's type is set to "LONGTEXT" in MySQL.
    When you want to play it, make an audio element with `src` attribute with this base64 value obtained from database. Example :
    <?php
    $sql = $PDO->query("SELECT `audio` FROM `myTable` WHERE `id` = 'whatever'");
    $base64 = $sql->fetchColumn();
    echo "<audio src='". $base64 ."'></audio>";

    Saving as Files

    This is the same as the previous one. Send the base64 data to the server and in the server, do as follows :
    <?php
    if(isset($_POST['audio'])){
      $audio = $_POST['audio'];
      $decoded = base64_decode($audio);
      $file_location = "./save_folder/recorded_audio.wav";
     
      file_put_contents($file_location, $decoded);
    }
    And when you need to retrieve audio, just link the src value of the audio object to the file location in server.
    If you used the HTML5's FormData() method, then use $_FILES['file'] variable to access the file.
    That's it. The Voice plugin contains only 60 lines of code, because most of the work is done by "recorder.js". The Voice plugin is just for making the complicated "recorder.js" file to a simple one.
  • You might also like

    No comments:

    Post a Comment

    Good day precious one, We love you more than anything.

Powered by Blogger.