Safari ios audio - отказ от воспроизведения с ошибкой

Ошибка javascript: Unhandled Promise Rejection: NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

Моя установка работает в других браузерах, как на настольных компьютерах, так и на мобильных устройствах.

Как это работает:

  • есть флаг first_audio_played = false;
  • добавить прослушиватель событий касания, который воспроизводит звук, и устанавливает first_audio_played = true; (затем удаляет прослушиватель касаний)
  • все последующие проверки аудио if (first_audio_played) some_other_audio.play();

таким образом, только воспроизводимый звук первый требует прямого ввода пользователем. после этого все звуки могут запускаться в зависимости от игровых событий, времени и т. д.

это, по-видимому, «правило» для звука в большинстве браузеров. является ли «правилом» iOS, что звук каждый должен запускаться пользователем? или есть еще какой-то шаг, который мне не хватает?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
0
1 504
2

Ответы 2

В моей игре на javascript звуки недавно перестали работать на iOS. У всех есть readyState = 4, но работает только звук, который я воспроизводил при нажатии, остальные не воспроизводятся. Может быть, ты сможешь воспроизвести все звуки с первого нажатия. Но найденное мной решение, которое сейчас работает для меня, - это загрузить все звуки из буферов массива ajax и использовать decodeAudioData (). Затем, как только вы проиграете 1 звук от пользовательского нажатия (не на корпусе), все они будут воспроизводиться каждый раз.

Вот мой рабочий код, где второй способ сделать это внизу. Когда я нажимаю, чтобы воспроизвести звук2, звук1 также начинает работать.

<html>
    <body>
        <div id=all style='font-size:160%;background:#DDD' onclick = "log('clicked');playSound(myAudio)">
            Sound1 should be playing every couple seconds.
            <br />Tap here to play sound1.
        </div>
        <div id=debug style='font-size:120%;' onclick = "playSound(myAudio2)">
            Tap here to play the sound2.
        </div>
        <script>
            var url = "http://curtastic.com/drum.wav"
            var url2 = "http://curtastic.com/gold.wav"
            var myAudio, myAudio2
            if (0)
            {
                var playSound = function(sound)
                {
                    log("playSound() readyState = "+sound.readyState)
                    log("gold readyState = "+myAudio2.readyState)
                    sound.play()
                }

                var loadSound = function(url, callback)
                {
                    var audio = new Audio(url)
                    audio.addEventListener('canplaythrough', function()
                    {
                        log('canplaythrough');
                        if (callback)
                            callback()
                    }, false)

                    audio.load()
                    if (audio.readyState > 3)
                    {
                        log('audio.readyState > 3');
                        if (callback)
                            callback()
                    }
                    return audio
                }

                myAudio = loadSound(url, startInterval)
                myAudio2 = loadSound(url2)
            }
            else
            {
                var playSound = function(sound)
                {
                    log("playSound()")
                    var source = audioContext.createBufferSource()
                    if (source)
                    {
                        source.buffer = sound
                        if (!source.start)
                            source.start = source.noteOn

                        if (source.start)
                        {
                            var gain = audioContext.createGain()
                            source.connect(gain)
                            gain.connect(audioContext.destination)

                            source.start()
                        }
                    }
                }

                var loadSound = function(url, callback)
                {
                    log("start loading sound "+url)

                    var ajax = new XMLHttpRequest()
                    ajax.open("GET", url, true)
                    ajax.responseType = "arraybuffer"
                    ajax.onload = function()
                    {
                        audioContext.decodeAudioData(
                            ajax.response,
                            function(buffer)
                            {
                                log("loaded sound "+url)
                                log(buffer)
                                callback(buffer)
                            },
                            function(error)
                            {
                                log(error)
                            }
                        )

                    }
                    ajax.send()
                }

                var AudioContext = window.AudioContext || window.webkitAudioContext
                var audioContext = new AudioContext()

                loadSound(url, function(r) {myAudio = r; startInterval()})
                loadSound(url2, function(r) {myAudio2 = r})
            }

            function startInterval()
            {
                log("startInterval()")
                setInterval(function()
                {
                    playSound(myAudio)
                }, 2000)
            }

            function log(m)
            {
                console.info(m)
                debug.innerHTML += m+"<br />"
            }
        </script>
    </body>
</html>

Вы можете использовать [WKWebViewConfiguration setMediaTypesRequiringUserActionForPlayback:WKAudiovisualMediaTypeNone] или [UIWebView setMediaPlaybackRequiresUserAction:NO] в зависимости от вашего класса WebView (или эквивалента Swift).

Другие вопросы по теме