如何缩短(从前面)一系列音频blob并仍然具有可播放的音频。
我最终尝试使用JS MediaRecorder API记录连续45秒的音频循环。用户可以按下一个按钮,最后45秒的音频将被保存。我可以录制,播放和下载单个录音。
当我从MediaRecorder中获得一个名为chunks
的1000个blob数组并使用chunks.slice(500, 1000)
时,生成的blob数组不能用于播放或下载音频。
奇怪的是chunks.slice(0,500)
仍然可以正常工作。
let chunks = [];
navigator.mediaDevices.getUserMedia({ audio: true })
.then((stream) => {
const mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (e) => chunks.push(e.data);
}
// At some later time, attempt to trim
const trimmedAudio = chunks.slice(500, 1000)
const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
const audioURL = URL.createObjectURL(blob);
// audio is an audio DOM element
audio.src = audioURL;
// At this point the audio won't play
因为从开始到中间的切片工作,我尝试反转,切片和反转回原始方向。失败。
我尝试在开始时留下16个斑点并移除一些中间部分。失败。
我的预感是blob不能统一包含数据,需要转换为ArrayBuffer或特定的TypedArray。我尝试了很多这些转换,但仍然没有找到解决方案。任何指导都将非常感激,因为我可以找到任何文档来编辑记录的blob数组。
根据Kaiido建议连接块,转换为ArrayBuffer,然后将其传递给web audio api,我尝试了以下内容。
const blob = new Blob(chunksFromMediaRecorder, { 'type' : 'audio/ogg codecs=opus' })
// blob is Blob size: 32714, type: "audio/ogg codecs=opus"}
function playFromBlob(blob) {
const aCtx = new (window.AudioContext || window.webkitAudioContext)()
const source = aCtx.createBufferSource()
const fileReader = new FileReader()
let arrayBuffer
fileReader.onload = function() {
arrayBuffer = this.result
console.log('arrayBuffer', arrayBuffer) // ArrayBuffer {} with byte length 32714
aCtx.decodeAudioData(arrayBuffer) // throws: Uncaught (in promise) DOMException: Unable to decode audio data
.then(decodedData => {
// use the decoded data here
source.buffer = decodedData
source.connect(audioCtx.destination)
})
}
fileReader.readAsArrayBuffer(blob);
}
以上是成功创建与Blob大小相同的ArrayBuffer,但是当我将其传递给decodeAudioData
函数时,它会抛出Unable to decode audio data
错误。我在转换过程中是否缺少一个步骤?
Kaiido指出,有一个已知的bug镀铬会阻止我移动音频数据阵列。据我所知,这使得任何类型的音频修剪或切割目前不可能在Chrome中(Firefox音频阵列修剪工作,请参阅Kaiido的评论小提琴)。
为了实现我连续45秒追溯录制的最终目标,我现在将两个MediaRecorders
偏移45s并将其交换掉。因此当一个人在45秒而另一个人在90秒时我开始新的录音并摆脱90年代MediaRecorder
。绝对不是最理想的,但我现在可以找到最好的解决方案。