ios Web音频API无法在设备上播放声音样本,但可在浏览器中运行

qq24tv8q  于 2022-12-30  发布在  iOS
关注(0)|答案(3)|浏览(190)

我有一个离子应用程序,是一个节拍器。使用网络音频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。
你知道哪里出了问题吗?

jtw3ybtb

jtw3ybtb1#

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

flvlnr44

flvlnr442#

现在是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上触摸浏览器页面后产生声音。
还是不理想,但总比完全没有声音好...

2exbekwf

2exbekwf3#

我在当前的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;
}

另请参见此commit in my project
我认为在play()方法中调用audioSource.start(0)有点太晚了,因为它在context.decodeAudioData()之后的回调中,因此对于iOS的标准来说,可能离用户交互“太远了”。

相关问题