如何将多个音频文件合成为一个音频文件(MP3)并使用JavaScript保存



这里有两个音频文件(.MP3(。A.mp3&B.mp3我想使用JavaScript合成这些文件(A&B(并保存一个文件(C(。请帮帮我。

所以基本上

  1. 创建脱机音频上下文
  2. 为您的曲目创建两个音频缓冲区
  3. 获取曲目并将其转换为音频缓冲区
  4. 您可以添加到链增益节点(或您需要的(
  5. 将此连接到上下文目标
  6. 渲染音频-您可以获得audioBuffer
  7. 将音频缓冲区转换为wav/mp3

您可以在这里找到一些帮助如何使用JavaScript将AudioBuffer转换为音频文件和堆叠

const context = new OfflineAudioContext();
const sourceA = context.createBufferSource();
const sourceB = context.createBufferSource();
const gainA = context.createGain()
const gainB = context.createGain();

sourceA.connect(gainA);
sourceB.connect(gainB);
gainA.connect(context.destination);
gainB.connect(context.destination);
const fetchTrack = async url => {
const response = await fetch(url);
const buffer = await response.arrayBuffer();
return await context.decodeAudioData(buffer)
}
const audioBuffer = await Promise.all([fetchTrack("urlA", "urlB")])
.then(([bufferA, bufferB]) => {
sourceA.buffer = bufferA;
sourceB.buffer = bufferB;
})
.then(() => {
return context.startRendering()
})
audioBufferToWav(audioBuffer)

来自教程:

function audioBufferToWav(aBuffer) {
let numOfChan = aBuffer.numberOfChannels,
btwLength = aBuffer.length * numOfChan * 2 + 44,
btwArrBuff = new ArrayBuffer(btwLength),
btwView = new DataView(btwArrBuff),
btwChnls = [],
btwIndex,
btwSample,
btwOffset = 0,
btwPos = 0;
setUint32(0x46464952); // "RIFF"
setUint32(btwLength - 8); // file length - 8
setUint32(0x45564157); // "WAVE"
setUint32(0x20746d66); // "fmt " chunk
setUint32(16); // length = 16
setUint16(1); // PCM (uncompressed)
setUint16(numOfChan);
setUint32(aBuffer.sampleRate);
setUint32(aBuffer.sampleRate * 2 * numOfChan); // avg. bytes/sec
setUint16(numOfChan * 2); // block-align
setUint16(16); // 16-bit
setUint32(0x61746164); // "data" - chunk
setUint32(btwLength - btwPos - 4); // chunk length
for (btwIndex = 0; btwIndex < aBuffer.numberOfChannels; btwIndex++)
btwChnls.push(aBuffer.getChannelData(btwIndex));
while (btwPos < btwLength) {
for (btwIndex = 0; btwIndex < numOfChan; btwIndex++) {
// interleave btwChnls
btwSample = Math.max(-1, Math.min(1, btwChnls[btwIndex][btwOffset])); // clamp
btwSample = (0.5 + btwSample < 0 ? btwSample * 32768 : btwSample * 32767) | 0; // scale to 16-bit signed int
btwView.setInt16(btwPos, btwSample, true); // write 16-bit sample
btwPos += 2;
}
btwOffset++; // next source sample
}
let wavHdr = lamejs.WavHeader.readHeader(new DataView(btwArrBuff));
let wavSamples = new Int16Array(btwArrBuff, wavHdr.dataOffset, wavHdr.dataLen / 2);
wavToMp3(wavHdr.channels, wavHdr.sampleRate, wavSamples);
function setUint16(data) {
btwView.setUint16(btwPos, data, true);
btwPos += 2;
}
function setUint32(data) {
btwView.setUint32(btwPos, data, true);
btwPos += 4;
}
}

function wavToMp3(channels, sampleRate, samples) {
var buffer = [];
var mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);
var remaining = samples.length;
var samplesPerFrame = 1152;
for (var i = 0; remaining >= samplesPerFrame; i += samplesPerFrame) {
var mono = samples.subarray(i, i + samplesPerFrame);
var mp3buf = mp3enc.encodeBuffer(mono);
if (mp3buf.length > 0) {
buffer.push(new Int8Array(mp3buf));
}
remaining -= samplesPerFrame;
}
var d = mp3enc.flush();
if(d.length > 0){
buffer.push(new Int8Array(d));
}
var mp3Blob = new Blob(buffer, {type: 'audio/mp3'});
var bUrl = window.URL.createObjectURL(mp3Blob);
// send the download link to the console
console.log('mp3 download:', bUrl);
}

最新更新