lamejs icon indicating copy to clipboard operation
lamejs copied to clipboard

In browser conversion

Open devjayhall opened this issue 9 years ago • 12 comments

Firstly this is an awesome library.

I'm trying to do an in browser conversion. Don't know what's wrong here, could you please assist?

see html below

<!DOCTYPE html>
<html>
  <head>
  <style>
  #originalPlayer, #converted {display: none;}
audio {display: block;}
input, button, p {margin: 10px 0;}
  </style>
    <script src="lame.min.js"></script>
    <meta charset="utf-8">

  </head>
  <body>
    <div> 
      <input id="audioIn" type="file" />  
      <audio id="originalPlayer" controls>
        </audio>
    </div> 
    <button id="convertBt" disabled>
      Convert
    </button>
    <div id="converted">
      <p>Converted to 
      <a id="convertedLink" download></a></p>
      <audio id="convertedPlayer" controls>
      </audio>
    </div> 
    <script>

    var file;
var load = function(){
  file = this.files[0];
  var src = URL.createObjectURL(file); 
  originalPlayer.src = src;
  originalPlayer.style.display = 'block';
  convertBt.disabled = false;
};
audioIn.addEventListener('change',load);

var read = function(){
  var fileReader = new FileReader();
  fileReader.addEventListener('load', convert);
  fileReader.readAsArrayBuffer(file);
};
convertBt.addEventListener('click',read);


liblame = new lamejs();
    function encodeMono(channels, sampleRate, samples) {
        mp3enc = new liblame.Mp3Encoder(channels, sampleRate, 128);
        var remaining = samples.length;
        var maxSamples = 1152;
        for (var i = 0; remaining >= maxSamples; i += maxSamples) {
            var mono = samples.subarray(i, i + maxSamples);
            var mp3buf = mp3enc.encodeBuffer(mono);
            if (mp3buf.length > 0) {
                //TODO write to output
            }
            remaining -= maxSamples;
        }
        var mp3buf = mp3enc.flush();

    var url = 'data:audio/mp3;base64,'+encode64(mp3buf);
    convertedPlayer.src = url;
    convertedLink.href = url;

    var name = file.name.substr(0, file.name.lastIndexOf('.'));
    convertedLink.textContent = name + '.mp3';

    converted.style.display = 'block';

        console.log('done encoding');
    }

var convert = function(){
    audioData = this.result;
        wav = liblame.WavHeader.readHeader(new DataView(audioData));
        console.log('wav:', wav);
        samples = new Uint16Array(audioData, wav.dataOffset, wav.dataLen / 2);
        encodeMono(wav.channels, wav.sampleRate, samples);
};
function encode64(buffer) {
  var binary = '',
      bytes = new Uint8Array( buffer ),
      len = bytes.byteLength;

  for (var i = 0; i < len; i++) {
    binary += String.fromCharCode( bytes[ i ] );
  }
  return window.btoa( binary );
}
</script>
  </body>
</html>

devjayhall avatar Jun 24 '15 02:06 devjayhall

note you have //TODO write to output this is where you actually write mp3
after flush its the last mp3 frame - naturally it would output silence

zhuker avatar Jun 24 '15 10:06 zhuker

what would be the best way to write to output?

devjayhall avatar Jun 24 '15 10:06 devjayhall

i've tried the method below but the audio sounds a bit distorted, assist me please

var output= mp3enc.encodeBuffer(mono);

devjayhall avatar Jun 25 '15 06:06 devjayhall

what is the application you are trying to write? wav file playback?

zhuker avatar Jun 25 '15 07:06 zhuker

a wav to mp3 file converter

devjayhall avatar Jun 25 '15 07:06 devjayhall

is your wav file mono or stereo?

zhuker avatar Jun 25 '15 07:06 zhuker

so far i've been using Left44100.wav as my test file, but i would like to do stereo

devjayhall avatar Jun 25 '15 07:06 devjayhall

Is it possible to give us a hint or sample code on how to write the mp3 to disk? Trying just a short mono wav file, encoded to mp3 using lamejs. I successfully reach the end of encoding, but can't force a download with "createObjectURL". I still have much to learn with blobs, etc... Thanks in advance!

calipoop avatar Jul 28 '15 22:07 calipoop

@calipoop If you can successfully get an object url from the blob, just set that url as the href of an tag. Clicking on that will download the mp3. Set the content-type in the blob to something like application/octet-stream instead of media/mpeg to have the browser download instead of playing directly in the browser.

shanewho avatar Jul 29 '15 00:07 shanewho

Thanks @shanewho - I've successfully downloaded files before (using the HTML5 download tag targeting modern browsers). Trouble is I can't get the object url from the blob, or maybe I'm not creating the blob correctly. I've tried multiple versions of this code (I think mp3buf is the final encoded mp3):

var typedArray = new Int8Array(mp3buf);
var blob = new Blob([typedArray.buffer], {type: 'audio/mpeg'});
var url = URL.createObjectURL(blob);

The downloaded result ends up being a short burst of noise, so I must be doing something wrong...

calipoop avatar Jul 29 '15 16:07 calipoop

You can pass the mp3buf directly to the blob (in an array). Try this instead:

var blob = new Blob([mp3buf], {type: 'audio/mpeg'});
var url = URL.createObjectURL(blob);

shanewho avatar Jul 30 '15 00:07 shanewho

we have this push-to-record script implemented which whoever wrote it used a slightly modified version of this script [http://typedarray.org/from-microphone-to-wav-with-getusermedia-and-web-audio/]. it works just fine but the files it generates are in wav and huge, even in mono. I've been trying to use this library to output mp3 files instead of wav but I'm confused as to which point in that script I should insert the mp3 encoding script. I don't need to keep the wav file. I'm not ashamed to say it's outside my comfort zone and I would very much appreciate any help. thanks in advance.

TransLucida avatar Aug 02 '15 08:08 TransLucida