Javascript 如何用新录制的音频覆盖部分web音频?

Javascript 如何用新录制的音频覆盖部分web音频?,javascript,web,audio,html5-audio,web-audio-api,Javascript,Web,Audio,Html5 Audio,Web Audio Api,我正在成功地录制音频,将其存储,并将其重新加载到audio对象中,以便在浏览器中播放 但是,我希望能够录制新的音频,并在某个时间偏移量将其“拼接”到原始录制中,从该偏移量开始完全替换原始录制的该部分。例如,假设我从麦克风录制了10秒的音频,然后,我希望用8秒的全新音频“录制”该音频的最后5秒,最后得到一个可以持久保存的新缓冲阵列。我已经花了几个小时研究这个问题,但对于如何做到这一点,我仍然很模糊。如果有人有任何建议,我将不胜感激 我能找到的最接近的例子是获取两个缓冲区并尝试连接它们,如中所示。然

我正在成功地录制音频,将其存储,并将其重新加载到
audio
对象中,以便在浏览器中播放

但是,我希望能够录制新的音频,并在某个时间偏移量将其“拼接”到原始录制中,从该偏移量开始完全替换原始录制的该部分。例如,假设我从麦克风录制了10秒的音频,然后,我希望用8秒的全新音频“录制”该音频的最后5秒,最后得到一个可以持久保存的新缓冲阵列。我已经花了几个小时研究这个问题,但对于如何做到这一点,我仍然很模糊。如果有人有任何建议,我将不胜感激

我能找到的最接近的例子是获取两个缓冲区并尝试连接它们,如中所示。然而,我在将这把小提琴与我的代码以及我需要做的事情联系起来时遇到了一些困难。某些帖子提到我需要知道采样率,创建具有相同采样率的新缓冲区,并将数据从两个缓冲区复制到新缓冲区。但是在这项技术上,很少有有用的例子,我正努力从MDN文档中弄明白这一点

这是我现在正在使用的代码

const saveRecordedAudio = (e) => {
  console.log("Audio data available", e.data);
  const reader = new FileReader();
  reader.addEventListener("loadend", function() {
    // reader.result contains the contents of blob as a typed array
    let bufferArray = reader.result;
    // From: https://stackoverflow.com/questions/9267899/arraybuffer-to-base64-encoded-string
    let base64String = btoa([].reduce.call(new Uint8Array(bufferArray),function(p,c){return p+String.fromCharCode(c)},''));
    // persist base64-encoded audio data on filesystem here.
    storeRecordedAudio(base64String); // defined elsewhere and not shown here for brevity's sake
  });
  reader.readAsArrayBuffer(e.data);

  const audioUrl = window.URL.createObjectURL(e.data);
  // Put the recorded audio data into the browser for playback.
  // From: http://stackoverflow.com/questions/33755524/how-to-load-audio-completely-before-playing (first answer)
  const audioObj = new Audio (audioUrl);
  audioObj.load();

};

const recordAudio = () => {
  navigator.getUserMedia = ( navigator.getUserMedia ||
                             navigator.webkitGetUserMedia ||
                             navigator.mozGetUserMedia ||
                             navigator.msGetUserMedia);
  if (navigator.getUserMedia) {
    navigator.getUserMedia (
      { // constraints - only audio needed for this app
        audio: true
      },
      // Success callback
      function(stream) {
        const mediaRecorder = new MediaRecorder(stream);
        mediaRecorder.ondataavailable = audio.saveRecordedAudio;
      }),
      // fail callback
      function(err) {
        console.log('Could not record.');
      }
   );
  }
};


// I've already fetched a previously recorded audio buffer encoded as
// a base64 string, so place it into an Audio object for playback
const setRecordedAudio => (b64string) => {
  const labeledAudio = 'data:video/webm;base64,' + b64String;
  const audioObj = new Audio(labeledAudio);
  audioObj.load();
};

如果我正确地理解了您要做的事情,下面是我处理此问题的方法:

1-我们应该声明一个blob数组并在其中存储数据:

var chuncks = [];
2-我们需要知道记录的秒数:

我们应该使用带有timeslice参数的方法来限制每个blob中的毫秒数, 在本例中,我们知道每个数据块大约有1秒长(chunks.length=记录的秒数) 他是我们的朋友:

mediaRecorder.ondataavailable = function( event ) {
    chunks.push( event.data );
}
现在,我们必须处理简单而不是缓冲区数组:-D(在您的示例中,我们应该删除或覆盖最后5项,并继续向其中添加blob)

3-最后,当我们的录音准备就绪时(块数组):

我们应该使用构造函数将所有组件连接在一起:

new Blob(chunks, {'type' : 'audio/webm;codecs=opus'});

我希望这会有所帮助:-D

仅保存传递给许多Blob构造函数的BufferArray可能会有所帮助。如果你有原始资料。相应的数组,您可以从聚合缓冲数组中添加、减去它们,并将最后一个BA传递给新的blob构造函数,从而实现音频剪辑混合匹配的reqmt。-mp3示例,您可以在其中调整原始的arrayBuffer,以便混合、聚合各个剪辑及其源。arrayBuffrs。从一团回到arrayBuff。谢谢你的提示。这也许对我有帮助。但是,我仍然不确定是否可以将第一个bufferArray的任意部分复制到一个新数组中,然后与另一个bufferArray(使用Blob)聚合,因为我不知道如何将要复制的字节数与录制的声音的毫秒数相关联。也就是说,假设我需要5.27秒的第一个剪辑与第二个剪辑的整体结合。如何计算要从第一个bufferArray中复制多少字节?我还将查看节点后端的ffmpeg,以便为您管理时间戳。您只需要执行CLI或API调用,而ffmpeg会执行所有的时间戳操作。缺点是所有剪辑都必须位于云/后端,CLI或API才能工作。谢谢,这是一个有用的提示。我将学习start()方法。但正如我在上面所评论的,我真正需要的是能够保留第一个剪辑的任意毫秒数,并将其与第二个剪辑的整体相结合。根据你的建议,我的分辨率不是只有1吗?我的意思是,我想这些块可能有100毫秒长,可能足够小,不会导致辍学。。。但是,如果用户想添加另一个剪辑,那么永久保留所有块可能会变得很难。上面的开始(1000)只是一个例子,如果对你有效,你可以使用100而不是1000。据我所知,这是唯一简单的方法,请记住,要裁剪出音频文件的确切特定部分并不容易(正如您在上面的评论中提到的5.27s),因为它包含多个声音信号。请告诉我是否有其他简单的方法可以做到这一点。谢谢。这完全是错误的,有几个原因。首先,提供给
start
的时间片只是对浏览器的一个建议,它应该多久获取一次数据块。无法保证它们会精确计时,如果运行足够长的时间或使用低于1000毫秒的值,它很快就会与经过的时间不同步。第二个问题是Blob数据分布不均匀,因此不能随意剪切和粘贴,因为很容易删除头信息并使文件损坏。