Модерация контента в реальном времени в SFU

Автор: Николай СапуновОбновлено: август 202620 мин чтения
Содержание статьи +

Кратко

Модерация контента в реальном времени – это задача поймать вредное видео, аудио или сообщение в живом звонке или трансляции достаточно быстро, чтобы среагировать до того, как это увидят другие; и естественное место для неё – медиа-сервер, который и так использует каждый групповой звонок, то есть SFU, потому что это единственная точка, видящая поток каждого участника. Проверить каждый кадр невозможно, поэтому реальная система берёт несколько кадров в секунду, гейтит звук по наличию речи, гоняет дешёвые детерминированные проверки перед дорогими и превращает оценку уверенности классификатора в действие: размыть, заглушить, предупредить, заблокировать или передать человеку. Одно решение определяет всю архитектуру и удивляет большинство команд: если включить настоящее сквозное шифрование на SFrame, сервер перестаёт видеть медиа – и серверная модерация просто перестаёт работать, проверку приходится переносить на устройство. Известные материалы с сексуальным насилием над детьми – отдельная категория: их находят по «отпечатку», о них обязывает сообщать закон, и их нужно сохранять как улику, а не тихо удалять, поэтому этот путь проектируют раньше всех остальных.

Почему это важно

Как только ваш продукт позволяет незнакомцам выходить в живой эфир друг к другу – соцсеть, дейтинг-сервис, маркетплейс с живым видео, виртуальный класс, комната ожидания телемедицины – вы унаследовали проблему безопасности, которая приходит в реальном времени и которую нельзя убрать постфактум. Вредный кадр, дошедший до зрителя, уже нанёс вред; нелегальный материал, прошедший через ваши серверы, уже создал юридическое обязательство. Эта статья – для продакт-менеджера, основателя или техлида, которому нужно описать функцию модерации, выставить разумный бюджет по задержке и стоимости и поговорить с инженерами и юристами, не утонув в жаргоне ни тех, ни других. Она объясняет, где живёт модерация в живой системе, что именно она проверяет, во что обходится и какие части за вас решает закон, а не ваш вкус. О версии этой задачи для архива – модерации миллионов уже записанных клипов – читайте в капстоне про конвейер UGC-модерации; эта статья – про живой путь.

Что на самом деле значит «модерация контента в реальном времени»

Начнём со слов, потому что за «модерацией» прячутся две очень разные задачи, которые постоянно путают, и путаница приводит к системам, промахивающимся мимо собственной цели.

Первая задача – модерация постфактум. Пользователь загружает видео; через секунды или минуты система его проверяет и решает, публиковать ли. В расписании есть запас: если проверка занимает тридцать секунд, никто не пострадал, потому что ничего ещё не было видно. Вторая задача – модерация в реальном времени, и запаса у неё нет вообще. Контент уже в эфире: человек прямо сейчас на камере, прямо сейчас говорит с другими людьми, и если он покажет что-то вредное, зрители увидят это в ту же секунду. Ваша модерация должна обнаружить и среагировать внутри короткого окна, пока вредный момент не разошёлся, а в живом звонке это доля секунды или пара секунд. Разница между двумя задачами – как разница между охранником, отсматривающим вчерашние записи, и охранником, который смотрит на мониторы вживую. Эта статья целиком про второго охранника.

Живое ограничение перекраивает всё. Нельзя ждать медленного, аккуратного, дорогого анализа, потому что к моменту его завершения вред уже нанесён. Нельзя посадить человека смотреть каждый поток, потому что потоков могут быть тысячи одновременно, а людей мало и они медленные. И нельзя просто блокировать всех заранее и проверять потом, потому что это сделает продукт непригодным для подавляющего большинства, кто не делает ничего плохого. Поэтому модерация в реальном времени – всегда компромисс между скоростью, стоимостью и точностью, и искусство в том, чтобы для каждого вида вреда решить, в какой точке этого треугольника сидеть.

SFU – единственное место, которое видит всё

Теперь архитектура – и хорошая новость в том, что нужный кусок вы почти наверняка уже запускаете. В звонке больше пары участников аудио и видео не летят напрямую между всеми. Они проходят через медиа-сервер в середине под названием Selective Forwarding Unit, сокращённо SFU – маршрутизатор, который принимает по одному потоку от каждого участника и пересылает нужные потоки всем остальным. Этот сервер и браузерные хуки вокруг него мы разбираем в статье про интеграцию ИИ в WebRTC.

SFU особенный для модерации по той же причине, по которой он особенный для живых субтитров и перевода: это единственная точка, видящая медиа каждого участника, разделённое по людям, в реальном времени. Это и делает его естественным домом для конвейера модерации. Вы снимаете поток один раз на SFU, гоняете проверки один раз и реагируете на результат один раз – вместо того чтобы пытаться запустить классификатор внутри браузера каждого участника, где вы не можете доверять коду и не видите других участников. Паттерн идентичен раздаче на стороне SFU, которую мы применяем для субтитров: один съём, центральная обработка, одно решение, разданное обратно.

Модерировать нужно три отдельные вещи, и им нужны три отдельные проверки, потому что это разные виды сигнала. Есть видео – кадры, где ищут наготу, сексуальные действия, насилие, оружие, кровь и известную нелегальную картинку. Есть аудио – речевая дорожка, где ищут угрозы, разжигание ненависти, сексуальные домогательства и оскорбления. И есть текст – сообщения чата, обычно идущие по data channel WebRTC, штатному боковому каналу для произвольных данных между участниками, описанному в IETF RFC 8831, где ищут травлю, мошенничество, доксинг и ссылки на вредные сайты. Полноценная система гоняет все три; многие команды сначала выпускают видео, потому что оно несёт самый тяжёлый и наименее спорный вред.

Рисунок 1. В групповом звонке конвейер модерации живёт на SFU – единственном сервере, который и так видит видео, аудио и чат каждого участника. Снимите каждый поток один раз и раздайте обратно одно решение.

Развилка шифрования, которая решает всю архитектуру

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

Обычный WebRTC-звонок зашифрован в транзите: медиа скремблируется, пока идёт по сети, но читаемо на SFU, потому что SFU обязан его декодировать, чтобы переслать. Именно эта читаемость и позволяет SFU модерировать. Но есть более строгий режим приватности – сквозное шифрование, сокращённо E2EE, при котором медиа скремблирует отправитель и расскремблировать может только получатель, но не сервер в середине. Стандарт, который делает это для медиа реального времени, – SFrame, опубликованный как IETF RFC 9605 в августе 2024 года. SFrame устроен умно: он шифрует медиа-кадры так, что SFU всё ещё видит достаточно метаданных, чтобы маршрутизировать их, но не видит картинку и не слышит звук. SFU пересылает запечатанные конверты, не имея возможности их вскрыть.

Вот развилка. То же свойство, что делает E2EE приватным – сервер не может читать медиа, – делает серверную модерацию невозможной, потому что нельзя классифицировать картинку, которую не видишь. У вас физически не может быть одновременно настоящего сквозного шифрования и серверной модерации на одном потоке; это противоречие, а не инженерный пробел, который закрывается усилиями. Это самое важное предложение в статье, и его чаще всего обнаруживают уже после того, как архитектура построена.

У вас есть три честных выхода, и выбираете вы под продукт. Можно гонять только транспортное шифрование и модерировать на SFU – верный выбор для открытого соцсетевого или дейтинг-продукта, где безопасность важнее максимальной приватности. Можно гонять настоящий E2EE и перенести модерацию на устройство, где медиа читаемо, приняв, что теперь вы доверяете клиентскому коду и не видите поверх участников – выбор приватного мессенджера. Или можно гонять гибрид, где большинство звонков E2EE, но помеченные или высокорисковые сессии опускаются до серверно-читаемых, чтобы их можно было проверить, с раскрытием этого понижения пользователям. Четвёртого варианта, дающего и то и другое разом, нет. Решите это первым, потому что именно это определяет, относится ли остальная статья к вашему серверу или к вашему клиенту.

