Web Audio API 无法在设备上播放声音样本,但可以在浏览器中播放

问题描述 投票:0回答:4

我有一个 Ionic 应用程序,它是一个节拍器。使用 Web Audio API,我已经使用振荡器功能使一切正常工作,但是当切换到使用 wav 文件时,真实设备 (iPhone) 上不会播放音频。

使用 Ionic Serve (chrome) 在浏览器中进行测试时,音频播放正常。

这是我所拥有的:

function snare(e) {
    var audioSource = 'assets/audio/snare1.wav';
    var request = new XMLHttpRequest();
    request.open('GET', audioSource, true);
    request.responseType = 'arraybuffer';

    // Decode asynchronously
    request.onload = function() {
        audioContext.decodeAudioData(request.response, function(theBuffer) {
            buffer = theBuffer;
            playSound(buffer);
        });
    }
    request.send();
}

function playSound(buffer) {
    var source = audioContext.createBufferSource();
    source.buffer = buffer;
    source.connect(audioContext.destination);
    source.start(0);
}

音频样本位于 www/assets/audio。

有什么想法可能会出错吗?

ios audio ionic-framework web-audio-api
4个回答
3
投票

我相信 iOS 设备需要某种用户手势才能播放音频。


0
投票

现在是 2017 年 7 月,iOS 10.3.2,我们仍然在 iPhone 上的 Safari 上发现此问题。有趣的是,MacBook 上的 Safari 浏览器没问题。 @Raymond Toy 的总体观察似乎仍然是正确的。但是@padenot的方法(通过https://gist.github.com/laziel/7aefabe99ee57b16081c)在我想播放声音来响应某些外部事件/触发器的情况下对我不起作用。

使用原始海报的代码,我已经取得了一些成功

var buffer; // added to make it work with OP's code

// keep the original function snare()

function playSound() { // dropped the argument for simplicity.
   var source = audioContext.createBufferSource();
   source.buffer = buffer;
   source.connect(audioContext.destination);
   source.start(0);
}

function triggerSound() {

    function playSoundIos(event) {
        document.removeEventListener('touchstart', playSoundIos);
        playSound();
    }

    if (/iPad|iPhone/.test(navigator.userAgent)) {
        document.addEventListener('touchstart', playSoundIos);
    }
    else { // Android etc. or Safari, but not on iPhone 
        playSound();
    }
}

现在调用

triggerSound()
将在 Android 上立即发出声音,并在 iOS 上触摸浏览器页面后发出声音。

仍然不理想,但总比没有声音好……


0
投票

我在当前的 iOS (15) 中也遇到了类似的问题。我尝试播放在所有浏览器中都有效的 base64 编码的二进制数据,但在 iOS 上无效。

最终对语句进行重新排序解决了我的问题:

let buffer = Uint8Array.from(atob(base64), c => c.charCodeAt(0));
let context = new AudioContext();

// these lines were within "play()" before
audioSource = context.createBufferSource();
audioSource.connect(context.destination);
audioSource.start(0);
// ---

context.decodeAudioData(buffer.buffer, play, (e) => {
    console.warn("error decoding audio", e)
});

function play(audioBuffer) {
    audioSource.buffer = audioBuffer;
}

另请参阅此在我的项目中提交

我认为在

audioSource.start(0)
方法中调用
play()
不知何故太晚了,因为它位于
context.decodeAudioData()
之后的回调中,因此对于 iOS 标准来说,可能与用户交互“太远”了。


0
投票

我尝试了很多方法让声音在 ios 上运行,最后在使用 howler.js 时成功了(https://goldfirestudios.com/howler-js-modern-web-audio-javascript-library)。我在 vue.js 项目中使用了它。

© www.soinside.com 2019 - 2024. All rights reserved.