可以合并两个音频“base64data”字符串来创建一个独特的音频文件吗?
我在字符串中有两个循环音频 Base64 wav,如下所示:
data:audio/x-wav;base64,UklGRuIfQVZFZm1R7SH$WP90AhICLwKT...
我想我正在做一些非常愚蠢的事情,但我想知道这是否可能。
我正在尝试将两个 wav 合并为一个可以在音频 HTML 元素中播放的 wav。 我想提取第二个的base64数据以合并到第一个,然后播放它,但导航器返回错误。
这是我的JavaScript代码:
var audio_Data1 = base64_audio1;
var audio_Data2 = base64_audio1.split(',')[1];
var audio_final = audio_Data1 + audio_Data2;
audioControl.src = audio_final;
audioControl.play();
感谢您的建议 谢谢你!
编辑:
我正在尝试解码 Base64 块以缓冲数据并连接缓冲区以再次编码为 Base64。
问题:返回的base64是“AA==”
我认为“AA==”是0字节。然后当我连接缓冲区时我做了一些坏事:
var myB64Data = myB64WavString.split(',');
var myB64Chunk = myB64Data[1];
var myBuffer1 = base64ToArrayBuffer(myB64Chunk);
var myBuffer2 = ""; //Same process
var myFinalBuffer = [];
myFinalBuffer.push.apply(myFinalBuffer, myBuffer1);
myFinalBuffer.push.apply(myFinalBuffer, myBuffer2);
var myFinalB64 = 'data:audio/x-wav;base64,' + arrayBufferToBase64(myFinalBuffer);
console.log( myFinalB64 );
控制台返回下一个:“data:audio/x-wav;base64,AA==”
我的编码/解码的 JavaScript 工作函数:
function base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array( len );
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
function arrayBufferToBase64( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}
我解决了它!(经过艰苦而疯狂的工作两天后,并通过从 Convert AudioBuffer to ArrayBuffer / Blob for WAV Download 复制答案) 我希望它可以帮助您节省我为此开发的所有工作;)
var myB64Data = myB64WavString.split(',');
var myB64Chunk = myB64Data[1];
var myBuffer1 = base64ToArrayBuffer(myB64Chunk);
var myBuffer2 = ""; //Same process
var myFinalBuffer = appendBuffer (myBuffer1, myBuffer2);
var myFinalBuffer = getWavBytes( arrBytesFinal, {
isFloat: false, // floating point or 16-bit integer
numChannels: 2, //1 for mono recordings
sampleRate: 48000, //Depends on your file audio bitrate !! 32000
})
var myFinalB64 = 'data:audio/x-wav;base64,' + arrayBufferToBase64(myFinalBuffer);
console.log( myFinalB64 );
//Then you can asign to an audio HTML control
myAudioControl.src = myFinalB64;
附加功能:
function appendBuffer(buffer1, buffer2) {
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(new Uint8Array(buffer1), 0);
tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
return tmp;
};
function getWavBytes(buffer, options) {
const type = options.isFloat ? Float32Array : Uint16Array
const numFrames = buffer.byteLength / type.BYTES_PER_ELEMENT
const headerBytes = getWavHeader(Object.assign({}, options, { numFrames }))
const wavBytes = new Uint8Array(headerBytes.length + buffer.byteLength);
// prepend header, then add pcmBytes
wavBytes.set(headerBytes, 0)
wavBytes.set(new Uint8Array(buffer), headerBytes.length)
return wavBytes
}
// adapted from https://gist.github.com/also/900023
// returns Uint8Array of WAV header bytes
function getWavHeader(options) {
const numFrames = options.numFrames
const numChannels = options.numChannels || 2
const sampleRate = options.sampleRate || 44100
const bytesPerSample = options.isFloat? 4 : 2
const format = options.isFloat? 3 : 1
const blockAlign = numChannels * bytesPerSample
const byteRate = sampleRate * blockAlign
const dataSize = numFrames * blockAlign
const buffer = new ArrayBuffer(44)
const dv = new DataView(buffer)
let p = 0
function writeString(s) {
for (let i = 0; i < s.length; i++) {
dv.setUint8(p + i, s.charCodeAt(i))
}
p += s.length
}
function writeUint32(d) {
dv.setUint32(p, d, true)
p += 4
}
function writeUint16(d) {
dv.setUint16(p, d, true)
p += 2
}
writeString('RIFF') // ChunkID
writeUint32(dataSize + 36) // ChunkSize
writeString('WAVE') // Format
writeString('fmt ') // Subchunk1ID
writeUint32(16) // Subchunk1Size
writeUint16(format) // AudioFormat
writeUint16(numChannels) // NumChannels
writeUint32(sampleRate) // SampleRate
writeUint32(byteRate) // ByteRate
writeUint16(blockAlign) // BlockAlign
writeUint16(bytesPerSample * 8) // BitsPerSample
writeString('data') // Subchunk2ID
writeUint32(dataSize) // Subchunk2Size
return new Uint8Array(buffer)
}
为了扩展上面的答案,这里是如何对一组编码字符串而不是两个字符串进行操作。
function joinBuffers(buffers) {
const byteLength = buffers
.map((buffer) => buffer.byteLength)
.reduce((prev, curr) => prev + curr);
var tmp = new Uint8Array(byteLength);
var length = 0;
for (let i = 0; i < buffers.length; i++) {
const buffer = buffers[i];
tmp.set(new Uint8Array(buffer), length);
length += buffer.byteLength;
}
return tmp;
}
上面的答案对我不起作用,但这个简单的答案对我有用:
只需解码每个 B64 字符串
// Decode the String
var decodedString0 = atob(encodedString0);
var decodedString1 = atob(encodedString1);
将它们合并在一起,然后编码回来,
var decodedStringMerge = decodedString0 + decodedString1
var ecodedStringMergeB64 = btoa(decodedStringMerge)
console.log(ecodedStringMergeB64);
播放合并的音频..
使用过时的
atob
更新答案:
const decoded1 = Buffer.from(encodedString1, "base64");
const decoded2 = Buffer.from(encodedString2, "base64");
const encodedCombined = Buffer.concat([decoded1, decoded2]).toString("base64");