Рисунок 2. Сквозное шифрование и серверная модерация взаимоисключающи на одном потоке. Развилка – модерировать на SFU, на устройстве или гибридно – это первое решение, а не последнее.

Каждый кадр посмотреть нельзя – поэтому вы семплируете

Допустим, вы выбрали серверно-читаемый путь. Следующий рефлекс у большинства неверный, и арифметика показывает почему. Рефлекс – гонять классификатор модерации на каждом кадре видео. Живое видео идёт, скажем, на тридцати кадрах в секунду, сокращённо fps – тридцать неподвижных картинок каждую секунду, показанных достаточно быстро, чтобы выглядеть движением. Представьте, что вы платите визуальному классификатору за проверку всех тридцати.

Допустим, одна проверка картинки стоит $0,001 – десятую цента, реалистичную цену хостинговой модерации в 2026 году. Гоняем её на каждом кадре одного потока:

30 fps × 60 с × $0,001 = $1,80 в минуту, на один поток

Для одного потока это уже больно; для тысячи одновременных потоков это $1 800 в минуту, что абсурдно для функции, которая ничего не зарабатывает. Поэтому каждый кадр не проверяют. Вы семплируете: проверяете несколько кадров в секунду и доверяете тому, что вред, видимый человеку, держится на многих кадрах, так что выборка его поймает. Семплирование на двух кадрах в секунду вместо тридцати режет тот же счёт в пятнадцать раз:

2 fps × 60 с × $0,001 = $0,12 в минуту, на один поток

Двух кадров в секунду хватает, потому что вредный контент, который зритель способен воспринять, не мелькает за одну тридцатую секунды; он задерживается, и проверка дважды в секунду на него попадёт. Выборку делают ещё умнее, добавляя кадры, которые важнее всего: ключевые кадры (периодические полные картинки, которые видеокодек и так производит) и кадры смены сцены (моменты, когда картинка сильно меняется – а это и есть момент появления нового контента). Аудио получает ту же обработку через Voice Activity Detection, сокращённо VAD – дешёвую программу, отвечающую на вопрос «говорит ли кто-то прямо сейчас?», – так что дорогая речевая проверка идёт только пока кто-то говорит, а не в тишине. Дисциплина та же, что держит доступными субтитры и перевод: обнаружь, что есть что проверять, и только потом трать деньги на проверку.

Слоёный конвейер: дёшево и точно перед дорого и размыто

Когда выборка решает, когда проверять, конвейер решает, что запускать, и правило – упорядочить проверки от самой дешёвой-и-самой-точной к самой дорогой-и-размытой, останавливаясь как можно раньше.

Первый слой – сопоставление по хешу для известной нелегальной картинки. Хеш – это цифровой отпечаток, короткая строка чисел, вычисленная из картинки. Известная система PhotoDNA, построенная Microsoft и лицензированная Google, Meta и другим, вычисляет отпечаток, переживающий мелкие правки вроде изменения размера или перекраски, так что картинка, уже опознанная как нелегальная, узнаётся, даже если её изменили, чтобы спрятать. Вы сравниваете отпечаток каждого выбранного кадра с базой отпечатков известных материалов с сексуальным насилием над детьми; совпадение быстрое, дешёвое и почти достоверное, и оно не требует от ИИ никакого суждения о картинке, которую он никогда не видел. Этот слой идёт первым, потому что он самый надёжный и самый юридически значимый.

Второй слой – визуальная классификация для вреда без отпечатка, потому что он новый: нагота, сексуальные действия, насилие, оружие, селф-харм, кровь. Это та самая ИИ-модель зрения – Hive, AWS Rekognition, Azure AI Content Safety, Google Cloud Vision, – которая смотрит на кадр и возвращает категории с оценками уверенности, например «явная нагота: 0,97». Она дороже и менее достоверна, чем хеш, поэтому гоняется на выбранных кадрах, прошедших проверку хешем. Когда фронтирная мультимодальная модель подходит лучше профильного классификатора – для тонких или контекстных решений – здесь тоже применима развилка «просто возьмём VLM».

Третий слой – модерация аудио. Речевую дорожку превращает в текст автоматическое распознавание речи, и текст оценивается на угрозы, разжигание ненависти и домогательства; некоторые движки, например Amazon Transcribe Toxicity Detection, читают и акустические признаки вроде крика, чтобы поймать токсичный умысел, который одни слова могли бы упустить. Четвёртый слой – модерация текст-чата: оценка сообщений на data channel на травлю, мошенничество и доксинг, самая дешёвая проверка из всех, потому что текст крошечный. Вот эти четыре медиа бок о бок:

МедиаЧто ищемТипичный инструментФорма стоимостиПервое действие
Видео-кадр (хеш)Известная нелегальная картинка (CSAM)PhotoDNA / перцептивный хешОчень дёшево, детерминированноБлок + сохранить + сообщить
Видео-кадр (классификатор)Новая нагота, насилие, оружие, кровьHive, Rekognition, Azure, GoogleУмеренно, на выбранный кадрРазмыть / приостановить / на ревью
АудиоУгрозы, разжигание ненависти, домогательстваASR + текст-классификатор; Transcribe ToxicityУмеренно, VAD-гейтЗаглушить / предупредить / на ревью
Текст-чатТравля, мошенничество, доксинг, плохие ссылкиAPI модерации текстаОчень дёшевоСкрыть / предупредить / блок
Рисунок 3. Упорядочьте проверки сначала дёшево-и-точно. Совпадение отпечатка для известной нелегальной картинки быстрое и решающее; размытый ИИ-классификатор гоняется лишь на кадрах, которые его пережили.

Материалы с насилием над детьми – отдельная категория

Бо́льшая часть модерации – вопрос политики и вкуса: ваш продукт сам решает, сколько кожи или мата он терпит. Одна категория – нет, и под неё вы проектируете раньше всех остальных, потому что закон уже всё решил.

Материалы с сексуальным насилием над детьми, сокращённо CSAM (child-sexual-abuse material), нелегальны везде и управляются правилами, которые перебивают ваши предпочтения. В США, как только провайдер становится осведомлён о наличии у себя видимого CSAM, федеральный закон – 18 U.S.C. § 2258A – обязывает его сообщить в CyberTipline, которую ведёт National Center for Missing & Exploited Children, сокращённо NCMEC, центральную точку приёма, передающую сообщения правоохранителям. Из этого следуют два инженерных вывода, которые легко сделать неправильно. Первый: вы не можете просто удалить материал, когда нашли его; вы обязаны сохранить его и связанные данные как улику на срок, который задаёт закон, так что ваше действие «блок» для этой категории пишет в запечатанное хранилище улик, а не в корзину. Второй: закон требует сообщать о том, о чём вы становитесь осведомлены – он не заставляет вас искать, и общего мандата на мониторинг нет, – но в момент срабатывания вашего хеш-матчера вы осведомлены, и часы пошли.

Вот почему сопоставление по хешу стоит в конвейере первым и почему его действие «блок» отличается от любого другого блока. Срабатывание классификатора наготы значит спрячь это и, может, отправь на ревью; срабатывание хеша CSAM значит останови поток, запечатай улику и подай сообщение. Стройте этот путь намеренно, с вашими юристами, в первый же день. Прикручивать его после запуска – так продукты в итоге либо нарушают закон, удаляя улики, либо рушат доверие, неправильно обращаясь с самыми чувствительными данными, к которым когда-либо притронутся. Технология обнаружения – перцептивный хеш – хорошо изучена; обязательство вокруг неё и есть та часть, которую надо инженерить с осторожностью.

От оценки уверенности к действию

Классификатор не возвращает «плохо». Он возвращает число – оценку уверенности между нулём и единицей, – и настоящий интеллект вашей системы это лестница, превращающая число в соразмерное действие. Ошибиться в лестнице – значит либо отпугнуть невинных пользователей, либо пропустить вред.

