Chrome 66 отключает звук после автозапуска

внешний интерфейс браузер Chrome Ресурс изображения
Chrome 66 отключает звук после автозапуска

На IOS/Android всегда была практика, что звук не может воспроизводиться автоматически.Настольная версия Safari также объявила о запрете на автоматическое воспроизведение мультимедиа со звуком в версии 11 в 2017 году, а затем и Chrome 66, выпущенный в апреле 2018 года. официально отключить автоматическое воспроизведение звука, т.е.<audio autopaly></audio> <video autoplay></video>Он также не будет работать в настольных браузерах.

Поначалу мобильный браузер полностью запрещал автоматическое воспроизведение аудио и видео с учетом пропускной способности мобильного телефона и расхода батареи. Но позже это было изменено, потому что производители браузеров обнаружили, что веб-разработчики могут использовать анимацию GIF вместо видео для автоматического воспроизведения, посколькуДокументация iOSГоворят, что пропускная способность при использовании GIF в 12 раз больше, чем при использовании формата видео (h264), а потребление производительности при воспроизведении составляет 2 раза, так что это нехорошо для пользователей. Или используйте Canvas для взлома, напримерДокументация Android Chromeупомянул. Поэтому производители браузеров сняли ограничения на автоматическое воспроизведение мультимедиа и могут автоматически воспроизводиться при соблюдении следующих условий:

(1) Звуковая дорожка отсутствует или установлен атрибут muted

(2) Видимый в представлении, чтобы быть вставленным в DOM и не отображаемым: нет или видимость: скрытая, без выскальзывания из видимой области.

Другими словами, пока вы не включаете звук, чтобы мешать публике, и он виден пользователю, он позволит вам воспроизводить его автоматически, и вам не нужно использовать метод GIF для взлома.

Настольная версия браузера также недавно использовала эту стратегию, как объясняется в обновленном Safari 11:

так же какИнструкции для документации Chrome:

Эта стратегия, несомненно, оказывает наибольшее влияние на видеосайты, например, приглашение открыть tudou в Safari:

Добавлен мастер настройки. Запрет Chrome более удобен для пользователя, у него естьстратегия МЭИЭта стратегия, вероятно, скажет, пока пользователь активно играет более 7s аудио и видео на текущей странице (окно видео не может быть менее 200 x 140), позволяет автоматически воспроизводить.


Для веб-разработчиков, как эффективно избежать этого риска?

Документация Chrome дает передовую практику: сначала добавьте атрибут muted к аудио и видео для автоматического воспроизведения, а затем отобразите кнопку с выключенным звуком, предлагая пользователю щелкнуть, чтобы включить звук. Для видео это действительно можно сделать, а для аудио многие люди слушают событие клика по странице и начинают воспроизводить звук до тех пор, пока на него щелкают один раз, обычно проигрывая фоновую музыку. Но что, если для страницы с несколькими звуковыми ресурсами автоматически воспроизводится несколько звуков?

Во-первых, если пользователь вызовет API, который воспроизводит звук, не взаимодействуя с ним, Chrome предложит:

DOMException: play() failed because the user didn't interact with the document first.

Safari предложит следующее:

NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

Сообщение об ошибке Chrome является наиболее дружественным, что означает, что пользователь не взаимодействовал и не может настроить воспроизведение. Что включает в себя взаимодействие с пользователем? Включая события касания, щелчка, двойного щелчка или нажатия клавиши, инициированные пользователем, в этих событиях можно настроить воспроизведение.

Таким образом, многие люди прослушивают вышеупомянутые события, щелкните, чтобы воспроизвести всю страницу, независимо от точки, где, пока точка на линии, включая снижение касания. Этот метод применим только к звуковому ресурсу, не применяют больше звука, больше звука должно быть, как сломать его? Это не значит, что браузер и против, «охранников и линия», наша цель состоит в том, чтобы улучшить пользовательский опыт, потому что некоторые сцены, если AutoPlay действительно лучше, ответ, как некоторые сценарии, вам нужно слушать звуковой ответ , Если пользователи могут повернуть автозапуск соответствующего заголовка в процессе ответа, голос действительно удобнее. Также обсудите технологию воспроизведения звука.

Для собственного воспроизведения видео следует использовать только тег video.В дополнение к использованию тега audio для собственного воспроизведения звука существует еще один API, называемый AudioContext, который можно использовать для управления воспроизведением звука и который имеет множество богатых интерфейсов для управления.Вызов audio.play должен реагировать на событие щелчка, а разница между использованием AudioContext заключается в том, что он может воспроизводиться, пока пользователь щелкает в любом месте страницы.. Таким образом, вы можете использовать AudioContext вместо аудио тега для воспроизведения звука.

Сначала мы используем audio.play, чтобы определить, поддерживает ли страница автоматическое воспроизведение, чтобы определить время нашего воспроизведения.

1. Обнаружение автозапуска страницы

