如何用新录制的音频覆盖部分网络音频?
How can I overwrite part of web audio with new recorded audio?
我正在成功录制音频、存储音频并将其重新加载到 Audio
对象中以便在浏览器中播放。
但是,我希望能够录制新的音频并 "splice" 以特定的时间偏移将其添加到原始录音中,从该偏移开始完全替换原始录音的那部分。例如,假设我从麦克风录制了 10 秒的音频,随后,我希望 "record over" 该音频的最后 5 秒与 8 秒的全新音频,最后得到一个我可以坚持的新 bufferArray .我花了几个小时研究这个,但对如何去做仍然很模糊。如果有人有任何建议,我将不胜感激。
我能找到的最接近的示例涉及获取两个缓冲区并尝试将它们连接起来,如 this fiddle 中所示。但是,我在将此 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:
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: (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参数的start(1000)方法来限制每个blob中的毫秒数,
在这种情况下,我们知道每个数据块大约有 1 秒长(chunks.length = 记录的秒数)。为了用数据填充块数组,ondataavailable 事件处理程序
是我们的朋友 :
mediaRecorder.ondataavailable = function( event ) {
chunks.push( event.data );
}
现在,我们必须处理简单的 Arrays 而不是缓冲区数组:-D(在您的示例中,我们应该删除或覆盖最后 5 个项目并继续向其添加 blob)
3- 最后,当我们的记录准备就绪时(块数组):
我们应该使用 Blob 构造函数将它们连接在一起:
new Blob(chunks, {'type' : 'audio/webm;codecs=opus'});
希望对您有所帮助:-D
我正在成功录制音频、存储音频并将其重新加载到 Audio
对象中以便在浏览器中播放。
但是,我希望能够录制新的音频并 "splice" 以特定的时间偏移将其添加到原始录音中,从该偏移开始完全替换原始录音的那部分。例如,假设我从麦克风录制了 10 秒的音频,随后,我希望 "record over" 该音频的最后 5 秒与 8 秒的全新音频,最后得到一个我可以坚持的新 bufferArray .我花了几个小时研究这个,但对如何去做仍然很模糊。如果有人有任何建议,我将不胜感激。
我能找到的最接近的示例涉及获取两个缓冲区并尝试将它们连接起来,如 this fiddle 中所示。但是,我在将此 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:
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: (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参数的start(1000)方法来限制每个blob中的毫秒数, 在这种情况下,我们知道每个数据块大约有 1 秒长(chunks.length = 记录的秒数)。为了用数据填充块数组,ondataavailable 事件处理程序 是我们的朋友 :
mediaRecorder.ondataavailable = function( event ) {
chunks.push( event.data );
}
现在,我们必须处理简单的 Arrays 而不是缓冲区数组:-D(在您的示例中,我们应该删除或覆盖最后 5 个项目并继续向其添加 blob)
3- 最后,当我们的记录准备就绪时(块数组):
我们应该使用 Blob 构造函数将它们连接在一起:
new Blob(chunks, {'type' : 'audio/webm;codecs=opus'});
希望对您有所帮助:-D