Содержание статьи +
- Кратко
- Почему Это Важно
- Аудиотракт WebRTC И Три Дома Для Подавителя
- Начните С Того, Что У Вас Уже Есть: Встроенный Подавитель
- Почему Шумоподавление Не Может Жить В Encoded Transform
- Обвязка RNNoise В Браузере: Паттерн AudioWorklet
- Частая Ошибка: Два Подавителя Сразу
- DeepFilterNet В Браузере: Проблема Веса
- Клиент Или Сервер: Выбирайте По Тому, Чем Вы Управляете
- Krisp ИИ: Управляемый Путь В WebRTC
- RNNoise WASM Против Krisp AI: Build-vs-buy Для WebRTC
- Где Здесь Фора Софт
- Ключевые Выводы
- Что Почитать Дальше
Кратко
В WebRTC-звонке у шумоподавления есть ровно три места, где оно может жить – встроенный браузерный подавитель, который вы включаете бесплатно; собственная модель, встроенная в звуковой тракт до сжатия аудио; либо модель на сервере, – и выбор неправильного места это самая частая и самая дорогая ошибка команд. Путь «собственная модель в клиенте» означает запуск модели вроде RNNoise (крошечной, бесплатной, скомпилированной в WebAssembly) или DeepFilterNet (тяжелее, но качественнее) внутри AudioWorklet – небольшого узла браузерной звуковой обвязки, который работает вне главного потока; путь «сервер» означает лицензирование управляемого движка вроде Krisp AI – on-device SDK, который стоит за Discord и RingCentral, а теперь подключается к LiveKit, Twilio и Daily. Главное правило, связывающее всё воедино: шумоподавлению нужно сырое, несжатое аудио, поэтому оно обязано стоять до Opus-энкодера – и никогда внутри WebRTC Encoded Transform, который видит только уже сжатые кадры. Эта статья показывает три точки вставки, обвязку для каждой, ловушку двойного подавления, которая портит качество, и как выбрать между RNNoise WASM, DeepFilterNet и Krisp ИИ для реального WebRTC-продукта.
Почему Это Важно
Если ваш продукт ведёт живые звонки в браузере – видеоконференции, телемедицина, голосовой ИИ-агент, инструмент для коучинга продаж – фоновый шум это самый быстрый способ сделать его дешёвым на ощупь, а шумоподавление это лекарство. Но в WebRTC сложная часть не в том, какую модель взять; а в том, куда её поставить, потому что одна и та же модель даёт чистое аудио в одном слоте и сломанный, роботизированный звук в другом. Статья для продакт-менеджера, основателя или инженерного лида, которому нужно решить, как чистое аудио встроится в WebRTC-продукт, и говорить об этом с инженерами, не давая обмануть себя демкой. К концу вы будете понимать аудиотракт WebRTC достаточно, чтобы знать, почему шумоподавление стоит до энкодера, как RNNoise и Krisp ИИ реально цепляются к живому звонку, почему два подавителя одновременно делают хуже и как выбрать между «собрать самому» и «купить управляемый движок». Если вам нужно глубокое сравнение того, как различаются модели по скорости, качеству и лицензиям – это в нашей спутниковой статье про модели шумоподавления; эта же статья про то, как встроить их в WebRTC.
Аудиотракт WebRTC И Три Дома Для Подавителя
Чтобы правильно разместить подавитель, сначала нужна мысленная карта того, где звук идёт в WebRTC-звонке. Путь всегда один и тот же. Микрофон захватывает звук. Браузер немного его чистит. Дальше аудио сжимается кодеком – почти всегда Opus, кодеком, поддержку которого WebRTC требует от каждого браузера (IETF, RFC 7874). Сжатое аудио идёт по сети, часто через сервер под названием SFU – Selective Forwarding Unit, реле, которое копирует поток каждого участника всем остальным. На дальнем конце аудио распаковывается и проигрывается в ухо слушателя.
Слово «сжатое» здесь важнее всего, поэтому закрепим его. Сжать аудио значит выбросить часть деталей, чтобы данные стали достаточно маленькими для отправки – как сохранить фото маленьким JPEG вместо полноразмерного оригинала. После сжатия Opus отдельные звуковые сэмплы исчезают; остаётся плотная упаковка байт, которую декодер превращает обратно в приблизительный звук. Запомните это, потому что от этого зависит всё ниже.
Подавитель шума можно вставить ровно в три места на этом пути. Первое – встроенный подавитель, который браузер уже запускает на захвате, до всего остального. Второе – собственная модель, которую вы вставляете сами, после захвата, но до того, как Opus-энкодер сожмёт звук. Третье – на сервере: внутри SFU, внутри ИИ-агента, который принимает звонок, или на шлюзе телефонной линии для звонков, приходящих из обычной телефонной сети. У каждого дома своя цена, и большая часть статьи про выбор между ними.
Начните С Того, Что У Вас Уже Есть: Встроенный Подавитель
До интеграции чего-либо проверьте, не хватает ли вам уже бесплатного подавителя. Каждый WebRTC-браузер поставляет на захвате стадию чистки аудио, в которую входят шумоподавление, эхоподавление и автоматическая регулировка усиления. Шумовую часть вы включаете одной опцией, когда запрашиваете микрофон.
// Запрашиваем микрофон со встроенными шумоподавлением и эхоподавлением.
navigator.mediaDevices.getUserMedia({
audio: { noiseSuppression: true, echoCancellation: true },
video: false
});Опция noiseSuppression это часть стандарта W3C Media Capture and Streams – спецификации, которая определяет, как веб-страница получает микрофон (W3C, Media Capture and Streams). Когда вы ставите её в true, браузер применяет свой встроенный подавитель. Это бесплатно, не требует работы по интеграции, и аудио не покидает устройство.
Подвох – в качестве. Встроенный подавитель настроен под обычный двусторонний разговор в умеренной комнате. Со стабильным вентилятором или гулом он справляется хорошо, но на трудных случаях он слабее современной специализированной модели – перекрывающиеся фоновые голоса, внезапный лязг, шумное кафе. Для многих продуктов встроенной базы реально достаточно, и правильное инженерное решение – выпустить её и идти дальше. Тянуться за её пределы стоит лишь когда пользователи жалуются на шум, который она пропускает, или когда нужно одинаковое поведение во всех браузерах вместо собственной версии каждого. (Про правило «сначала попробуй встроенную базу» и про разницу в качестве моделей – см. статью про модели.)
Почему Шумоподавление Не Может Жить В Encoded Transform
Когда команды решают добавить собственный подавитель, первый неверный поворот – потянуться не за тем API. WebRTC даёт фичу под названием Encoded Transform, которая позволяет запускать свой код на медиа по мере его прохождения через звонок, и звучит как идеальная зацепка. Для чистки аудио это неверный крючок, и понимание почему учит главному правилу.
Стандарт WebRTC Encoded Transform запускает ваш код на закодированных кадрах – на аудио после того, как кодек Opus его уже сжал, между энкодером и частью, которая упаковывает его для сети (W3C, WebRTC Encoded Transform). Вспомните аналогию с JPEG: к этому моменту отдельные звуковые сэмплы выброшены и заменены сжатыми байтами. Подавитель шума работает, изучая собственно звук – какие частоты это голос, какие шум – и приглушая шум. Он не может сделать этого с упаковкой сжатых байт, как нельзя стереть человека с фото, редактируя данные сжатия файла. Encoded Transform создан для вещей, которые работают со сжатой упаковкой целиком, например для сквозного шифрования. Для шумоподавления это неверный слой.
Верный слой – сырое аудио: несжатый поток звуковых сэмплов до того, как энкодер их коснётся. Браузер даёт два пути к сырому аудио. Старый, широко поддержанный путь – AudioWorklet из Web Audio API, небольшой узел обработки звука, который браузер запускает в выделенном звуковом потоке (W3C, Web Audio API). Новый путь – MediaStreamTrackProcessor, который отдаёт каждый кусок микрофонного аудио как сырой объект AudioData, который можно прочитать и изменить (W3C, MediaStreamTrack Insertable Media Processing). Оба ставят ваш код в верное место: после захвата, на сырых сэмплах, до Opus-энкодера. Это точка вставки B с Рис. 1, и именно сюда относится любой собственный подавитель.
Обвязка RNNoise В Браузере: Паттерн AudioWorklet
Самый чистый пример встраивания собственного подавителя в WebRTC-звонок – это RNNoise в AudioWorklet, и он не теоретический: ровно так шумоподавление поставляет open-source платформа конференций Jitsi Meet. Разбор их подхода показывает все движущиеся части.
RNNoise – крошечный open-source подавитель шума, написанный на языке C. Чтобы запустить его в браузере, его компилируют в WebAssembly – обычно сокращают до WASM – формат, который позволяет небраузерному коду вроде C работать почти с нативной скоростью внутри веб-страницы (Jitsi, 2022). Скомпилированный модуль весит несколько сотен килобайт, достаточно мало, чтобы загрузиться мгновенно.
Причина, почему он идёт в AudioWorklet, а не в старый звуковой код, – отзывчивость. Ранний браузерный узел обработки звука работал на главном потоке – том же, что рисует страницу и обрабатывает клики, – поэтому любой сбой в интерфейсе мог исказить аудио. AudioWorklet работает на отдельном выделенном звуковом потоке, так что звук обрабатывается без помех от остальной страницы (W3C, Web Audio API). Jitsi перешёл со старого подхода на главном потоке к AudioWorklet именно потому, что когда вы изменяете аудио, а не просто измеряете, любая задержка или заикание становятся слышны (Jitsi, 2022).
Здесь есть один кусок арифметики, в который упирается каждая команда, и его стоит показать, потому что он объясняет реальный объём работы по интеграции. AudioWorklet отдаёт вашему коду аудио фиксированными блоками по 128 сэмплов за раз – размер изменить нельзя (W3C, Web Audio API). RNNoise же хочет обрабатывать 480 сэмплов за вызов (Jitsi, 2022). При стандартных для WebRTC 48 000 сэмплов в секунду эти числа переводятся во время так:
128 сэмплов ÷ 48 000 сэмплов/с = 0,00267 с ≈ 2,67 мс (что отдаёт worklet)
480 сэмплов ÷ 48 000 сэмплов/с = 0,01000 с = 10,0 мс (что хочет RNNoise)Блок, который отдаёт браузер (2,67 мс), меньше блока, который нужен модели (10 мс), поэтому нельзя просто передавать каждый блок прямо в RNNoise. Решение – буфер-накопитель, называемый кольцевым буфером: вы копите маленькие блоки по 128 сэмплов, пока не наберёте 480, отправляете это в RNNoise на очистку, затем передаёте чистое аудио дальше – оставляя излишек сэмплов на следующий круг (Jitsi, 2022). Как только worklet выдаёт чистое аудио, вы подменяете им исходную микрофонную дорожку, и дальше звонок идёт как обычно: Opus кодирует чистый звук, и все слышат разницу.
// Набросок: пропустить микрофон через AudioWorklet шумоподавления и отправить чистую дорожку.
const ctx = new AudioContext({ sampleRate: 48000 });
await ctx.audioWorklet.addModule('rnnoise-worklet.js'); // ваш скомпилированный WASM + worklet
const mic = await navigator.mediaDevices.getUserMedia({
audio: { noiseSuppression: false, echoCancellation: true } // встроенное NS ВЫКЛ — см. ниже
});
const source = ctx.createMediaStreamSource(mic);
const denoiser = new AudioWorkletNode(ctx, 'rnnoise-processor');
const sink = ctx.createMediaStreamDestination();
source.connect(denoiser).connect(sink);
const cleanTrack = sink.stream.getAudioTracks()[0]; // эту дорожку отправляем по peer connectionЧастая Ошибка: Два Подавителя Сразу
Присмотритесь к коду выше – там написано noiseSuppression: false. Это не опечатка: это самая важная строка, и ошибиться в ней – самая частая ошибка во всей теме.
Ловушка – двойное подавление. Если оставить встроенный подавитель браузера включённым и запустить свою модель, аудио проходит через два подавителя подряд. Это хуже любого из них по отдельности по двум причинам. Первая – впустую потраченные вычисления: вы платите процессорную цену дважды за одну работу, что садит батареи ноутбуков и заикается на телефонах. Вторая – испорченное аудио: современный подавитель обучен на сыром, нетронутом звуке, и подача ему аудио, которое другой подавитель уже изменил, сбивает его и может дать странный, «обработанный» результат. LiveKit, который лицензирует модели шумоподавления в свою платформу, прямо формулирует правило в своей документации – не включайте модель шумоподавления поверх аудио, которое другая модель уже обработала, потому что модели обучены на сыром аудио и иначе могут вести себя непредсказуемо (LiveKit, 2026).
Решение – простая дисциплина: ровно один подавитель шума в тракте. Когда отправляете собственную модель, ставьте noiseSuppression: false, чтобы встроенный подавитель браузера отошёл в сторону. Когда полагаетесь на встроенный, не добавляйте ещё и свою модель. Эхоподавление и автоматическая регулировка усиления – отдельные задачи и обычно могут оставаться включёнными: правило – один шумоподавитель, а не один аудиопроцесс в целом. (Эхоподавление – соседняя, но отдельная проблема, разбор в нашей статье про эхоподавление в WebRTC.)
DeepFilterNet В Браузере: Проблема Веса
RNNoise достаточно лёгкий, чтобы работать в любом браузере. DeepFilterNet – open-source модель, дающая заметно более высокое качество за счёт тяжёлого двухстадийного дизайна, – встраивается сложнее, и причина в размере и инструментарии.
Обычный способ запустить DeepFilterNet в браузере – через ML-рантайм ONNX Runtime Web, и сам рантайм весит около 11,8 мегабайта до добавления модели – тяжёлая загрузка по сравнению с несколькими сотнями килобайт RNNoise. Исторически у него также были трудности с работой внутри AudioWorklet – того самого места, где должно жить аудио реального времени. Команды обходят это собранными вручную WebAssembly-версиями, которые гораздо меньше, и рабочие интеграции DeepFilterNet для WebRTC-клиентов существуют, но это больше инженерных усилий, чем RNNoise, для браузерного развёртывания. Практический паттерн в 2026: берите RNNoise WASM, когда нужна бесплатная модель целиком в браузере, и рассматривайте DeepFilterNet, когда его более высокое качество оправдывает лишний вес – или запускайте его на сервере, где размер перестаёт иметь значение. О том, как две модели сравниваются по чистому качеству и задержке – см. статью про модели.
Клиент Или Сервер: Выбирайте По Тому, Чем Вы Управляете
Все пути с собственной моделью выше работают в браузере пользователя – на стороне клиента. Третий дом, сервер, – верный выбор в наборе ситуаций, которые стоит назвать чётко, потому что решение упирается в один вопрос: управляете ли вы устройством, с которого приходит аудио?
У работы в клиенте, в браузере, есть реальные плюсы. Аудио чистится до того, как его коснётся теряющий качество Opus-энкодер, а это лучший возможный момент – вы очищаете оригинальный звук, а не сжатую копию. Вычислительная цена раскладывается по устройствам всех пользователей, так что она масштабируется бесплатно по мере добавления участников, а сервер остаётся дешёвым. Это вариант по умолчанию для конференций браузер-к-браузеру.
Работа на сервере становится необходимой, когда вы не управляете исходным устройством. Самый ясный случай – обычная телефонная сеть: когда кто-то дозванивается в ваш продукт с обычного телефона через то, что инженеры называют SIP – протокол, мостящий интернет-звонки к телефонным линиям, – на его конце нет браузера, чтобы запустить модель, поэтому единственное место для чистки этого аудио – ваш сервер. Та же логика – для голосовых ИИ-агентов: бот, который входит в звонок, чтобы транскрибировать или отвечать, принимает аудио из многих источников, и чистить его централизованно, на входе, проще всего – а чистое аудио прямо повышает точность любых живых субтитров или транскрипции поверх. Сервер также даёт одно место для контроля качества и обновления моделей – ценой процессорного времени, за которое вы теперь платите на каждом потоке. Тяжёлые GPU-движки вроде аудиоэффектов NVIDIA Maxine живут здесь, очищая аудио на серверных видеокартах до того, как оно пойдёт в транскрипцию или проигрывание (NVIDIA, 2026).
| Вопрос | Клиент (браузер) | Сервер (SFU / агент / SIP) |
|---|---|---|
| Где работает | На устройстве пользователя | На ваших серверах |
| Относительно Opus-энкодера | До кодирования (чистит оригинал) | После декодирования (чистит сжатую копию) |
| Кто платит за вычисления | Устройство пользователя | Вы, за каждый поток |
| Масштабируется с числом юзеров | Да, автоматически | Нет – растёт ваша цена |
| Работает для дозвона (SIP) | Нет (на их конце нет браузера) | Да |
| Лучше всего для | Конференций браузер-к-браузеру | ИИ-агентов, телефонных мостов, контроля |
Честное резюме: чистите в клиенте, когда все участники в браузере, которым вы управляете, и чистите на сервере, когда аудио приходит с устройств или сетей, которыми вы не управляете. Многие боевые системы делают и то, и другое – клиент для браузерных юзеров, сервер для дозвона.
Krisp ИИ: Управляемый Путь В WebRTC
Пока собственные модели были теми, что вы сами обвязываете и эксплуатируете. Krisp ИИ – альтернатива: управляемый коммерческий движок, который вы лицензируете и встраиваете, где вендор владеет моделью и покрытием платформ. Поскольку «Krisp» – имя, которое команды слышат первым, стоит уточнить, что это такое и как оно цепляется к WebRTC-звонку.
Krisp – Voice ИИ компания, основанная в 2017 году в Беркли, Калифорния, чьё ПО шумоподавления работает целиком на устройстве – по заявлению самой компании, аудио никогда не загружается на её серверы (Krisp, 2026). Её технология стоит за шумоподавлением в Discord, RingCentral, Zoho и, через партнёрства, в платформах звонков Twilio и Daily; в 2025 году компания заявила около $37,7 млн годовой выручки (getLatka, 2026). Krisp поставляется как SDK – software development kit, готовая библиотека кода, которую разработчик встраивает в приложение – под Windows, macOS, Linux, Android, iOS и браузеры, последние через WebAssembly-сборку. В живом звонке он добавляет примерно 25 миллисекунд задержки для стандартной модели и около 15 для облегчённой, что удерживает его в рамках бюджета задержки разговора (Krisp, 2026).
Как он цепляется к WebRTC, зависит от слота. В браузере Krisp ставится как аудиопроцессор на микрофонную дорожку до отправки аудио – та же точка вставки B, что и у RNNoise, только управляемая за вас. LiveKit, например, отдаёт Krisp через однострочный track processor в своём web SDK:
// Управляемый фильтр Krisp от LiveKit: цепляем к локальной микрофонной дорожке до публикации.
const { KrispNoiseFilter } = await import('@livekit/krisp-noise-filter');
const krisp = KrispNoiseFilter();
await localAudioTrack.setProcessor(krisp); // чистит исходящее аудио в браузере
await krisp.setEnabled(true);На сервере Krisp работает внутри платформы: Twilio загружает Krisp SDK рядом со своим Voice JS SDK и запускает его как шаг пред-обработки между микрофоном и аудиоэнкодером, а LiveKit и другие запускают его на входящем аудио для ИИ-агентов и включают на телефонном шлюзе одним флагом krisp_enabled: true для SIP-звонков (Twilio, 2026; LiveKit, 2026).
Самая полезная в 2026 способность Krisp для конференций – вторая модель под названием background voice cancellation, или BVC. Обычное шумоподавление убирает неречевой звук – вентиляторы, трафик, клавиатуру – сохраняя все голоса. BVC идёт дальше и убирает чужие голоса, оставляя только основного говорящего. Это важно в open-space и для голосовых ИИ-агентов, где иначе коллега, говорящий рядом, транскрибируется как сам говорящий. Улучшение измеримо: в опубликованном тесте LiveKit сырое шумное аудио дало word-error rate транскрипции 117,6 процента (хуже бесполезного – в транскрипте больше ошибок, чем слов), тогда как модель BVC от Krisp срезала это до 23,5 процента, а конкурирующий движок ai-coustics достиг 7,1 процента (LiveKit, 2026). Урок двойной: эти модели работают, и серьёзный вендор теперь не один – Krisp самый известный, но уже не единственный управляемый вариант.
RNNoise WASM Против Krisp AI: Build-vs-buy Для WebRTC
Сведённое к сути, решение для WebRTC-продукта – это развилка из трёх путей, и она отличается от общего сравнения моделей, потому что она про эксплуатацию, а не только про качество.
| Вариант | Что вы поставляете | Цена | Качество на трудном шуме | Кроссплатформенность | Лучше всего для |
|---|---|---|---|---|---|
| RNNoise WASM | Модель, которую вы компилируете и обвязываете в AudioWorklet | Бесплатно (BSD) | Хорошо на стабильном, слабее на трудном | Каждую платформу строите сами | Браузер, скромный бюджет, обычный шум |
| DeepFilterNet | Тяжёлая open-модель, браузер или сервер | Бесплатно (MIT / Apache) | Выше, ценой веса и задержки | Каждую платформу строите сами | Чувствительность к качеству, есть запас |
| Krisp ИИ (или ai-coustics) | Лицензируемый управляемый SDK + процессор | Платно | Боевое; BVC убирает чужие голоса | Все основные «из коробки» | Кроссплатформа, ноль эксплуатации, агенты, SIP |
Читайте как эксплуатацию, а не турнирную таблицу. RNNoise WASM бесплатен и целиком ваш, но вы компилируете его, обвязываете AudioWorklet, управляете буферизацией и принимаете его потолок качества на трудном шуме. Krisp (а теперь и ai-coustics) стоит денег, но отдаёт боевое качество на всех платформах, модель удаления чужих голосов и ноль обслуживания – модель обновляет вендор, а не вы. Сравнение брендов – Krisp против NVIDIA Maxine и Dolby для решения build-vs-buy – это отдельная тема, в нашей статье Krisp vs Maxine vs Dolby; правило здесь уже: если вы поставляете только в браузере и шум обычный, RNNoise WASM – самый дешёвый верный ответ, а как только нужны все платформы, поддержка дозвона или удаление чужих голосов, управляемый движок отрабатывает свою цену.
Где Здесь Фора Софт
Мы строим WebRTC-продукты, зависящие от чистого живого аудио – платформы видеоконференций, телемедицинские консультации, где врач должен расслышать каждое слово, e-learning-классы и ИИ-инструменты для встреч. В этой работе выбор интеграции важнее имени модели. Для браузерной конференц-фичи на скромном бюджете верный ответ часто – сначала встроенная база, затем RNNoise в AudioWorklet там, где пользователи упёрлись в её пределы – обвязанный до энкодера, со встроенным подавителем, выключенным во избежание двойной обработки. Для продуктов, принимающих дозвон или запускающих голосовых ИИ-агентов, серверное подавление на входящем аудио – единственный вариант, покрывающий устройства, которыми мы не управляем, и управляемый движок с удалением чужих голосов обычно стоит там своей цены. Паттерн, который мы применяем, – решить три вопроса по порядку: где в тракте, клиент или сервер, собрать или купить – до того, как кто-то коснётся модели, потому что подавитель в неверном слоте это не проблема качества, которую можно подкрутить, а проблема архитектуры, которую придётся перестраивать.
Ключевые Выводы
- У WebRTC-шумоподавления три дома: встроенный, собственный до энкодера, серверный.
- Шумоподавлению нужно сырое аудио – ставьте его до Opus, не в Encoded Transform.
- Собственные модели идут в AudioWorklet, вне главного потока; RNNoise компилируется в WASM.
- Никогда не запускайте два подавителя – ставьте noiseSuppression: false со своей моделью.
- Чистите в клиенте для браузерных юзеров; на сервере для дозвона и ИИ-агентов.
- Krisp ИИ – управляемый путь; его модель BVC убирает чужие голоса, не только шум.