Метод очень прост, то есть создать аудио элемент, назначить ему src, добавить его в dom, а затем вызвать его воспроизведение, чтобы увидеть, будет ли выброшено исключение.Если исключение поймано, это означает, что оно не поддерживается, как показано в следующем коде:

function testAutoPlay () {
    // 返回一个promise以告诉调用者检测结果
    return new Promise(resolve => {
        let audio = document.createElement('audio');
        // require一个本地文件,会变成base64格式
        audio.src = require('@/assets/empty-audio.mp3');
        document.body.appendChild(audio);
        let autoplay = true;
        // play返回的是一个promise
        audio.play().then(() => {
            // 支持自动播放
            autoplay = true;
        }).catch(err => {
            // 不支持自动播放
            autoplay = false;
        }).finally(() => {
            audio.remove();
            // 告诉调用者结果
            resolve(autoplay);
        });
    });
}

Здесь используется пустой аудиофайл, это mp3 файл с временной длиной 0 с, размером всего 4кб, упакован в локальный формат base64 через webpack, поэтому нет необходимости вызывать play после события canplay , и напрямую написать его как синхронный код.Если src является удаленным URL-адресом, то вам нужно прослушать событие canplay, а затем воспроизвести его.

Сообщая вызывающей стороне результат, используйте метод разрешения промиса, поскольку результат воспроизведения является асинхронным, а библиотечная функция не рекомендует использовать ожидание.

2. Отслеживайте клики по взаимодействию со страницей

Если текущая страница может воспроизводиться автоматически, то вы можете позволить звуку воспроизводиться автоматически без каких-либо угрызений совести, иначе он не будет воспроизводиться автоматически, пока пользователь не начнет взаимодействовать со страницей, то есть произойдет операция щелчка, как показано на следующем код:

let audioInfo = {
    autoplay: false,
    testAutoPlay () {
        // 代码同,略... 
    },
    // 监听页面的点击事件,一旦点过了就能autoplay了
    setAutoPlayWhenClick () {
        function setAutoPlay () {
            // 设置自动播放为true
            audioInfo.autoplay = true;
            document.removeEventListener('click', setAutoPlay);
            document.removeEventListener('touchend', setAutoPlay);
        }
        document.addEventListener('click', setCallback);
        document.addEventListener('touchend', setCallback);
    },
    init () {
        // 检测是否能自动播放
        audioInfo.testAutoPlay().then(autoplay => {
            if (!audioInfo.autoplay) {
                audioInfo.autoplay = autoplay;
            }
        });
        // 用户点击交互之后,设置成能自动播放
        audioInfo.setAutoPlayWhenClick();
    }
};
audioInfo.init();
export default audioInfo;

Приведенный выше код в основном отслеживает событие щелчка документа и устанавливает значение автовоспроизведения в значение true в событии щелчка. Другими словами, пока пользователь щелкает, мы можем вызывать API воспроизведения AudioContext в любое время, даже если он не находится в функции ответа на событие клика, хотя audio.play нельзя вызвать в асинхронном обратном вызове, AudioContext может это сделать.

Наконец, код сохраняет информацию, которая может воспроизводиться автоматически, в переменной audioInfo.autoplay, вызывая audioInfo.init. Когда вам нужно воспроизвести звук, например, когда вы переходите к следующему вопросу, и вам нужно автоматически воспроизвести несколько аудиоресурсов текущего вопроса, вы можете использовать эту переменную, чтобы судить, может ли он воспроизводиться автоматически. он нажимает на нее один раз, она может быть воспроизведена автоматически.

Итак, как использовать AudioContext для воспроизведения звука?

3. AudioContext воспроизводит звук

Сначала запросите аудиофайл, поместите его в ArrayBuffer, а затем используйте API AudioContext для декодирования и декодирования, а затем позвольте ему воспроизводиться после декодирования.

Давайте сначала напишем ajax, который запрашивает аудиофайл:

function request (url) {
    return new Promise (resolve => {
        let xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        // 这里需要设置xhr response的格式为arraybuffer
        // 否则默认是二进制的文本格式
        xhr.responseType = 'arraybuffer';
        xhr.onreadystatechange = function () {
            // 请求完成,并且成功
            if (xhr.readyState === 4 && xhr.status === 200) {
                resolve(xhr.response);
            }
        };
        xhr.send();
    });
}

Здесь необходимо отметить изменение типа ответа xhr на arraybuffer, поскольку для декодирования необходимо использовать этот формат хранения.После этой настройки xhr.response является форматом ArrayBuffer.

Затем создайте экземпляр AudioContext, дайте ему декодировать и воспроизвести, как показано в следующем коде:

// Safari是使用webkit前缀
let context = new (window.AudioContext || window.webkitAudioContext)();
// 请求音频数据
let audioMedia = await request(url);
// 进行decode和play
context.decodeAudioData(audioMedia, decode => play(context, decode));

Функция игры реализована следующим образом:

