【问题标题】:onaudioprocess not called on ios11ios11上未调用onaudioprocess
【发布时间】:2018-03-03 22:25:53
【问题描述】:

我正在尝试从在 iOS11 上的 Safari 上工作的麦克风获取音频捕获 after support was recently added

但是,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 上调用它?

【问题讨论】:

  • 我也有同样的问题=(
  • 编辑:您必须创建webkitAudioContext() 或调用.resume() 以直接响应点击,而不是在获得流时。有关您的代码的完整工作版本,请参阅下面的答案。

标签: ios safari web-audio-api ios11


【解决方案1】:

只是想知道...您是否在 Safari 设置中启用了该设置?在 iOS11 中默认启用它,但也许你只是在没有注意到的情况下禁用它。

【讨论】:

  • 感谢@damianmr 的提示,但是在 Safari 中启用了摄像头和麦克风访问权限,它会在我第一次访问该页面时提示我允许访问。似乎一切正常,只是 onaudioprocess 从未被调用
【解决方案2】:

在 iOS 11.0.1 上试过,不幸的是这个问题仍然没有解决。

作为一种解决方法,我想知道将 ScriptProcessor 替换为一个从自助餐中获取蒸汽数据然后每 x 毫秒处理一次的函数是否有意义。但这对功能来说是一个很大的变化。

【讨论】:

  • 是的,我自己刚刚在 iOS 11.0.1 上尝试过。我已经看到了一些按照您的建议进行的演示,但是每 X 毫秒发送的“缓冲区”始终是空的(至少在我尝试过的演示中)。似乎访问麦克风字节本身就是问题所在。
  • 你写的东西给了我一些想法,不幸的是,到目前为止,它们都没有奏效。我还是把它们放在这里,也许它有帮助。你提到自助餐是空的,所以我认为问题可能出在 getUserMedia 上。尝试了 {audio: true, video: true} 和 navigator.getUserMedia 而不是 navigator.mediaDevices.getUserMedia。这些组合都不起作用。还尝试指定设备 ID,但也没有用。
  • 不幸的是,我无法评论内森的回答,但他的方法有效。在createMediaStremSource 之前移动processor = createScriptProcessorprocessor.connect 可以解决问题。
  • @DanielWu 您的最后一条评论刚刚修复了我的 web 应用程序,该应用程序对记录进行了必要的使用,所以我非常感激。您能否用它编辑您的答案,以便其他人更容易找到它,因为它被其他人掩盖了,并且似乎在 iOS Safari 上有所不同。
【解决方案3】:

有两个问题。主要问题是 iOS 11 上的 Safari 似乎会自动暂停新的AudioContext,这些不是为了响应点击而创建的。你可以resume()他们,但只能响应点击。

(更新:Chrome 移动版也有此功能,Chrome 桌面版将从 70 版/2018 年 12 月开始具有相同的限制。)

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

您的代码的另一个问题是 AudioContext 在 Safari 中的前缀为 webkitAudioContext

这是一个工作版本:

<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 回调,但在用户批准麦克风访问之前,您会得到空缓冲区。)

哦,还有一个需要注意的 iOS 错误:iPod touch 上的 Safari(从 iOS 12.1.1 开始)报告说它没有麦克风(它有)。因此,如果您在那里请求音频,getUserMedia 将错误地拒绝 Error: Invalid constraint

仅供参考:我在 npm 上维护 microphone-stream 包,它会为您执行此操作并在 Node.js 样式的 ReadableStream 中提供音频。如果您或其他任何人更愿意使用它而不是原始代码,它包含此修复程序。

【讨论】:

  • 是的,promise 解决被视为一个单独的事件,它不计为直接用户操作,因此音频被阻止。创建一个直接响应点击的音频上下文,然后再使用它。
  • (整个混乱是因为 Apple 不希望在移动 Safari 上自动播放音频。所以他们破坏了一切以防止这种情况发生。)
  • 呸!抱歉@nathan-friedly - 在我有机会测试并接受它作为答案之前,自动将赏金分配给了不同的答案。
  • 即使作为对用户操作的响应,我也让 audioContext 处于挂起状态,并且必须在创建后立即添加 audioContext.resume(),即 11.0.3
  • 您好,感谢您提供的优质资源。我有个问题。我们如何将原始数据转换为可以重放的 blob?提前致谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-22
  • 1970-01-01
  • 2018-03-04
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
相关资源
最近更新 更多