【问题标题】:Its possible to merge two audio 'base64data' strings to create an unique audio file?可以合并两个音频“base64data”字符串来创建一个独特的音频文件吗?
【发布时间】:2021-04-22 08:41:06
【问题描述】:

是否可以合并两个音频“base64data”字符串来创建一个唯一的音频文件?

我在字符串中有两个循环音频 base64 wav,如下所示:

data:audio/x-wav;base64,UklGRuIfQVZFZm1R7SH$WP90AhICLwKT...

我想我在做一些非常愚蠢的事情,但我想知道这是否可能。

我正在尝试将两个 wav 合并为一个,我可以在音频 HTML 元素中播放。 我想提取第二个的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 );
}

【问题讨论】:

    标签: javascript audio web-audio-api


    【解决方案1】:

    我解决了!(经过两天的艰苦和疯狂的工作,并从 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)
    }
    

    【讨论】:

    • 能否请您告诉如何处理 mpeg 格式数据:audio/mpeg;base64
    【解决方案2】:

    为了扩展上面的答案,这里是一个编码字符串数组而不是两个。

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-22
      • 1970-01-01
      • 2011-12-06
      • 2017-08-19
      • 2014-09-08
      相关资源
      最近更新 更多