function play (context, decodeBuffer) {
    let source = context.createBufferSource();
    source.buffer = decodeBuffer;
    source.connect(context.destination);
    // 从0s开始播放
    source.start(0);
}

Таким образом реализуется основная функция AudioContext для воспроизведения звука.

Если текущая страница не может быть воспроизведена автоматически, консоль Chrome выдаст предупреждение при использовании нового AudioContext:

Это означает, что пользователь не взаимодействует со страницей, и вы можете инициализировать AudioContext, я не позволю вам играть, вам нужно восстановить этот контекст после того, как пользователь щелкнет, чтобы иметь возможность играть.

Предположим, мы игнорируем это предупреждение и вызываем play напрямую, не сообщая об ошибке, но звука нет. Итак, на данный момент нам нужно использовать информацию audioInfo.autoplay на предыдущем шаге. Если это правда, вы можете играть, иначе вы не можете играть. Вам нужно позволить пользователю щелкнуть значок звука для воспроизведения. Итак, давайте реорганизуем код:

function play (context, decodeBuffer) {
    // 调用resume恢复播放
    context.resume();
    let source = context.createBufferSource();
    source.buffer = decodeBuffer;
    source.connect(context.destination);
    source.start(0);
}

function playAudio (context, url) {
    let audioMedia = await request(url);
    context.decodeAudioData(audioMedia, decode => play(context, decode));
}

let context = new (window.AudioContext || window.webkitAudioContext)();
// 如果能够自动播放
if (audioInfo.autoplay) {
    playAudio(url);
}
// 支持用户点击声音图标自行播放
$('.audio-icon').on('click', function () {
    playAudio($(this).data('url'));
});

После настройки возобновления, если есть какое-либо аудио, воспроизведение которого ранее было запрещено, оно начнет воспроизводиться, если нет, функция автовоспроизведения контекста будет восстановлена ​​напрямую. Таким образом достигается основная цель: если поддерживается автоматическое воспроизведение, играйте прямо в коде, если не поддерживается, просто ждите клика. Пока вы нажимаете один раз, независимо от того, где вы нажимаете, следующие могут воспроизводиться автоматически. Он может достичь цели автоматического воспроизведения звука следующего вопроса каждые 3 секунды:

// 每隔3秒自动播放一个声音
playAudio('question-1.mp3');
setTimeout(() => playAudio(context, 'question-2.mp3'), 3000);
setTimeout(() => playAudio(context, 'question-3.mp3'), 3000);

Здесь есть еще один вопрос, как узнать, что каждый звук закончен, а затем воспроизводить следующий звук каждые 3 секунды? Вы можете передать два параметра, один из которых состоит в том, что декодированный decodeBuffer имеет атрибут продолжительности текущего аудио, и вы можете узнать текущую точность времени воспроизведения через context.currentTime, а затем вы можете получить таймер для сравнения каждые 100 мс, независимо от того, является ли context.currentTime больше, чем docode.duration, если это так, то это означает, что трансляция завершена. Так реализована библиотека soundjs, которую мы можем использовать для облегчения работы со звуком.

Таким образом достигается цель использования AudioContext для автоматического воспроизведения нескольких аудио.Ограничение состоит в том, что пользователь не может автоматически воспроизводить страницу в первый раз, но как только пользователь щелкает в любом месте страницы, это может быть.

AudioContext также имеет некоторые другие операции.

4. AudioContext управляет свойствами звука

Например этоCSS TricksПеречислено несколько примеров, одним из которых является использование осциллятора AudioContext для записи электронного ксилофона:

В этом примере не используются никакие звуковые ресурсы, он синтезирован напрямую и выглядит как эта демонстрация:Play the Xylophone (Web Audio API).

Также есть примеры таких эквалайзеров реверберации:

См. этот код:Web Audio API: parametric equalizer.


Наконец, только мобильные браузеры всегда отключали автоматическое воспроизведение аудио и видео, а теперь это начинают делать и десктопные браузеры. Цель браузера — не дать пользователям открыть страницу и транслировать различную рекламу или другие беспорядочные звуки, чтобы создать чистую и спокойную среду. Но браузеры не являются универсальными, по крайней мере, они позволяют воспроизводить аудио и видео с отключенным звуком. Таким образом, для видео его можно воспроизводить автоматически с отключением звука, а затем добавить значок с отключенным звуком, чтобы пользователь мог щелкнуть его, чтобы открыть, и добавить мастер настройки и другие методы, которые помогут пользователю настроить текущий веб-сайт на автоматическую настройку. играть. Для звука можно использовать API AudioContext.Поскольку AudioContext активируется при однократном щелчке страницы, воспроизведением можно управлять непосредственно в коде.

Вышеупомянутое можно использовать в качестве справочного материала для наилучшей практики воспроизведения мультимедиа на текущей веб-странице.

【Дополнительный】"Эффективный интерфейс》Готовясь ко второму изданию, я слышал, что вы еще не купили его