简体   繁体   English

onaudioprocess 未在 ios11 上调用

[英]onaudioprocess not called on ios11

I am trying to get audio capture from the microphone working on Safari on iOS11 after support was recently added 最近添加了支持后,我正在尝试从在 iOS11 上的 Safari 上工作的麦克风获取音频捕获

However, the onaudioprocess callback is never called.但是,永远不会调用onaudioprocess回调。 Here's an example page:这是一个示例页面:

<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>

On most platforms, you will see items being added to the messages list as the onaudioprocess callback is called.在大多数平台上,当onaudioprocess回调被调用时,您会看到项目被添加到消息列表中。 However, on iOS, this callback is never called.但是,在 iOS 上,永远不会调用此回调。

Is there something else that I should do to try and get it called on iOS 11 with Safari?我还应该做些什么来尝试使用 Safari 在 iOS 11 上调用它?

There are two problems.有两个问题。 The main one is that Safari on iOS 11 seems to automatically suspend new AudioContext 's that aren't created in response to a tap.主要的一点是 iOS 11 上的 Safari 似乎会自动挂起不是为了响应点击而创建的新AudioContext You can resume() them, but only in response to a tap.您可以resume()它们,但只能响应点击。

(Update: Chrome mobile also does this, and Chrome desktop will have the same limitation starting in version 70 / December 2018.) (更新:Chrome 移动版也执行此操作,从 70 版 / 2018 年 12 月开始,Chrome 桌面版将具有相同的限制。)

So, you have to either create it before you get the MediaStream , or else get the user to tap again later.因此,您必须在获得MediaStream之前创建它,或者让用户稍后再次点击。

The other issue with your code is that AudioContext is prefixed as webkitAudioContext in Safari.您的代码的另一个问题是AudioContext在 Safari 中以webkitAudioContext为前缀。

Here's a working version:这是一个工作版本:

<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>

(You can set the onaudioprocess callback sooner, but then you get empty buffers until the user approves of microphone access.) (您可以更快地设置onaudioprocess回调,但是在用户批准麦克风访问之前,您会获得空缓冲区。)

Oh, and one other iOS bug to watch out for: the Safari on iPod touch (as of iOS 12.1.1) reports that it does not have a microphone (it does).哦,还有一个需要注意的 iOS 错误:iPod touch 上的 Safari(从 iOS 12.1.1 开始)报告说它没有麦克风(它有)。 So, getUserMedia will incorrectly reject with an Error: Invalid constraint if you ask for audio there.因此,如果您在那里请求音频, getUserMedia 将错误地拒绝并显示Error: Invalid constraint

FYI: I maintain the microphone-stream package on npm that does this for you and provides the audio in a Node.js-style ReadableStream.仅供参考:我在 npm 上维护了麦克风流包,它为您执行此操作并以 Node.js 样式的 ReadableStream 提供音频。 It includes this fix, if you or anyone else would prefer to use that over the raw code.如果您或其他任何人更愿意在原始代码上使用它,它包括此修复程序。

Tried it on iOS 11.0.1, and unfortunately this problem still isn't fixed.在 iOS 11.0.1 上试过了,可惜这个问题还是没有解决。

As a workaround, I wonder if it makes sense to replace the ScriptProcessor with a function that takes the steam data from a buffet and then processes it every x milliseconds.作为一种解决方法,我想知道用一个函数替换 ScriptProcessor 是否有意义,该函数从自助餐中获取蒸汽数据,然后每 x 毫秒处理一次。 But that's a big change to the functionality.但这对功能来说是一个很大的变化。

Just wondering... do you have the setting enabled in Safari settings?只是想知道...您是否在 Safari 设置中启用了该设置? It comes enabled by default in iOS11, but maybe you just disabled it without noticing.它在 iOS11 中默认启用,但也许您只是在没有注意到的情况下禁用了它。

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM