navigator.audioSession позволяет странице объявить тип звука и увидеть состояние interrupted. Что это говорит об устройстве и где проходят границы.
Веб-страница, которая воспроизводит звук, может узнать, что нечто вне браузера забрало у неё аудиотракт, — например, входящий звонок или другое приложение, захватившее звук в монопольное пользование. Для этого не нужны ни запрос разрешения, ни доступ к микрофону. Это побочный эффект API, созданного по разумной причине — чтобы сообщать операционной системе, какой именно звук издаёт страница. В статье разбираем, что раскрывает Audio Session API, чего он страницам не сообщает и почему он принадлежит к тому же семейству API, которые создавались для адаптации к устройству, а заодно позволяют пассивно за ним наблюдать.
Ключевые выводы
navigator.audioSessionпозволяет странице объявить категорию звука через свойствоtype:auto,playback,transient,transient-solo,ambientилиplay-and-record. По нему операционная система решает, приглушать, ставить на паузу или смешивать остальной звук.- У сессии есть и
state—active,inactiveилиinterrupted, — а при его смене срабатывает событиеstatechange. interruptedвызывают события вне браузера, например входящий звонок или захват аудиофокуса другим приложением. Страница узнаёт, что что-то получило приоритет, и когда, но не узнаёт, кто звонил и что именно прервало звук.- Поддержка различается по движкам. WebKit выпустил подмножество API в Safari 16.4, MDN по-прежнему помечает его как экспериментальный с ограниченной доступностью, а что считать прерыванием, решает платформа, поэтому наличие API и его поведение — ещё и грубый сигнал о движке.
- Отключить его нельзя. Это поведение присуще самому факту звука на странице, так что реалистичная защита — осведомлённость и общая гигиена против фингерпринтинга.
Для чего нужен Audio Session API
Раньше браузеру приходилось угадывать, как звук страницы должен уживаться со всем остальным на устройстве. Страница видеозвонка, подкаст-плеер и страница, играющая короткий сигнал уведомления, снаружи выглядят похоже, но телефон должен обращаться с ними по-разному: звонок получает приоритет и заглушает другие приложения, подкаст ставится на паузу при входящем вызове, а сигнал лишь ненадолго приглушает остальной звук.
AudioSession решает это, позволяя странице сказать, чем она занята. Свойство type принимает такие значения:
| Тип | Назначение |
|---|---|
auto | Браузер выбирает сам по тому, что воспроизводится |
playback | Музыка, видео, подкасты — звук, ради которого пришёл пользователь |
transient | Короткие звуки вроде уведомления; остальной звук приглушается |
transient-solo | Короткие звуки, на время заглушающие всё остальное |
ambient | Фоновый звук, который смешивается с другими приложениями |
play-and-record | Двусторонний звук, например звонки |
Спецификация W3C называется «Audio Session», а WebKit объявил о поддержке её подмножества в заметках о выпуске Safari 16.4. Объявление типа — законная половина истории, и задумано оно удачно: платформа получает информацию, а не вынуждена выводить намерение.
Другая половина: состояние сессии
Тот же объект сообщает, в каком положении сейчас сессия:
if ("audioSession" in navigator) {
console.log(navigator.audioSession.type); // e.g. "playback"
console.log(navigator.audioSession.state); // "active", "inactive" or "interrupted"
}
Определены три состояния. active — страница воспроизводит или записывает звук, inactive (значение по умолчанию) — ни то ни другое, interrupted — платформа временно приостановила активную до этого сессию. При переходах срабатывает событие statechange, так что опрашивать состояние не нужно. Пока сессия прервана, браузер сам ставит на паузу медиаэлементы страницы, приостанавливает её AudioContext и отключает дорожки микрофона, а когда состояние возвращается в active, всё возобновляет.
Именно interrupted важно для приватности. В качестве примеров причин MDN приводит входящий звонок и другое приложение, захватившее звук в монопольное пользование. Родственное свойство Web Audio AudioContext.state использует то же слово — прерывание из-за события «вне контроля веб-приложения», — и там же MDN оговаривает, что способ срабатывания состояния interrupted может отличаться между браузерами. Точный набор триггеров определяют платформа и браузер, поэтому он различается.
Почему это история о приватности
Большинство сигналов о том, что пользователь делает со своим устройством, либо требуют разрешения, либо недоступны вебу. Разговариваете ли вы по телефону — страница знать не должна. Audio Session API выдаёт размытую версию этой информации как побочный продукт воспроизведения звука.
Важно точно обозначить пределы, потому что это легко преувеличить:
- Страница не узнает, кто звонил и что стало причиной прерывания. Она видит смену состояния, а не причину.
- Работает только пока у страницы есть аудиосессия. Если звука нет, прерывать нечего.
- Одно событие — слабое свидетельство. Звонок и перехват аудиофокуса другим приложением могут выглядеть одинаково.
Остаётся поведенческая хронология. Поскольку страница видит и возврат в active, она может засечь длительность каждого прерывания. Повторяющиеся прерывания, их время и длительность состояния interrupted складываются в запись о том, когда устройство было занято чем-то другим. Идентификатором это само по себе не является, но именно такой малозаметный сигнал без запроса любят собирать системы аналитики и антифрода, и пользователь не ждёт, что страница его увидит.
Тихий сигнал: определение возможностей
Есть и вторая, более привычная утечка. Существует ли navigator.audioSession вообще и как срабатывает interrupted, зависит от движка. WebKit выпустил подмножество в Safari 16.4, MDN помечает API как экспериментальный и не входящий в Baseline, а для близкого свойства AudioContext.state прямо пишет, что способ срабатывания прерывания может отличаться между браузерами. Это расхождение — ровно тот шаблон, что описан в статье об определении версии движка по возможностям: возможность есть в одном движке и нет в другом, и это сужает круг браузеров и ОС без чтения строки user-agent.
Именно так для Chromium работает проверка ядра BrowserInsight. Её матрица возможностей проверяет аудио-API, например AudioContext.setSinkId(), чтобы поместить браузер на шкалу версий. Уточним границы: сайт не опрашивает navigator.audioSession, AudioSession.state и AudioContext.state, и ни один инструмент здесь не сообщает о звонках или прерываниях. setSinkId() — лишь конкретный пример того, как наличие аудио-API служит сигналом о движке.
Тот же шаблон, что у других API состояния устройства
Это не уникально для звука. Повторяющийся урок: API, созданные, чтобы страницы могли подстраиваться под устройство, заодно служат пассивным наблюдением за ним:
- Battery Status API отдавал страницам уровень заряда и состояние зарядки без запроса; позже Firefox его убрал, а WebKit так и не выпустил.
- Network Information API раскрывал тип соединения и оценки, с уклоном в Chromium.
- Перечисление медиаустройств показывает, какие камеры и микрофоны подключены.
- Датчики устройства выдают данные о движении и ориентации.
Везде исходная цель настоящая. Цена для приватности возникает из сочетания: нет запроса разрешения, данные обновляются непрерывно, реализации в браузерах неодинаковы.
Почему на мобильных это заметнее
Прерывания на телефоне частые и осмысленные, на десктопе — редкие. Звонки и борьба приложений за аудиофокус на мобильном происходят постоянно, поэтому сигнал там и богаче, и лучше различает пользователей. Потому статья и входит в мобильный кластер: на настольном браузере тот же API по большей части молчит. Общую картину того, чем отличаются телефоны, см. в статье о фингерпринтинге мобильных браузеров.
Что можно сделать на деле
Честно говоря, очень мало. Переключателя для Audio Session API нет, а поведение следует из самого наличия звука на странице. Страницам, которые не воспроизводят звук, наблюдать нечего. В остальном реалистичный ответ — общие меры, подходящие для любых мелких сигналов:
- Блокируйте или ограничивайте ненужные скрипты с помощью расширения для блокировки контента.
- Выбирайте браузер с более строгими настройками защиты от фингерпринтинга по умолчанию.
- Посмотрите, что раскрывает ваш браузер, в проверке отпечатка, а общую картину — в статье что такое отпечаток браузера.
Важны и несоответствия: профиль, который заявляет одну платформу, а показывает поверхность API другой, — это тот тип расхождений, что разобран в статье о согласованности отпечатка.
Часто задаваемые вопросы
Может ли сайт понять, что я разговариваю по телефону?
Напрямую нет. Страница, воспроизводящая звук, видит, что её аудиосессия стала interrupted, и звонок может это вызвать. Она может засечь, сколько длилось прерывание, но не узнает, кто звонил, и не поймёт, был ли виной звонок или что-то другое, например другое приложение, перехватившее звук.
Нужно ли для Audio Session API разрешение?
Нет. Это свойство navigator, и чтение его типа и состояния не вызывает запроса. Во многом именно поэтому оно важно для приватности.
Какие браузеры его поддерживают?
WebKit выпустил подмножество в Safari 16.4. MDN помечает API как экспериментальный с ограниченной доступностью, поэтому актуальную таблицу совместимости смотрите на странице MDN, а не полагайтесь на догадки.
Можно ли его отключить?
Настройки нет. Если страница не воспроизводит звук, прерывать нечего, а блокировка ненужных скриптов ограничивает круг наблюдателей.
Заключение
Audio Session API — разумный ответ на реальную проблему: операционная система должна знать, какой звук издаёт страница. Его состояние interrupted — непреднамеренное дополнение: страница замечает, что нечто вне браузера получило приоритет, без запроса и не узнавая причины. Сигнал сам по себе слабый, на телефонах богаче, чем на десктопах, и вместе с API батареи, сети и датчиков напоминает: функции адаптации и функции наблюдения часто оказываются одной и той же функцией.
Рекомендуем прочитать:


