zhuker / lamejs Goto Github PK
View Code? Open in Web Editor NEWmp3 encoder in javascript
License: Other
mp3 encoder in javascript
License: Other
im able to record with 32kbps on firefox and chrome on MAC but doesnt work on windows. It shows it recorded but there is no sound. I dont get any errors in console.
64kbps works fine on windows.
Hi,
Love the library! Works great and haven't had any trouble getting it up and running. Recordings on desktop devices sound great! Only issue that I've encountered is that voice audio recorded on mobile devices (both Android and iOS) is about a half octave lower than real life. Do you have any idea what might be going on or how to fix the issue?
My app (still under development) is deployed at bespoke-audio.com. Feel free to login and observe the effect. I've been testing with an iPhone X and an LG Aristo (Android) and noticed it on both devices.
I'm obtaining better quality with this library than with
https://github.com/blixt/js-lameworker
but blixt uses a web worker to run the conversion in the background improving in theory the performance,
would this be possible with this library as well?
best
The README of this project mentions that the code works on "both on node and chrome", so why not put it on npm? All it takes is a package.json
file, which npm can help you make if you just run npm init
in the root of this project, and then you can npm publish
it.
Hi,
I saw your project and was very impressed.
While testing to see it's performance, I've came across an error.
"NumUsed is not defined" on lame.all.js line 15163.
Would appreciate a bug fix in order to complete the cycle.
Thanks,
Avi.
Uncaught TypeError: Cannot read property 'length' of undefined at Mp3Encoder.encodeBuffer (/home/kanhu/ElectronJS/audio-record/node_modules/lamejs/src/js/index.js:121) at encodeMono (control.js:54) at XMLHttpRequest.request.onload (control.js:84)
It is not working in my case and shows the error in mp3enc.encodeBuffer()
ERROR in ./~/use-strict/index.js
Module not found: Error: Can't resolve 'module' in '/Users/cooper/dev/closeio/closeio/closeio/static/node_modules/use-strict'
@ ./~/use-strict/index.js 1:13-30
@ ./~/lamejs/src/js/lametest.js
@ ./js/voicemail-recorder/encoder.js
@ ./js/voicemail-recorder/mic-recorder.js
@ ./js/views/settings/voicemail_recorder.js
@ ./js/test/tests/settings/voicemail_recorder.js
@ ./js/test/tests.js
If you comment the first line on lametest.js
, everythin works as expected:
// require('use-strict');
@zhuker
I am using the npm-package lamejs. I am not sure the reason you are using this module "use-strict", but it fixes when you comment this line. If you think this module is not useful anymore, I can remove and open a PR.
I'm guessing the license would be LGPL like LAME?
Chrome is about to land AudioWorklet and deprecate ScriptProcessorNode.
It would be awesome if lamejs could be used a normal WebAudio node.
Hi friends
I'm developing an audio web app for ipad and android,
I have the latest 10.1.1, build 14B150, and I have an IPAD retina model MD510LL/A
Everything used to work fine on this iPAD months ago, but not anymore.
No sounds comes out anymore from the web audio API. All is perfect on PC and on Android etc.
Only on iPAD it fails. Not only fails in my app, but also generic tests and demos around the web.
In this very same iPAD web audio was working perfectly months ago. Not anymore. I have tried everything including a reset to factory state and reinstalling the latest 10.1.1 14B150. Nothing.
I read somewhere that this problem had been fixed on the new build 14B150.
Well, No. It is not. I have 14B150 and web audio continues broken.
Even generic tests like this one fail: https://www.sharphosting.uk/ipad_test.html#
any ideas? thank you very much
I need to encode an mp3 file with bitrate 8kbps and sample rate 8000 Hz.
Here is an ffmpeg command that produces the desirable quality:
ffmpeg -i in.mp3 -codec:a libmp3lame -b:a 8k -ar 8000 out.mp3
Modifying worker-realtime.js
for mic.html
example on line 22 produces the result that sounds like slow motion.
mp3Encoder = new lamejs.Mp3Encoder(1, 44100/2, config.bitRate || 123);
Update:
I found out that there was a related pull request from 2015 that was never merged
#11
@zhuker are you still maintaining this great library?
Hi, I'm using chunk based encoding method where I'm grabbing the WAV blob after 1 second intervals, encoding it and then appending the encoded mp3 data to an array where I build the final blob with the encoded mp3 data.
When the chunks of the WAV files are listened too they're clear but the mp3's seem to have a little click between each of the chunks after encoding. (You can listen to the mp3 here https://clyp.it/vbaf0zg1)
This is my encoding code which is pretty much the same as a lot of peoples.
for (var i = 0; i < leftSamples.length; i += sampleBlockSize) {
buffer = mp3encoder.encodeBuffer(
leftSamples.subarray(i, i + sampleBlockSize),
rightSamples.subarray(i, i + sampleBlockSize)
);
if (buffer.length > 0) {
mp3Data.push(new Int8Array(buffer));
}
}
buffer = mp3encoder.flush();
// Push any leftover blocks into the mp3 data array
if (buffer.length > 0) {
mp3Data.push(new Int8Array(buffer));
}
When I log the mp3Data
once every chunk is encoded I get something that looks like this, if anyone wants to see what the data looks like.
I'm not sure if theres anything that could be stripped from the chunk to make them fit together more smoothly? Or any ideas why this could be happening?
I appreciate any help and thanks for such a great library!
James
Hi,
I'm using timeSlice
with the StereoAudioRecorder
and it seems to return different sized blobs for each interval of one second sometimes which is causing some audio glitches in the final output. I'm just wondering if anyone knows what could possibly cause this?
Some data appears to get lost which is causing issues later on with mp3 encoding.
This is the output of each second of recording, as you can see, most of the blobs are the same size apart from the odd few which is throwing things off.
Any help would be greatly appreciated, thanks very much!
James
Hi guys,
When I create the buffer into a file using the lamejs and opennig on VLC player to see the media info the codec says I'm using MPEG Audio layer 1/2 (mpga). Is this a mp2 not a mp3, right?
How can I write using a mp3 codec? Sorry I'm a little confused about it.
I am using your lamejs for recording voice and convert into mp3.
Below is audio link what i am exactly facing the problem after recording
Distorted Audio : https://www.ptemocktest.com/pte/uploaddata/answer-audio/d3cd0a153620a3ddb12e09c31c3f7bbd.mp3
This is configuration i am using to record
var mp3Encoder, maxSamples = 1152, samplesMono, config, dataBuffer;
var clearBuffer = function () {
dataBuffer = [];
};
var appendToBuffer = function (mp3Buf) {
dataBuffer.push(new Int8Array(mp3Buf));
};
var init = function (prefConfig) {
config = prefConfig || {debug: true};
mp3Encoder = new lamejs.Mp3Encoder(1, config.sampleRate || 48000, config.bitRate || 128);
clearBuffer();
};
Please help where i am doing wrong with configuration.
In using the emscripten libmp3lame, I've been feeding it Float32Array buffer output straight from the user's microphone output
this.node.onaudioprocess = function(e){
//Data buffer from mic ouput
var buffer = e.inputBuffer.getChannelData(0);
var output Lame.encode_buffer_ieee_float(mp3codec, buffer, buffer);
};
And the output is a UInt8Array which, when constructed into a blob, gives a nice neat mp3 file.
When I feed the same array into lamejs, it gives me silence:
var output = mp3encoder.encodeBuffer(buffer);
I see in the examples that you feed an Int16Array into the encoder, and when I convert the Float32Array into a Int16Array I get the same output - just silence. any idea what I'm doing wrong?
Thank you so much for this great library!
As a first step, I'm trying to run your realtime-worker example. After the console prints "MP3 conversion worker started." I get the error "Uncaught TypeError: lame.Mp3Encoder is not a constructor." It's being thrown from these lines in the worker:
lame = new lamejs();
mp3Encoder = new lame.Mp3Encoder(1, config.sampleRate || 44100, config.bitRate || 123);
The lamejs construction is returning an empty object. I must be doing something stupid or else someone would have noticed this. Could you give me a nudge in the right direction? Thank you!
I have a problem regarding lamejs working together with RecordRTC. So i found RecrodRTC and i think its a great project to record audio and video in a browser. So i tried RecordRTC and the lib created a wav file (blob) and it was working well. But when i add that data as Int16Array to lamejs i get no data back the result has every time 835 byte.
The input data and length look correct butt i get not result.
does anyone know a solution for that problem? Here my code.
// Stop recording and get data
recordRTC.stopRecording(function() {
var recordedBlob = recordRTC.blob;
var reader = new FileReader();
reader.onload = function(event) {
var buffer = event.target.result;
var mp3Blob = new Blob([encodeMP3(buffer)], {type: 'audio/mp3'});
setUploadAudioData(mp3Blob);
};
reader.readAsArrayBuffer(recordedBlob);
});
var encodeMP3 = function(buffer) {
var samples = new Int16Array(buffer);
console.log(samples);
console.log(samples.byteLength);
mp3encoder = new liblame.Mp3Encoder(1, 44100, 128);
mp3encoder.encodeBuffer(samples);
var mp3Data = mp3encoder.flush();
console.log(mp3Data);
return mp3Data;
};
Hi, thanks for your perfect library :)
I know nothing about audio encoding and I am trying to use this library for low the bitrate of an mp3 file in browser.
input: mp3 320kbps -> output: mp3 128kbps
I assigned a mp3 file as arraybuffer to the samples variable but i only obtain noise.
var samples = new Int16Array(mp3file);
is there something similar to WavHeader.readHeader() but for mp3?
what should I do?
Can you help me please? I appreciate your help so much
I tried to implement https://github.com/zhuker/lamejs/blob/master/example.html
But the resulting mp3 is right length but has no audio.
The sampleRate being returned in chrome windows is 6000kb.
I tried with 44100 but then it sounds like fast forward audio.
Does the library works on Firefox?
I'm receiving an error while loading it.
Thanks!
Would like to discuss 3 things here:
I finally made things work with this great library. I was having the exact same issue than Dewsworld, lots of noise in the output, and i solved it exactly as he did as well, i think this is important to raise for others to know. I had to change
samples = new Uint16Array(audioData, wav.dataOffset, wav.dataLen / 2);
to
samples = new Int16Array(audioData, wav.dataOffset, wav.dataLen / 2);
I have noticed that if as input i use a wav with 2 channels instead of 1, the sound will come out two times slower, how can i solve this? Converting 1 channel no probs, but converting a 2 channel wav to a 1 channel mp3, how can i avoid the sound output being 2 times slower?
And now where i need your help. So i can now convert wav to mp3 without noise and good quality with this library. But now what i need to convert is the microphone input. Specifically i would like to convert it in real time as i record, just as Blixt did here:
https://github.com/blixt/js-lameworker
(im not using Blixt library to convert to mp3 because it gave me different issues and yours is also smaller)
In this library, to convert in real time as the microphone is recording, Blixt does this
(i also use howler.js for the webaudioapi stuff)
// Set up Web Audio API to process data from the media stream (microphone).
var context = new AudioContext();
var microphone = context.createMediaStreamSource(stream);
var processor = context.createScriptProcessor(0, 1, 1);
// Add all buffers from LAME into an array.
var buffers = [];
processor.onaudioprocess = function (event) {
// Send microphone data to LAME for MP3 encoding while recording.
var array = event.inputBuffer.getChannelData(0);
lame.encodeBuffer(LAME_HANDLE, array, array, function (error, buffer) {
buffers.push(buffer);
});
};
etc etc
So the question is how can i do the same with this library?
var context = new AudioContext();
var microphone = context.createMediaStreamSource(stream);
var processor = context.createScriptProcessor(0, 1, 1);
// Add all buffers from LAME into an array.
var buffers = [];
processor.onaudioprocess = function (event) {
// So this gets the stuff coming from microphone on each cycle
var array = event.inputBuffer.getChannelData(0);
// but i need to replace this here below with the correct one from your library, could you help me with the right command here? thank you :)
//lame.encodeBuffer(LAME_HANDLE, array, array, function (error, buffer) {
// And this adds to the buffer
buffers.push(buffer);
});
};
By the way, in your view is it practical to do this, to convert the micro input to mp3 on the fly at the same time as we record the input? I had to give up the Blixt library because the output was cracking and distorted etc etc i wonder if it had to do with that
In any case now that i can convert with no probs wav to mp3 with your library, i'm looking to understand how to conver the microphone input via webaudioapi like blixt does on the fly, like above, and also maybe after the recording has ended
thank you for your help
Jav
:)
I import this library with ES6 like this
import lamejs from 'lamejs';
Im using webpack and babel to compile my ES6 code, this all works fine. But when I run my Mocha tests i run into the following error:
node_modules/lamejs/src/js/index.js:19
Lame = require('./Lame.js');
^
ReferenceError: Lame is not defined
Shouldn't the following classes be defined as a variable?
Lame = require('./Lame.js');
Presets = require('./Presets.js');
GainAnalysis = require('./GainAnalysis.js');
QuantizePVT = require('./QuantizePVT.js');
Quantize = require('./Quantize.js');
Takehiro = require('./Takehiro.js');
Reservoir = require('./Reservoir.js');
MPEGMode = require('./MPEGMode.js');
BitStream = require('./BitStream.js');
I'll make a PR for this, but please let me know if I'm missing something
I have mp3 urls and I want to split the file inside browser, can I stream from specific time and save it as mp3 again?
How to add ID3 Tags with lamejs?
thank you
Many thanks for this great library.
I'm trying to encode the microphone recorded from the browser using lamejs.
The encoded chunks are then sent to another browser tab using a nodejs websocket server and decoded using audioContext.decodeAudio which works great.
The websocket connections are handled in a web worker thread and if i send the raw pcm data i have no glitches in the audio output. But using the encoded mp3 chunks i get crackling noises.
I noticed that the mp3 chunks are around 50ms longer in duration the decoded chunk is also around 2000 bytes bigger.
I tested to encode pcm samples of a fixed value. The decoded audio then seems to have a padding of around 25ms at the beginning and end of the mp3 which seems to be just how mp3 works according to lame faq.
So i tried to just ignore 25ms at the beginning and end and the crackling got better but is still there.
My question is: Is there a way that i know exactly how many samples or duration has been added to the beginning and end of the mp3? Is it encoded in the mp3 as mentioned in the faq from above or is it some kind of fixed value?
Kind regards
Hello,
i have a small problem converting the wav data to MP3 and i hope someone can help me. If my recording is too long and i use only
var mp3buf = mp3encoder.encodeBuffer(buffer);
i get no result and some strange problems. So i tried to change my code to the chunked version.
var mp3Data = [];
// Get Buffer and create new mp3encoder
var buffer = new Int16Array(this.result);
var mp3encoder = new lame.Mp3Encoder(1, recordRTC.sampleRate, 128);
// Encode main data
var sampleBlockSize = 1152;
for (var x = 0; x < buffer.length; x += sampleBlockSize) {
var sampleChunk = buffer.subarray(x, x + sampleBlockSize);
var mp3buf = mp3encoder.encodeBuffer(sampleChunk);
if (mp3buf.length > 0) {
mp3Data.push(mp3buf);
}
}
I don't get valid mp3 data then when i look at the output if mp3Data i get an array that contains many of Int8Array for every encoded chunk i think that is not correct.
When i use only the one line i get Output like this
[Int8Array[33333]]
0: Int8Array[13123]
1: Int8Array[123]
That looks like the left and right channel if u use then mp3Data[0] its working well and i have the mp3 data. But like i said its not working if the recording is too long. What is wrong?
I am reading left and right channel data from an arraybuffer via web audio API, modifying the individual channel data and trying to write them back to a MP3 blob.
The problem is, I am getting a zero valued MP3 but of the correct duration.
Here's my complete worker code:
(function () {
importScripts('./lame.min.js');
var mp3Data = [];
var encode = function (samplesLeft, samplesRight) {
var mp3Encoder = new lamejs.Mp3Encoder(2, 44100, 128);
var mp3buf = mp3Encoder.encodeBuffer(samplesLeft, samplesRight);
mp3Data.push(mp3buf);
finish(mp3Encoder);
};
var finish = function (mp3Encoder) {
var mp3buf = mp3Encoder.flush();
mp3Data.push(mp3buf);
self.postMessage({cmd: 'end', buf: mp3Data });
mp3Data = [];
};
self.onmessage = function (e) {
if (e.data.cmd == 'encode') {
encode(e.data.samplesLeft, e.data.samplesRight);
}
};
})();
One difference, I can see is this:
While you use Int16Array as samples, my mp3 samples buffer (extracted from buffer, read via web audio api) are Float32Array. Could this be the cause of all zero valued output.
Thanks
Can someone tell me how to encode a mp3 file out of Float32Array in typescript (Angular 6) without using lame? (i tried using Lame but it displayed errors, for files generated when installing Lame, when compiling the project.)
please help.
You write
Fast mp3 encoder written in JavaScript. On my machine it works 20x faster than realtime
but I have a problem with it.
I have demo.mp3 file with total duration 54 sec
On my machine
time sox demo.mp3 -C 256 ~/demo2.mp3
real 0m1.557s
user 0m1.527s
sys 0m0.018s
When I use lamejs encoding spend ~50 sec and it's too much!
Now I try to use another js encoder (https://higuma.github.io/mp3-lame-encoder-js/) and it spent only ~3sec!
What I do wrong? My code:
buffer // <-- decoded with web audio api AudioBuffer
let mp3buf = [];
let mp3encoder = new lamejs.Mp3Encoder(buffer.numberOfChannels, buffer.sampleRate, 192)
mp3buf.push(mp3encoder.encodeBuffer(buffer.getChannelData(0), buffer.getChannelData(1)))
mp3buf.push(mp3encoder.flush())
let blob = new Blob(mp3buf, { type: 'audio/mp3' })
Recent examples were added in #17.
While the sound of index.html
is really nice, the one in mic.html
is noisy.
You can try yourself there:
https://rawgit.com/zhuker/lamejs/master/worker-example/mic.html
Currently it's not possible to use this library with webpack. If I try to require it, I get errors like:
ERROR in ./~/lamejs/src/js/lametest.js
Module not found: Error: Cannot resolve module 'fs' in node_modules/lamejs/src/js
@ ./~/lamejs/src/js/lametest.js 3:5-18
I don't really want to use lame.all.js
or lame.min.js
directly, webpack should be able to build the library.
The mic.html example (that uses mic.js) seems to cut the audio off about half a second too early. The amount it cuts off varies so I assume this related to the audio buffer boundary and the part of the audio stream isn't being passed to the lame encoder.
Any advice on what's wrong with mic.js that'll fix this? If I can fix this problem for myself I can contribute a pull request fixing it in the example as well.
hello
how to use GainAnalysis module ?
thanks
First of all i would like to thank for providing such a nice recorder. It is working perfectly fine in chrome and mozilla in android devices. But it not at all working in android default browser. Please help me out in making this working at default browser of android.
Hi Guys,
I have an requirement of Converting the Mp3 file from Stereo to Mono.
I get the MP3 Stereo data in to buffer using aurora.js and now i want create a mono mp3 out of that, How should i pick data for mono out of 2 channels.
Hi,
I have a question, it's not really a bug, but i want to know if you have a example for using lamejs on a nodeJS server to convert a .wav file to a . mp3 file without the browser ?
Thanks a lot.
Best Regards.
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>
This is great work Alex, the speed is perfect. I've got a problem with the worker-example however, the resulting mp3 seems to have an intermittent rhythmic click presumably a side effect of the buffers getting joined together. It's not that noticeable but becomes more obvious when gain is applied afterwards.
Any ideas how to eliminate this, or somehow 'smooth/blend' the buffer edges into one another to achieve the same thing?
Hi there,
This plugin is great and way easier to use than the other options.
I've been trying to no avail to convert a local wav file to a local mp3 file with this plugin.
This is what I have. It is writing an mp3 but the mp3 is just silence for the exact length of the wav file. Could you help me understand what I'm doing wrong and if there's an easier way?
window.resolveLocalFileSystemURL('../local/audio/recording.wav', (fileEntry) => {
fileEntry.file((resFile) => {
var reader = new FileReader();
reader.onload = function () {
var arrayBuffer = reader.result;
console.log('array buffer:');
console.log(arrayBuffer);
var audioData = arrayBuffer;
var wav = lamejs.WavHeader.readHeader(new DataView(audioData));
console.log('wav:', wav);
var samples = new Int16Array(audioData, wav.dataOffset, wav.dataLen / 2);
var buffer = [];
var mp3enc = new lamejs.Mp3Encoder(wav.channels, wav.sampleRate, samples);
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) {
buffer.push(new Int8Array(mp3buf));
}
remaining -= maxSamples;
}
var d = mp3enc.flush();
if(d.length > 0){
buffer.push(new Int8Array(d));
}
console.log('done encoding, size=', buffer.length);
var blob: any = new Blob(buffer, {type: 'audio/mpeg'});
blob.name = 'recording
var bUrl = window.URL.createObjectURL(blob);
console.log('Blob created, URL:', bUrl);
console.log(blob);
File.createFile('../local/file/recording.mp3', true).then((fileEntry) =>{
fileEntry.createWriter((fileWriter) => {
fileWriter.onwriteend = () => {
console.log('File writer - write end event fired');
};
fileWriter.onerror = (e) => {
console.log('Error with file writer: ' + e.toString());
}
fileWriter.write(blob);
})
})
}
reader.readAsArrayBuffer(resFile);
})
})
Hi,
would you care to clarify which version of the LGPL lamejs
is licensed under? E.g. 2.1 or 3.0? A good idea might be to mention it in README.md
and put a link to the full license in the LICENSE
file.
Hello, thank you for such a useful lib. I was converting to an mp3 and found the audio quality is bad and too much noisy. That's my code of example.html. I am quite unsure if it's my bug or something is getting wrong.
<body>Encoding mp3 from <code>testdata/Left44100.wav</code>
<div id="recordingslist"></div>
</body>
<script src="lame.all.js"></script>
<script>
liblame = new lamejs();
function encodeMono(channels, sampleRate, samples) {
var out = new Int8Array(samples.length/2);
var index=0;
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) {
out.set(mp3buf, index);
index = index + mp3buf.length;
}
remaining -= maxSamples;
}
var mp3buf = mp3enc.flush();
var blob = new Blob([out.buffer], {type: 'audio/mpeg'});
var url = URL.createObjectURL(blob);
var url = URL.createObjectURL(blob);
var li = document.createElement('li');
var au = document.createElement('audio');
var hf = document.createElement('a');
au.controls = true;
au.src = url;
hf.href = url;
hf.download = new Date().toISOString() + '.mp3';
hf.innerHTML = hf.download;
li.appendChild(au);
li.appendChild(hf);
recordingslist.appendChild(li);
console.log('done encoding');
}
var wavFile = "testdata/Left44100.wav";
var request = new XMLHttpRequest();
request.open("GET", wavFile, true);
request.responseType = "arraybuffer";
// Our asynchronous callback
request.onload = function () {
audioData = request.response;
wav = liblame.WavHeader.readHeader(new DataView(audioData));
samples = new Uint16Array(audioData, wav.dataOffset, wav.dataLen / 2);
encodeMono(wav.channels, wav.sampleRate, samples);
};
request.send();
// var encoder = lib.Mp3Encoder(1, 44100, 128);
</script>
</html>
Front padding should be filled with all zeroes after decoding. It is java -> js porting issue.
If the source and the desired target sample rate differ, will this script resample to target rate?
I just write some code like this.
How can I save buffer to a mp3 file with nodejs?
var lamejs = require('lamejs');
var fs = require('fs');
function encodeMono(channels, sampleRate, samples) {
var buffer = [];
var mp3enc = new lamejs.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) {
buffer.push(new Int8Array(mp3buf));
}
remaining -= maxSamples;
}
var d = mp3enc.flush();
if(d.length > 0){
buffer.push(new Int8Array(d));
}
console.log('done encoding, size=', buffer.length);
// fs.open('test.mp3', 'w', (err, fd) => {
// if (err) {
// console.log(err);
// return;
// }
// fs.write(fd, buffer, (err, written, buffer) => {
// if (err) {
// console.log(err);
// return;
// }
// console.log('written:', written);
// });
//
// });
}
function toArrayBuffer(buf) {
var ab = new ArrayBuffer(buf.length);
var view = new Uint8Array(ab);
for (var i = 0; i < buf.length; ++i) {
view[i] = buf[i];
}
return ab;
}
var wavFile = "./Left44100.wav";
//var request = new XMLHttpRequest();
//var request = XMLHttpRequest;
fs.readFile(wavFile, (err, data) => {
let audioData = toArrayBuffer(data);
console.log(audioData);
var wav = lamejs.WavHeader.readHeader(new DataView(audioData));
console.log('wav:', wav);
var samples = new Int16Array(audioData, wav.dataOffset, wav.dataLen / 2);
encodeMono(wav.channels, wav.sampleRate, samples);
});
This is a great library, I'm trying to use it to do something similar to what blixt does in
https://github.com/blixt/js-lameworker
that is to encode the microphone input directly to a blob in memory that i then send to server to be saved as mp3 file there
is this possible with your library? I had issues wth blixt library and i think yours seems more polished and faster so i really would love to try your library but encoding directly the microphone input through web Audio API to an mp3 blob that i can send to server
by the way i hear that mp3 patents expired in september 2015, do you know anything about that? is mp3 now free of patents?
thank you sooo much
First of all thank you for that great lib!
I want to convert a 1411 kbps pcm_s16le 44100 Hz stereo, s16(recorded with recordRTC) to mp3.
The problem is that the wav file sounds perfect but the converted mp3 file sounds bad, sounds lower than the original and is twice as long.
Full js: http://julius.athenstaedt.net/rep/rcx2/background.js
recorded wav: http://julius.athenstaedt.net/rep/wav%20(16).wav
converted mp3 http://julius.athenstaedt.net/rep/mpeg%20(14).mp3
function convertToMP3(audioBlob) {
//audioBlob is the recorded Blob from recordRTC api
//with FileReader get the dataform like with XMLHttpRequest (maybe the problem?)
console.log(audioBlob);
var audioData;
fileReader = fileReader || new FileReader();
fileReader.onload = function() {
audioData = this.result;
var wav = lamejs.WavHeader.readHeader(new DataView(audioData));
console.log("wav:",wav);
mp3encoder = new lamejs.Mp3Encoder(wav.channels, wav.sampleRate, 128);
var mp3Data = [];
left = new Int16Array(audioData, wav.dataOffset, wav.dataLen /2);
right = new Int16Array(audioData, wav.dataOffset, wav.dataLen /2);
sampleBlockSize = 1152;
var mp3buf=[];
for (var i = 0; i < left.length; i += sampleBlockSize) {
leftChunk = left.subarray(i, i + sampleBlockSize);
rightChunk = right.subarray(i, i + sampleBlockSize);
mp3buf = mp3encoder.encodeBuffer(leftChunk, rightChunk);
if (mp3buf.length > 0) {
mp3Data.push(new Int8Array(mp3buf));
}
}
mp3buf = mp3encoder.flush(); //finish writing mp3
if (mp3buf.length > 0) {
mp3Data.push(new Int8Array(mp3buf));
}
var blob = new Blob(mp3Data, {
type: 'audio/mp3'
});
var url = window.URL.createObjectURL(blob);
saveFile(url, "mpeg.mp3");
};
fileReader.readAsArrayBuffer(audioBlob);
}
Thank You for help!!
(sorry for bad english)
Tried using the library but always got the same error in my script using Chrome: Uncaught TypeError: Cannot read property 'readHeader' of undefined.
Then copied example file to my server and tried reading a mono 8 and 16 bit wav file. Same error at line:
var wav = lamejs.WavHeader.readHeader(new DataView(audioData));
The file is being read in correctly. The audio data is there. Just not finding the error in the library.
Thanks in advance for this lovely codebase - imho much better than the others available. I'm able to encode an external wav file using one of the new examples. But what about audio (audioBuffers) created with the Web Audio API? I tried passing audioBuffer.getChannelData(0) as samples, but it's not working out. I know getChannelData() returns 32-bit float - could that be the problem? My code below... @zhuker @shanewho or anybody! Any thoughts?
var lib = new lamejs();
var channels = 1; //1 for mono or 2 for stereo
var sampleRate = 44100; //44.1khz (normal mp3 samplerate)
var kbps = 128; //encode 128kbps mp3
var mp3encoder = new lib.Mp3Encoder(channels, sampleRate, kbps);
var mp3Data = [];
var samples = buffer.getChannelData(0);
console.log(samples);
var sampleBlockSize = 1152; //can be anything but make it a multiple of 576 to make encoders life easier
var sampleChunk;
for(var i = 0; i < samples.length; i += sampleBlockSize){
sampleChunk = samples.subarray(i, i + sampleBlockSize);
var mp3buf = mp3encoder.encodeBuffer(sampleChunk);
if(mp3buf.length > 0){
mp3Data.push(mp3buf);
}
}
var mp3buf = mp3encoder.flush(); //finish writing mp3
if(mp3buf.length > 0){
mp3Data.push(mp3buf);
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.