Логика пороговая. Выше высокой уверенности – скажем, 0,95 – вы реагируете автоматически и немедленно: размываете видео, глушите звук или приостанавливаете поток, потому что почти полная уверенность оправдывает действие без человека. В средней полосе – скажем, 0,70–0,95 – вы делаете что-то обратимое и направляете момент в очередь ревью человеком, потому что машина подозревает, но не уверена, и решение должен принять человек, прежде чем вы накажете пользователя. Ниже нижнего порога вы разрешаете, логируя оценку, чтобы потом настроиться. Два способа ошибиться тянут в противоположные стороны: ложноположительное размывает или выкидывает того, кто ничего не сделал, и делает продукт враждебным, а ложноотрицательное пропускает реальный вред к зрителям. Свести оба к нулю одновременно нельзя – опуская порог, вы ловите больше вреда, но наказываете больше невинных, – поэтому баланс ставится по категориям. Вы строги к тяжёлому, необратимому вреду и снисходительны к пограничному, и держите человека в петле везде, где оценка неопределённа, а цена ошибки высока.

Рисунок 4. Оценка – не решение. Высокая уверенность действует автоматически, неопределённая середина уходит человеку, а известная нелегальная картинка пропускает лестницу ради фиксированного юридического пути.

Бюджет задержки и стоимости, вслух

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

Сначала задержка. Чтобы модерация предотвращала вред, а не просто документировала его, решение должно прийти до того, как вредный кадр дойдёт до зрителей. Рычаг, покупающий время, тот же, что давно используют стриминговые площадки: небольшая задержка вещания. Придерживая живой поток на секунду-две перед тем, как он дойдёт до аудитории – современное эхо телевизионной «семисекундной задержки», – вы даёте конвейеру окно, чтобы взять кадр, оценить его и среагировать, пока контент ещё в буфере, а не на экранах зрителей. В плотном конференц-звонке, где даже секунда задержки вредит разговору, это окно купить нельзя, поэтому вы принимаете, что модерация реактивна – она отрезает нарушителя на такт позже, чем он начал, а не раньше, – и сильнее опираетесь на быстрые аудио-проверки и приостановку постфактум. Версия этой дисциплины тайминга для всего звонка – тема статьи про бюджет задержки до 100 миллисекунд.

Теперь стоимость – это та же математика выборки, перенесённая на парк. Возьмём площадку с пятьюстами одновременными живыми потоками, модерирующую видео на двух выбранных кадрах в секунду по $0,001 за кадр, где аудио и текст добавляют примерно ещё половину:

видео = 500 потоков × 2 fps × 60 с × $0,001   = $60,00 в минуту
аудио + текст ≈ 0,5 × видео                    = $30,00 в минуту
итого ≈ $90 в минуту ≈ $5 400 за час пиковой одновременности

Это число – выход проектирования, а не закон природы, и его двигают три рычага. Снижение частоты выборки режет его линейно, но рискует пропустить краткий вред. Гонять дешёвые слои хеша и текста на всём, а дорогой визуальный классификатор приберечь для потоков, которые уже чем-то помечены, режет резко. А self-host открытого визуального классификатора вместо оплаты за вызов переводит стоимость с «за кадр» на фиксированную инфраструктуру, что окупается выше объёма, который решает обычно комплаенс, а не арифметика. Смысл написать бюджет вслух в том, что «модерировать всё, всегда, на полной частоте кадров» – это не план, а способ обнаружить в проде, что безопасность может стоить дороже, чем продукт зарабатывает.

Частая ошибка: модерировать запись, а не живой поток

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

Но запись пишется после того, как живой поток уже отыграл аудитории. Модерация записи ловит вред на час позже, чем нужно, чтобы его остановить – она производит отчёт, а не защиту. Зрители уже увидели вредный кадр; единственное, что меняет поздняя проверка, – теперь у вас есть запись о вреде, который вы не предотвратили. Лекарство – та архитектура, что описана во всей этой статье: снимать живое медиа на SFU, в транзите, и реагировать внутри окна задержки вещания – а не на файле, который приземляется потом. Держите проверку записи тоже, как более медленный и тщательный бэкстоп, который может использовать тяжёлые модели и людей-ревьюеров, но никогда не путайте её с модерацией реального времени. Система безопасности, всегда приходящая после вреда, – не система безопасности; это архив ваших провалов.

