我正试图通过iOS11 after support was recently added
上的Safari上的麦克风进行音频捕获但是,永远不会调用onaudioprocess
回调。这是一个示例页面:
<html>
<body>
<button onclick="doIt()">DoIt</button>
<ul id="logMessages">
</ul>
<script>
function debug(msg) {
if (typeof msg !== 'undefined') {
var logList = document.getElementById('logMessages');
var newLogItem = document.createElement('li');
if (typeof msg === 'function') {
msg = Function.prototype.toString(msg);
} else if (typeof msg !== 'string') {
msg = JSON.stringify(msg);
}
var newLogText = document.createTextNode(msg);
newLogItem.appendChild(newLogText);
logList.appendChild(newLogItem);
}
}
function doIt() {
var handleSuccess = function (stream) {
var context = new AudioContext();
var input = context.createMediaStreamSource(stream)
var processor = context.createScriptProcessor(1024, 1, 1);
input.connect(processor);
processor.connect(context.destination);
processor.onaudioprocess = function (e) {
// Do something with the data, i.e Convert this to WAV
debug(e.inputBuffer);
};
};
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(handleSuccess);
}
</script>
</body>
</html>
在大多数平台上,当调用onaudioprocess
回调时,您会看到要添加到消息列表中的项目。但是,在iOS上,永远不会调用此回调。
我是否应该尝试使用Safari在iOS 11上调用它?
答案 0 :(得分:20)
有两个问题。主要的一点是,iOS 11上的Safari似乎会自动暂停新的AudioContext
,而这些新的resume()
是为了响应点击而创建的。您可MediaStream
他们,但仅限于点按。
(更新:Chrome移动版也会执行此操作,Chrome桌面将从2018年12月的版本70开始具有相同的限制。)
因此,您必须在获得AudioContext
之前创建它,或者让用户稍后再次点按。
您的代码的另一个问题是webkitAudioContext
在Safari中以<html>
<body>
<button onclick="beginAudioCapture()">Begin Audio Capture</button>
<script>
function beginAudioCapture() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var processor = context.createScriptProcessor(1024, 1, 1);
processor.connect(context.destination);
var handleSuccess = function (stream) {
var input = context.createMediaStreamSource(stream);
input.connect(processor);
var recievedAudio = false;
processor.onaudioprocess = function (e) {
// This will be called multiple times per second.
// The audio data will be in e.inputBuffer
if (!recievedAudio) {
recievedAudio = true;
console.log('got audio', e);
}
};
};
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(handleSuccess);
}
</script>
</body>
</html>
为前缀。
这是一个有效的版本:
onaudioprocess
(您可以更快地设置Error: Invalid constraint
回调,但在用户批准麦克风访问之前,您将获得空缓冲区。)
哦,另外还有一个需要注意的iOS漏洞:iPod touch上的Safari(从iOS 12.1.1开始)报告它没有麦克风(确实如此)。因此,如果您在那里要求提供音频,getUserMedia将拒绝{
"rules": {
"users": {
"$uid": {
".read": "auth !== null",
".write": "auth.uid === $uid",
"name": {"
},
"userName": {
}
}
},
"users-Used": {
".read": true,
".write": "auth !== null"
}
}
}
。
仅供参考:我在npm上维护microphone-stream包,为你做这件事,并在Node.js风格的ReadableStream中提供音频。我刚刚使用此修复程序更新了它,如果您或其他任何人愿意使用原始代码。
答案 1 :(得分:4)
在iOS 11.0.1上尝试过,不幸的是这个问题仍然没有解决。
作为一种解决方法,我想知道用一个函数替换ScriptProcessor是否有意义,该函数从自助餐中获取蒸汽数据,然后每隔x毫秒处理一次。但这是对功能的重大改变。
答案 2 :(得分:2)