在ios11上没有调用onaudioprocess

Joh*_*lly 20 safari ios web-audio-api ios11

在最近添加支持后,我试图通过iOS11上的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>
Run Code Online (Sandbox Code Playgroud)

在大多数平台上,当onaudioprocess调用回调时,您将看到要添加到消息列表中的项目.但是,在iOS上,永远不会调用此回调.

我还应该做些什么来尝试在iOS 11上使用Safari调用它?

Nat*_*dly 25

有两个问题.主要的一点是,iOS 11上的Safari似乎会自动挂起AudioContext不是为响应点击而创建的新游戏.你可以resume(),但只是为了回应.

(更新:Chrome移动设备也可以执行此操作,Chrome桌面将从版本70/2018年12月开始具有相同的限制.)

因此,您必须在获得之前创建它MediaStream,或者让用户稍后再次点击.

您的代码的另一个问题AudioContextwebkitAudioContext在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>
Run Code Online (Sandbox Code Playgroud)

(您可以onaudioprocess更快地设置回调,但在用户批准麦克风访问之前,您将获得空缓冲区.)

哦,还有另外一个需要注意的iOS漏洞:iPod touch上的Safari(从iOS 12.1.1开始)报告说它没有麦克风(确实如此).所以,Error: Invalid constraint如果你在那里要求音频,getUserMedia会拒绝.

仅供参考:我在npm上维护麦克风流包,为您完成此操作,并以Node.js风格的ReadableStream提供音频.我刚刚使用此修复程序更新了它,如果您或其他任何人更愿意使用原始代码.

  • (整个混乱是因为 Apple 不想在移动 Safari 上自动播放音频。所以他们打破了一切以防止这种情况发生。) (2认同)
  • 即使作为对用户操作的响应,我将audioContext置于挂起状态,并且必须在创建后立即添加audioContext.resume(),即11.0.3 (2认同)