title: How to convert m3u8 URL to mp4 downloadable file in browser?
body: <p>I am writing an extension to download videos from a website. That web site has <code>mp4</code> files and <code>m3u8</code> files. I have already implemented the part to download direct <code>mp4</code> files. I stuck at converting the <code>m3u8</code> file to <code>mp4</code>. I tried lot of js packages but there are a lot of dependencies and failed even after using <code>browserfy</code>.</p>
  <h1>Current popup.js file</h1>
  <pre><code>function loadvideoList(callback){
      chrome.storage.sync.get(['courseID'], function(result) {
          if(result.courseID != 'undefined'){
              $.ajax({
                  type: 'GET',
                  url: &quot;http://localhost:80/get_videos_list/&quot;+result.courseID,
                  crossDomain: true,
                  success: function(response) {
                      document.getElementById(&quot;loading_icon&quot;).style.display='none';
                      document.getElementById(&quot;videos_list&quot;).style.display='block';
                      document.getElementById(&quot;videos_list&quot;).style.padding='10px';
                      for(var i = 0; i &lt; response.video_list.length; i++){
                          if(response.video_list[i].type == 'mp4'){
                              handleDownloadButton(response.video_list[i]);
                          }else{
                              // ************ HERE ***************
                              handleDownloadButton-m3u8Tomp4(response.video_list[i].video_url)
                          }
                      }
                  },
                  error: function (err) {
                      alert(&quot;unexpected error occured: &quot;+err.code);
                      console.log(err);
                  }
               });
          }else{
              document.getElementById(&quot;videos_list&quot;).style.display='none';
              document.getElementById(&quot;videos_list&quot;).style.padding='0';
          }
      });
  }
  
  function handleDownloadButton(json_vid){
      var node = document.createElement(&quot;DIV&quot;); 
      // node.style.marginBottom = &quot;5px&quot;
      var t = document.createElement('p');
      t.textContent = json_vid.file_name;
      t.style.width =&quot;240px&quot;;
      node.appendChild(t);
      node.style.padding = &quot;5px&quot;;
      var downloadBtn = document.createElement(&quot;BUTTON&quot;);
      downloadBtn.style.cssFloat = &quot;right&quot;;
      downloadBtn.className = &quot;btn btn-primary btn-sm download_btn&quot;;
      downloadBtn.innerHTML = &quot;Download&quot;; 
      // downloadBtn.value = json_vid.video_url;
      node.appendChild(downloadBtn);
      downloadBtn.id = json_vid.video_id;
      document.getElementById(&quot;videos_list&quot;).appendChild(node);
  
      var progress_bar = document.createElement(&quot;DIV&quot;);
      progress_bar.className = &quot;progress_container&quot;;
      node.appendChild(progress_bar);
      var moving_bar = document.createElement(&quot;DIV&quot;);
      moving_bar.className = &quot;progress_bar&quot;;
      progress_bar.appendChild(moving_bar);
      moving_bar.id = json_vid.video_id+&quot;bar&quot;;
  
      $(function(){
          $(`#${json_vid.video_id}`).click(function(){
              $(`#${json_vid.video_id}`).attr(&quot;disabled&quot;, true);
              // alert(json_vid.video_url);
              var that = this;
              var page_url = json_vid.video_url;
          
              var req = new XMLHttpRequest();
              req.open(&quot;GET&quot;, page_url, true);
              // req.withCredentials = true;
              req.addEventListener(&quot;progress&quot;, function (evt) {
                  if(evt.lengthComputable) {
                      var percentComplete = evt.loaded / evt.total;
                      // document.getElementById(&quot;download_stat&quot;).innerHTML = percentComplete;
                      // console.log(percentComplete);
                      document.getElementById(json_vid.video_id+&quot;bar&quot;).style.width = `${percentComplete*100}%`;
                      document.getElementById(json_vid.video_id).textContent = `${(percentComplete*100).toFixed(2)}%`;
                  }
              }, false);
              
              req.responseType = &quot;blob&quot;;
              req.onreadystatechange = function () {
                  if (req.readyState === 4 &amp;&amp; req.status === 200) {
                      var filename = $(that).data('filename');
                      if (typeof window.chrome !== 'undefined') {
                          // Chrome version
                          $(`#${json_vid.video_id}`).attr(&quot;disabled&quot;, false);
                          $(`#${json_vid.video_id}`).attr(&quot;onclick&quot;, &quot;&quot;).unbind(&quot;click&quot;);
                          document.getElementById(json_vid.video_id).textContent = 'Save';
                          $(function(){
                              $(`#${json_vid.video_id}`).click(function(){
                                  // alert(&quot;download is ready&quot;);
                                  var link = document.createElement('a');
                                  // link.text = &quot;download is ready&quot;;
                                  // document.getElementById(&quot;videos_list&quot;).appendChild(link);
                                  link.href = window.URL.createObjectURL(req.response);
                                  link.download = json_vid.file_name;
                                  link.click();
                              });
                          });
                          
                      } else if (typeof window.navigator.msSaveBlob !== 'undefined') {
                          // IE version
                          var blob = new Blob([req.response], { type: 'application/force-download' });
                          window.navigator.msSaveBlob(blob, filename);
                      } else {
                          // Firefox version
                          var file = new File([req.response], filename, { type: 'application/force-download' });
                          window.open(URL.createObjectURL(file));
                      }
                  }
              };
              req.send();
          });
  
      });
  }
  
  </code></pre>
  <p><code>handleDownloadButton</code> function create the button to download the direct <code>mp4</code> files. I need to implement a similar function called <code>handleDownloadButton-m3u8Tomp4</code>(see the code sample) that should first convert the <code>http://...file.m3u8</code> to a mp4 and make it also downloadable. I seek for a script in similar repos like <a href="https://github.com/puemos/hls-downloader-chrome-extension" rel="nofollow noreferrer">https://github.com/puemos/hls-downloader-chrome-extension</a>, but I was unable to do so. It would be great, If anyone could help me, Thanks in advance!</p>