【发布时间】:2018-02-14 00:55:09
【问题描述】:
我看到很多关于如何录制音频然后停止录制、然后播放音频或将其保存到文件的问题,但这些都不是我想要的。
tl;dr 简而言之,这是我的问题:“我怎样才能立即播放从用户麦克风录制的音频?”也就是说,我不想要保存录音并在用户点击“播放”按钮时播放它,我不想要将录音保存到用户计算机上的文件,我不想使用 WebRTC 在任何地方流式传输音频。我只想对着我的麦克风说话,然后从扬声器里听到我的声音。
我要做的只是制作一个非常简单的“回声”页面,它会立即播放从麦克风录制的音频。我开始使用mediaRecorder 对象,但这不起作用,据我所知,这是用于录制完整的音频文件,所以我切换到基于AudioContext 的方法。
一个非常简单的页面如下所示:
<!DOCTYPE html>
<head>
<script type="text/javascript" src="mcve.js"></script>
</head>
<body>
<audio id="speaker" volume="1.0"></audio>
</body>
脚本如下所示:
if (navigator.mediaDevices) {
var constrains = {audio: true};
navigator.mediaDevices.getUserMedia(constrains).then(
function (stream) {
var context = new AudioContext();
var source = context.createMediaStreamSource(stream);
var proc = context.createScriptProcessor(2048, 2, 2);
source.connect(proc);
proc.onaudioprocess = function(e) {
console.log("audio data collected");
let audioData = new Blob(e.inputBuffer.getChannelData(0), {type: 'audio/ogg' } )
|| new Blob(new Float32Array(2048), {type: 'audio/ogg'});
var speaker = document.getElementById('speaker');
let url = URL.createObjectURL(audioData);
speaker.src = url;
speaker.load();
speaker.play().then(
() => { console.log("Playback success!"); },
(error) => { console.log("Playback failure... ", error); }
);
};
}
).catch( (error) => {
console.error("couldn't get user media.");
});
}
它可以录制重要的音频数据(即,并非每个集合都以Blob 调用的Blob 结尾),但它无法播放。它永远不会遇到“无法获取用户媒体”的问题,但它总是会遇到“播放失败...”的问题。错误打印如下:
DOMException [NotSupportedError: "The media resource indicated by the src attribute or assigned media provider object was not suitable."
code: 9
nsresult: 0x806e0003]
此外,消息Media resource blob:null/<long uuid> could not be decoded. 会重复打印到控制台。
据我所知,这里可能会发生两件事(也许两者都有):
- 我没有对音频进行编码。我不确定这是否是个问题,因为我认为从麦克风收集的数据自动带有“ogg”编码,我尝试将我的
Blobs 的type属性留空,但无济于事。如果这是问题所在,我不知道如何编码audioprocess事件给我的一段音频,这就是我需要知道的。 -
<audio>元素基本上无法播放音频片段,即使正确编码也是如此。也许由于没有完整的文件,有一些违反编码标准的丢失或无关的元数据,并阻止浏览器理解我。如果是这种情况,也许我需要一个不同的元素,甚至是一个完全脚本化的解决方案。或者我应该为每个音频数据块就地构造一个类似文件的对象?
我已经根据 MDN 和 SO 答案中的示例构建了这段代码,我应该提到我已经在 this example demo 测试了我的麦克风,它似乎工作得很好。
这里的最终目标是通过 websocket 将此音频流式传输到服务器并将其中继给其他用户。如果可能,我不想使用 WebRTC,因为我不想将自己仅限于 Web 客户端 - 一旦它工作正常,我也会制作一个桌面客户端。
【问题讨论】:
-
你的问题不是很清楚。
-
怎么样?我该怎么做才能更清楚?
-
看看
DelayNode。 -
@K3N 我不确定这会有什么帮助,因为我没有尝试制作循环音频源,并且在我切换到服务器时引入手动延迟似乎是个坏主意/中继系统。
-
我相信@anoneemus 希望在录制时播放音频——换句话说,在录制时听到输入。有谁可以解决这个问题?
标签: javascript dom audio html5-audio audio-streaming