Стройте на фреймворке, покупайте классификаторы, укомплектуйте очередь

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

Медиа-слой – это сам звонок. Можно гонять open-source SFU – mediasoup, Janus, сервер LiveKit – и владеть съёмом кадра и действием блокировки самому, читая кадры из потока браузерными хуками Encoded Transform и Insertable Streams, которые мы разбираем в статье про интеграцию ИИ в WebRTC, или взять хостинговую платформу реального времени, которая отдаёт медиа участников серверному агенту с меньшим количеством обвязки. LiveKit в частности относится к серверному агенту как к гражданину первого класса, поэтому он и всплывает в продакшен-сборках модерации.

Слой классификаторов – это то, что почти всегда покупают или self-host, а не тренируют с нуля. Хостинговые варианты – Hive, AWS Rekognition, Azure AI Content Safety, Google Cloud Vision, бесплатный модерационный эндпоинт OpenAI для текста и картинок – различаются не столько сырой способностью, сколько тем, в каком облаке вы уже живёте и как они тарифицируются; профильные вендоры вроде Hive меняют более высокую цену за вызов на более высокую точность в самых трудных визуальных категориях. Для CSAM конкретно вы не ходите по маркетплейсу: вы подаёте заявку в Microsoft на PhotoDNA или работаете с NCMEC и Tech Coalition, потому что база отпечатков ограничена by design. Слой поддержки – это часть, которую команды недооценивают и потом жалеют: очередь ревью человеком и люди, чтобы её укомплектовать, запечатанное хранилище улик для юридической категории, журнал аудита каждого решения (который EU Digital Services Act ожидает, что вы сможете объяснить) и путь апелляции, чтобы ошибочно заблокированный пользователь мог попросить человека посмотреть ещё раз. Конвейер – это хребет; очередь, журнал и апелляция – то, что делает его законным и человечным.

Где здесь Фора Софт

Мы строим живые видео-продукты, где модерация не опциональна – соцсети и дейтинг-приложения, где незнакомцы встречаются на камере, маркетплейсы и лайв-коммерс-площадки с открытым видео, e-learning и телемед-системы, где обязанность заботы явная, – и строим модерацию так, как доказывает эта статья: на SFU, который вы и так запускаете, снимая видео, аудио и чат один раз, гейтя траты выборкой и наличием речи, чтобы стоимость шла за риском, а не за местами. Поскольку мы работаем по видеонаблюдению, конференц-связи и регулируемым вертикалям, мы относимся к развилке шифрования как к проектному решению первого класса, а не к сюрпризу, и планируем неблагодарные части – очередь ревью человеком, запечатанный путь улик для нелегального материала, журнал аудита, читаемый регулятором, – с первого спринта, а не после первого инцидента. Модели обнаружения меняются каждый год; архитектура, решающая, где они гоняются, во что обходятся и кто ревьюит их ошибки, – та часть, которую стоит сделать правильно один раз.

Главное

  • Модерация в реальном времени должна сработать до того, как вред дойдёт до зрителей – запаса нет.
  • SFU – единственный сервер, видящий каждый поток; снимайте и решайте там один раз.
  • Настоящий E2EE (SFrame) и серверная модерация взаимоисключающи – выбирайте первым.
  • Каждый кадр не проверить; семплируйте несколько в секунду плюс ключевые кадры и смены сцены.
  • Гоняйте дешёвый, точный хеш перед дорогим, размытым ИИ-классификатором.
  • Известный CSAM – юридический путь: совпадение, запечатать как улику, сообщить в NCMEC, не удалять.

Что почитать дальше

Строите такую систему?

Подберём параметры кодирования под ваш контент и посчитаем стоимость доставки до старта разработки.