我正在录制音频,将其作为blob发送到nodejs服务器。然后,nodejs服务器将其发送给当前未记录的所有连接用户。
发送blob:
mediaRecorder.onstop = function(e) {
var blob = new Blob(this.chunks, { 'type' : 'audio/ogg; codecs=opus' });
socket.emit('radio', blob);
};
服务器接收blob:
socket.on('radio', function(blob) {
socket.broadcast.emit('voice', blob);
});
收听blob的听众:
socket.on('voice', function(arrayBuffer) {
var blob = new Blob([arrayBuffer], { 'type' : 'audio/ogg; codecs=opus' });
var audio = document.getElementById('audio');
audio.src = window.URL.createObjectURL(blob);
audio.play();
});
这适用于除safari和任何ios设备之外的所有浏览器/设备。在safari的检查员的帮助下,我发现了这一点:
safari是否需要在其标题中使用其他内容才能正确解释blob对象?我已经研究过接受过的音频类型,试过aac / mp3 / ogg没有任何成功。在进一步阅读后,我听说过在safari和IOS中存在流blob音频/视频数据的错误,尽管我不太清楚任何细节。
仪式方向的指导非常有帮助!
编辑:接收blob中的这一行audio.src = window.URL.createObjectURL(blob);
看起来是造成blob错误的原因(我链接的图片)
编辑2:我试图查看使用blob以外的其他格式是否有效,选择使用base64编码的字符串。看起来这适用于除IOS和Safari之外的所有设备和浏览器。我得到的印象是它与IOS如何解释/加载数据有关...
答案 0 :(得分:2)
对我来说,解决方案是将一个源元素插入audio元素,并使用sourceElement.src属性来引用blob。我甚至不需要将音频元素附加到DOM。以下示例,希望它可以帮助某人。
var audioElement = document.createElement('audio')
var sourceElement = document.createElement('source')
audioElement.appendChild(sourceElement)
sourceElement.src = '<your blob url>'
sourceElement.type = 'audio/mp3' // or whatever
audioElement.load()
audioElement.play()
答案 1 :(得分:1)
这周我遇到了类似的问题。我正在Safari上录制音频,并且音频Blob正在生成。但是,当我尝试将Blob发送到服务器时,没有数据到达那里。下面的解决方案使用File Reader读取blob以将其转换为base64,然后将其发送到服务器。这是对我有用的东西:
const reader = new FileReader();
reader.readAsDataURL(audioBlob);
reader.onloadend = () => {
const base64data = reader.result;
const audioName = uuid.v4() + '.mp3';
this.http.post(this.app.cloudStorageEndpoint + '/audios/local?audioName=' + audioName, base64data , header).subscribe(
res => { resolve(audioName); },
err => { reject(err); }
);
};
我已经在iPad和iPhone上使用Safari 12进行了测试,并且效果很好。
答案 2 :(得分:0)
我无法使用音频元素找到解决方案,但Web Audio Api似乎可以解决问题:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API
var audioContext = new (window.AudioContext || window.webkitAudioContext);
socket.on('voice', function(arrayBuffer) {
audioContext.decodeAudioData(arrayBuffer, audioData => {
var source = audioContext.createBufferSource();
source.buffer = audioData;
source.connect(audioContext.destination);
source.start()
});
您可能仍然在iOS上遇到问题,因为任何音频/视频都必须由用户操作触发。