【发布时间】:2023-03-28 15:26:01
【问题描述】:
我正在成功录制音频、存储音频并将其重新加载到Audio 对象中以便在浏览器中播放。
但是,我希望能够录制新音频并在某个时间偏移处将其“拼接”到原始录音中,从该偏移处完全替换原始录音的那部分。例如,假设我从麦克风录制了 10 秒的音频,然后,我希望用 8 秒的全新音频“录制”该音频的最后 5 秒,最终得到一个我可以保留的新 bufferArray。我已经花了几个小时研究这个,但仍然很模糊如何做到这一点。如果有人有任何建议,我将不胜感激。
我能找到的最接近的例子涉及获取两个缓冲区并尝试将它们连接起来,如this fiddle。但是,我在将这个小提琴与我的代码以及我需要做的事情联系起来时遇到了一些困难。某些帖子提到我需要知道采样率,创建具有相同采样率的新缓冲区,并将数据从两个缓冲区复制到新缓冲区中。但是关于这种技术的工作示例很少,我正在努力从 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();
};
【问题讨论】:
-
只保存传递给许多 Blob 构造函数的 bufferArrays 可能会有所帮助。如果你有原件。相应的数组,您可以从聚合的 bufferArray 中添加、减去它们,并将最后一个 BA 传递给新的 blob 构造函数,从而实现音频剪辑的混合和匹配请求。
-
github.com/higuma/mp3-lame-encoder-js/blob/master/src/… - mp3 示例,您可以在其中调整 raw 、 arrayBuffer 以混合、聚合各个剪辑及其原点。数组缓冲区。
-
npmjs.com/package/blob-to-buffer 从 blob 返回到 arrayBuff。
-
感谢您的提示。这确实对我有帮助。但是,我仍然不确定是否可以将第一个 bufferArray 的任意部分复制到一个新数组中,然后与另一个 bufferArray 聚合(使用 Blob),因为我不知道如何关联要复制的字节数,到毫秒的录音。即,假设我需要 5.27 秒的第一个剪辑与整个第二个剪辑相结合。我将如何计算从第一个 bufferArray 中复制多少字节?
-
我还会查看节点后端的 ffmpeg 来为您管理时间戳。你只会做 CLI 或 API 调用,而 ffmpeg 会做所有时间戳的东西 4 u。缺点是所有剪辑都必须位于云/后端,CLI 或 API 才能正常工作。
标签: javascript web audio html5-audio web-audio-api