Демонстрация экрана через Android WebRTC: полное руководство по реализации в 2026

Подробнее по теме: читайте наш полный гайд — WebRTC на Android: SDK, захват, Compose UI (2026).

Демонстрация экрана через WebRTC на Android в 2026 году — это уже не задача на выходные: Android 14 сломал половину паттернов, которые работали в 2023-м. Если вы передаёте видео пользователям Android сегодня, вам нужен foreground service типа mediaProjection, запущенный до запроса проекции, нужна поддерживаемая библиотека WebRTC (готовая сборка от Google умерла) и нужно проектировать UX с учётом частичного захвата приложения, появившегося в Android 14+. Этот гайд проходит весь путь реализации, который команда Android в Фора Софт использует на боевых продуктах, таких как виртуальный класс BrainCert и система перевода VOLO.live на 22 000 участников, с код-скелетами, реальными бюджетами битрейта и пятью граблями, на которые наступают команды в продакшене.

Ключевые тезисы

  • Перестаньте использовать google-webrtc. Официальная сборка не поддерживается с 2018 года. В 2026 году берите getstream/webrtc-android (рекомендуем) или форк от LiveKit.
  • Сначала foreground service, потом проекция. Android 14 требует именно такого порядка; если перепутать, прилетит SecurityException и приложение упадёт.
  • 15 fps при 720p и 1,5–2 Mbps — реалистичная база для демонстрации экрана через сотовую сеть. 1080p — только когда вы подтвердили, что пользователь в Wi-Fi.
  • Частичный захват приложения в Android 14+ меняет UX-предпосылки: пользователь может выбрать одно окно. Слушайте onCapturedContentResize и onCapturedContentVisibilityChanged.
  • Android 15 автоматически прекращает захват на экране блокировки, скрывает содержимое уведомлений во время проекции и предоставляет callback состояния записи, чтобы приложения могли защищать чувствительные экраны.
  • Фора Софт выкатывает такие фичи быстрее за счёт переиспользования протестированного модуля захвата экрана между WebRTC-проектами — оценки получаются на 30–40% меньше по срокам и бюджету, чем при разработке с нуля.

Зачем мы написали это руководство

Фора Софт делает продукты на WebRTC с 2010 года, включая Android-клиенты BrainCert (LMS с годовой выручкой 225 млн ₽), VOLO.live (22 000+ участников на Black Hat 2025) и Sprii (платформа live-коммерции с оборотом €365 млн+). Демонстрация экрана — это функция, которую мы выкатили на нескольких Android-кодовых базах и нескольких версиях Android, и мы знаем, где у неё болевые точки.

Это руководство мы передаём новому Android-инженеру, который начинает работать над фичей демонстрации экрана в 2026 году. Каждый код-скелет компилируется, каждая цифра по битрейту взята из продакшен-трафика, каждая грабля — та, на которую мы наступили и которую починили.

Пропустить вперёд. Если нужен только код — переходите к скелету на Kotlin. Если у вас была работающая реализация, которая сломалась — читайте про изменения в Android 14. Если что-то горит в продакшене — идите к матрице диагностики.

Демонстрация экрана на Android — обзор за 60 секунд

На верхнем уровне путь демонстрации экрана на Android состоит из пяти подвижных частей:

1. MediaProjection. Системный API Android для захвата пикселей экрана. Требует согласия пользователя в каждой сессии.

2. Foreground service. Android 14 требует, чтобы media projection запускалась внутри foreground service типа mediaProjection, и сервис должен быть запущен до получения проекции.

3. ScreenCapturerAndroid. Реализация VideoCapturer из библиотеки WebRTC, которая оборачивает MediaProjection в поток кадров.

4. PeerConnection. Абстракция WebRTC, которая отвечает за ICE, сигналинг и SRTP-шифрование до удалённого пира.

5. Сигналинг. Внешний канал (WebSocket, SIP, кастомный), через который обмениваются SDP offer/answer и ICE-кандидатами.

Пропустите любой пункт — и функция не работает. Перепутайте их порядок на Android 14+ — и ОС убьёт приложение.

Выбор библиотеки WebRTC в 2026 году

Это первое решение — и то, в котором большинство команд ошибается. org.webrtc:google-webrtc от Google не поддерживается с 2018 года, а готовая сборка пропала вместе с закрытием JCenter. Если в ответе на Stack Overflow от 2025 года вам советуют использовать её — для 2026-го этот совет уже неверен.

Библиотека Статус Для каких задач Лицензия
getstream/webrtc-android Активна Новые проекты, свежие фичи WebRTC, поддержка Compose BSD
webrtc-sdk/android (LiveKit) Активна Приложения на базе LiveKit, изоляция namespace Apache 2.0
org.webrtc:google-webrtc Мертва с 2018 года Ни для чего — не используйте BSD
LiveKit Android SDK Активна Высокоуровневая абстракция, managed-инфраструктура Apache 2.0
Daily Android SDK Активна Клиенты Daily.co; готовые комнаты из коробки Проприетарная

Наш выбор для новых проектов: io.getstream:stream-webrtc-android. Активна, следует за апстримом WebRTC, дружественные Kotlin-API, поддержка Compose, без сюрпризов с лицензированием.

// build.gradle.kts (Module: app)

dependencies {
    implementation("io.getstream:stream-webrtc-android:1.3.6")
    // optional Compose helpers
    implementation("io.getstream:stream-webrtc-android-ui-compose:1.3.6")
}

Актуальную версию всегда проверяйте в репозитории GetStream/webrtc-android.

AndroidManifest.xml — разрешения и объявление сервиса

В Android 14 и выше пропущенные разрешения или неправильный тип сервиса убивают фичу — либо молча, либо с непонятными исключениями. Здесь нужно навести порядок в первую очередь.

<manifest ...>
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
  <uses-permission android:name="android.permission.RECORD_AUDIO" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

  <application ...>
    <service
      android:name=".ScreenShareService"
      android:foregroundServiceType="mediaProjection"
      android:exported="false" />
  </application>
</manifest>

Два неочевидных момента: FOREGROUND_SERVICE_MEDIA_PROJECTION обязателен начиная с Android 14, POST_NOTIFICATIONS — с Android 13. Оба должны быть в манифесте, и разрешение на уведомления нужно также запросить в рантайме.

Foreground service — порядок вызовов, который ломает Android 14

Начиная с Android 14, startForeground нужно вызывать до вызова getMediaProjection. Если перепутать порядок, прилетит SecurityException. Скелет:

class ScreenShareService : Service() {
  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    val notification = buildNotification()
    startForeground(
      NOTIF_ID, notification,
      ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
    )
    // NOW it's safe to grab the projection
    val resultCode = intent!!.getIntExtra(EXTRA_RESULT_CODE, -1)
    val data = intent.getParcelableExtra<Intent>(EXTRA_DATA)!!
    val mp = mediaProjectionManager.getMediaProjection(resultCode, data)
    startCapture(mp)
    return START_STICKY
  }
}

Что важно: пробрасывайте resultCode и data Intent от проекции в сервис через putExtra. Intent проекции одноразовый: если вы получили его в активити и потеряли — всё, потерян.

Запрос проекции — пляска согласия пользователя

Пользователь обязан подтверждать каждую сессию проекции. Подавить диалог невозможно. Поток такой: запускаем intent → получаем результат → передаём его в foreground service.

// In your Activity (Compose or View)
private val projectionLauncher = registerForActivityResult(
  ActivityResultContracts.StartActivityForResult()
) { result ->
  if (result.resultCode == RESULT_OK && result.data != null) {
    val svc = Intent(this, ScreenShareService::class.java).apply {
      putExtra(EXTRA_RESULT_CODE, result.resultCode)
      putExtra(EXTRA_DATA, result.data!!)
    }
    ContextCompat.startForegroundService(this, svc)
  }
}

fun requestScreenShare() {
  val mpm = getSystemService(MediaProjectionManager::class.java)
  projectionLauncher.launch(mpm.createScreenCaptureIntent())
}

Подключаем capturer к PeerConnection

Внутри сервиса передайте проекцию в ScreenCapturerAndroid, оберните её в VideoSource и добавьте получившийся трек в свой PeerConnection.

private fun startCapture(projection: MediaProjection) {
  val eglBase = EglBase.create()
  val factory = PeerConnectionFactory.builder()
    .setVideoEncoderFactory(
      DefaultVideoEncoderFactory(eglBase.eglBaseContext, true, true)
    )
    .setVideoDecoderFactory(
      DefaultVideoDecoderFactory(eglBase.eglBaseContext)
    )
    .createPeerConnectionFactory()

  val capturer = ScreenCapturerAndroid(
    projectionData(projection),
    object : MediaProjection.Callback() {
      override fun onStop() { stopSelf() }
    }
  )

  val sthelper = SurfaceTextureHelper.create("CaptureThread", eglBase.eglBaseContext)
  val source = factory.createVideoSource(true) // isScreencast = true
  capturer.initialize(sthelper, this, source.capturerObserver)
  capturer.startCapture(1280, 720, 15) // width, height, fps

  val track = factory.createVideoTrack("screen0", source)
  peerConnection.addTrack(track, listOf("stream0"))
}

Ключевой флаг: createVideoSource(true) — параметр isScreencast говорит WebRTC использовать профиль кодировщика, оптимизированный под экран (меньше keyframe-ов, адаптивный к контенту битрейт). Забыть этот флаг — самая частая причина того, что демонстрация экрана выглядит ужасно.

Битрейт, частота кадров, разрешение — работающий бюджет

Большинство команд выбирает цифры, которые красиво смотрятся на маркетинговой странице (1080p, 30 fps), а потом релиз дропает кадры на сотовой сети. Цифры ниже — из реального продакшен-трафика на выпущенных Android-приложениях Фора Софт.

Сценарий Разрешение FPS Битрейт Сеть
Слайды / статика 1280×720 5–10 500–800 kbps 3G+
Прохождение по приложению 1280×720 15 1,0–1,5 Mbps 4G/Wi-Fi
Воспроизведение видео 1280×720 24–30 2–3 Mbps Wi-Fi
Разбор кода 1920×1080 10–15 1,5–2,5 Mbps Wi-Fi
Высокое качество 1080p 1920×1080 30 3–5 Mbps Только Wi-Fi

Дефолт для продакшена: 1280×720, 15 fps, целевой битрейт 1,5 Mbps, максимум 2,5 Mbps. Это работает практически на всех 4G-соединениях, отлично выглядит для 95% экранного контента и не плавит CPU устройств среднего сегмента.

Максимальный битрейт ставьте явно через RtpSender.parameters.encodings[i].maxBitrateBps. Без этого congestion control в WebRTC задушит звук и менее приоритетные потоки в том же соединении.

Кодеки — что использовать в 2026 году

Выбор кодека на Android в WebRTC зависит от того, что поддерживает железо устройства и что умеет декодировать удалённый пир.

H.264. Универсальная аппаратная поддержка на Android. Лучший дефолт для демонстрации экрана в 2026 году, потому что любое устройство кодирует его в железе. Минус: сжимает хуже, чем VP9, на текстовом контенте.

VP8. Исторический дефолт WebRTC. Универсальная программная поддержка; аппаратная — как повезёт. На экранном контенте слегка лучше H.264 при том же битрейте.

VP9. Лучше сжимает экраны с большим количеством текста. Аппаратная поддержка на среднем Android неравномерна. Подходит как путь апгрейда с программным фолбэком.

AV1. Лучшее сжатие, но требует в 3–5 раз больше CPU, чем VP9. Аппаратные декодеры AV1 на Android в 2026 году редкость, большинство устройств декодирует программно — и это убивает батарею. AV1 SCC (Screen Content Coding) интересен для сверхнизкого битрейта при демонстрации экрана (100–500 kbps), но массовое внедрение — история 2027–2028 годов.

Практический дефолт: H.264 с фолбэком на VP8. Договаривайтесь через SDP munging; пусть удалённый браузер или приложение само выберет. AV1 для демонстрации экрана пропустите, пока аппаратные декодеры не станут массовыми, — кроме нишевых сценариев со сверхнизкой полосой.

Захват системного звука вместе с экраном

Android 10+ предоставляет AudioPlaybackCaptureConfiguration, который позволяет захватывать системный звук во время сессии media projection. Полезно, когда вы делитесь экраном с воспроизведением видео или звуковыми оповещениями приложений.

val config = AudioPlaybackCaptureConfiguration.Builder(projection)
  .addMatchingUsage(AudioAttributes.USAGE_MEDIA)
  .addMatchingUsage(AudioAttributes.USAGE_GAME)
  .build()

val audioRecord = AudioRecord.Builder()
  .setAudioPlaybackCaptureConfig(config)
  .setAudioFormat(...)
  .setBufferSizeInBytes(bufferSize)
  .build()

Подводные камни: приложения с флагом android:allowAudioPlaybackCapture="false" отключают захват (так обычно делают банки и DRM-приложения). Микрофонный вход — это отдельный AudioRecord; смешивайте оба потока на сервере или на клиенте в зависимости от сценария.

Изменения в Android 14 — частичный захват приложения и callbacks ресайза

Android 14 принёс два больших изменения, которые ломают наивные реализации:

1. Частичный захват приложения. ОС показывает выбор, в котором пользователь может расшарить одно приложение вместо всего экрана. От вашего кода тут не требуется ничего — проекция просто возвращает кадры выбранного приложения. Но UX-предпосылки ломаются: пользователь думает, что показывает слайды, а вы думаете, что он показывает домашний экран.

2. Новые callbacks. MediaProjection.Callback#onCapturedContentResize(width, height) срабатывает, когда захватываемое приложение меняет размер. onCapturedContentVisibilityChanged(isVisible) сообщает, когда захватываемый контент пропадает (пользователь свернул приложение).

projection.registerCallback(object : MediaProjection.Callback() {
  override fun onStop() { stopCapture() }
  override fun onCapturedContentResize(w: Int, h: Int) {
    capturer.changeCaptureFormat(w, h, 15)
  }
  override fun onCapturedContentVisibilityChanged(visible: Boolean) {
    if (!visible) showResumePrompt()
  }
}, handler)

Без них расшариваемое приложение в 1080×1920 может схлопнуться до 800×600, потому что пользователь перетащил его в split-screen, и удалённый зритель увидит растянутую размытую кашу.

Android 15 — остановка на экране блокировки и детектирование записи

Android 15 ещё сильнее затянул гайки приватности:

Автоматическая остановка при блокировке. Если пользователь заблокировал устройство, проекция останавливается автоматически. Чтобы продолжить, нужно заново подтверждение. Планируйте UX с учётом этого: при разблокировке предлагайте пользователю заново начать демонстрацию.

Маскирование уведомлений. Тело уведомлений скрывается во время проекции. Пользователи видят «Уведомление» вместо реального содержимого.

Callback детектирования записи. Приложения теперь могут определять, что их записывают, через MediaProjection.Callback#onRecordingStateChanged(). Чувствительные экраны (банкинг, ввод пароля, двухфакторные коды) должны это детектировать и отказываться рендериться.

Чип в статусбаре. Android 15 показывает постоянный чип в статусной строке во время проекции. По нему можно тапнуть, чтобы остановить демонстрацию. Приложение не может его скрыть.

Защита контента — FLAG_SECURE и DRM

Если вы делаете приложение, которое работает с чувствительными данными (банкинг, медицина, платный стриминг), вам нужно понимать, что значит FLAG_SECURE чужих приложений для вашего захвата экрана и что значит FLAG_SECURE у вас — для того, чтобы вас можно было захватить.

Захват защищённого контента. Окна приложений с FLAG_SECURE рендерятся чёрным в ваших захваченных кадрах. Аппаратный DRM (Widevine L1) обеспечивается на уровне чипсета, и никакие программные обходы не работают.

Защита собственного контента. Если ваше приложение показывает то, что другие не должны захватить (PIN, OTP, персональные данные), ставьте window.setFlags(FLAG_SECURE, FLAG_SECURE) на соответствующих Activity. На Android 15 дополнительно реализуйте callback состояния записи как защиту в глубину.

Сигналинг, ICE и TURN — связность, нужная для демонстрации экрана

WebRTC нужен канал сигналинга для обмена SDP offer/answer и ICE-кандидатами. Сам WebRTC сигналинг не предоставляет — его нужно приносить с собой (доминирующий выбор — WebSocket).

ICE-серверы. Настраивайте и STUN, и TURN. STUN отвечает за прямую связность между пирами при дружелюбных NAT. TURN обязателен на мобильных сетях, потому что большинство сотовых CGN-конфигураций блокируют прямой peer-to-peer. В реальных боевых развёртываниях используют 2–3 STUN- и 1–2 TURN-сервера по разным регионам.

Провайдеры TURN. Twilio Network Traversal Service, Xirsys, Cloudflare Calls TURN или self-hosted coturn. Закладывайте 0,3–0,7 ₽/мин ретранслируемого трафика на одного пользователя; на масштабе это легко перебивает расходы на сигналинг и SFU.

Стратегия переподключения. Мобильные сессии демонстрации экрана живут долго (часто 10–30 минут). WebSocket сигналинга обязательно где-то порвётся. Реализуйте экспоненциальный бэкофф для переподключения с heartbeat-ами и пересогласовывайте SDP, если новое соединение оказалось в другой IP-топологии.

Глубже про архитектуру — в наших гайдах по архитектуре WebRTC и боевым WebRTC-системам.

Ориентация, уход в фон и поворот экрана

Три рантайм-условия молча ломают демонстрацию экрана, если их не обработать.

Поворот. Поворот устройства генерирует configuration change. Capturer продолжит выдавать кадры в исходной ориентации, пока вы не вызовете capturer.changeCaptureFormat(width, height, fps) с новыми размерами. Подцепляйтесь к onConfigurationChanged на уровне сервиса или вешайте DisplayManager.DisplayListener.

Уход исходного приложения в фон. Пользователь может расшарить приложение, а потом переключиться. На Android 14+ это срабатывает как onCapturedContentVisibilityChanged(false); покажите подсказку, чтобы пользователь вернулся.

Doze и оптимизации батареи. Уведомление foreground service защищает вас от того, чтобы вас убили за неактивность, но Doze может троттлить сеть. Для долгих сессий запрашивайте исключение из оптимизаций батареи (REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) с понятным пояснением для пользователя — у Google Play есть жёсткие правила против злоупотреблений.

Матрица диагностики — симптомы и причины

Симптом Вероятная причина Решение
SecurityException при getMediaProjection Foreground service не запущен заранее (Android 14+) Вызывайте startForeground до getMediaProjection
Приходят чёрные кадры Захватываемое приложение использует FLAG_SECURE или DRM Починить нельзя — пояснить ограничение пользователям
Дёрганые кадры на сотовой сети Слишком высокий битрейт; congestion control душит поток Ограничьте битрейт 1,5–2 Mbps; рассмотрите VP8
Захват останавливается через 30 сек Нет foreground service; ОС убила проекцию Запускайте захват внутри foreground service
Растянутое или сплющенное изображение после поворота Не обработан поворот Вызывайте changeCaptureFormat при configuration change
Нет соединения на сотовой сети Нет TURN-сервера; CGN блокирует прямой peer Настройте TURN c udp + tcp + tls
Приложение падает на Android 15 после блокировки Захват прекращён, нет обработки возобновления Слушайте onStop и предлагайте пользователю заново начать демонстрацию

Стратегия тестирования — как проверить перед релизом

Демонстрацию экрана сложно покрывать юнит-тестами — она зависит от реальной графики, реальной сети и реальных пользователей, тапающих системный диалог. Наша пирамида тестов:

Юнит-тесты. Замокайте MediaProjection; тестируйте жизненный цикл — обработку intent-а, порядок запуска сервиса, подключение callback-ов. Это ловит баги «неправильного порядка».

Инструментальные тесты на Firebase Test Lab. Прогон на реальных устройствах с Android 11, 12, 13, 14, 15. Через UiAutomator подтверждайте, что диалог захвата экрана появляется и что ваш сервис стартует. Лабораторные прогоны нестабильные, но они отлично ловят регрессии по семействам устройств.

Ручная матрица. Тестируйте на Pixel 6+ (Android 14–15), Samsung Galaxy A-серии (Android 13–14), Xiaomi Redmi (Android 12–13). Эти три семейства ловят 90% проблем совместимости.

Шейпинг сети. Используйте adb shell tc или прокси вроде Charles Network Conditioner, чтобы симулировать 3G, рваный 4G и быстрые переключения сети. Большинство полевых багов воспроизводится именно здесь.

Продакшен-аналитика. Логируйте ключевые WebRTC-метрики (битрейт, потерянные пакеты, частоту кадров) в разрезе сессии в бэкенд. Без этого жалобы пользователей не получится отлаживать.

Как крупные приложения подходят к демонстрации экрана на Android

Zoom. Проприетарный стек кодеков, заточенный под реальное время, аппаратное кодирование, когда оно доступно, агрессивная адаптация битрейта под перегрузку. По умолчанию режет до 720p на сотовых сетях.

Google Meet. На базе WebRTC; на Android нативное приложение использует VP8 для экранного контента с фолбэком на H.264. Целится в 1,5 Mbps при 720p/15fps для демонстрации экрана.

Microsoft Teams. Кастомный видеопайплайн, оптимизированный под корпоративные сети, консервативные 1–1,5 Mbps при 720p/15fps. Сильный фолбэк до только-текста и только-звука, если видео не вытягивается.

Discord. На базе WebRTC; по умолчанию 30 fps для игр, с адаптивным понижением до 15 fps под нагрузкой. Для демонстрации экрана предпочитают VP8.

Slack Huddles. WebRTC; консервативные 500–1000 kbps при 720p; ставят доступность на слабых сетях выше визуального качества.

Все они перешли с чистого peer-to-peer на SFU-архитектуры. Про SFU и P2P подробнее — в нашем гайде по архитектуре WebRTC.

Кейсы — как мы делали это на реальных проектах Фора Софт

BrainCert — виртуальный класс на WebRTC, LMS. 100 000+ платящих клиентов, годовая выручка 225 млн ₽. Преподаватели показывают экраны своих Android-устройств, чтобы разобрать задачи. Наша реализация работает в 1280×720, 15 fps, целевой битрейт 1,2 Mbps, с фолбэком на TURN; стабильное качество даже на посредственном 4G в учебных рынках Индии и Юго-Восточной Азии.

Телемедицинские проекты. Врачи иногда показывают Android-экран, чтобы провести пациента по портальным сценариям. Мы по умолчанию ставим FLAG_SECURE на приложение врача, чтобы пациент не мог захватить экран обратно; события детектирования записи мы логируем для аудита соответствия требованиям.

Sprii — лайв-шопинг. Ведущие показывают крупные планы товаров; мы поднимаем fps до 24 для плавного движения при 720p. Синхронизация аудио и видео держится за счёт transport-wide CC в WebRTC.

Вывод Фора Софт

Демонстрация экрана на Android — это вопрос корректности жизненного цикла, а не выбора кодека. Поставьте правильный порядок запуска foreground service, обработайте новые callback-и Android 14, заложитесь под повторное согласие в Android 15 — и дальше остаётся только тюнинг. Наш подход Agent Engineering позволяет переиспользовать эту работу между проектами, поэтому оценки получаются на 30–40% меньше по срокам и бюджету, чем при разработке с нуля.

AV1 станет массовым к 2028 году. Аппаратные энкодеры появляются на топовых Snapdragon-ах; средний сегмент будет отставать. Планируйте VP8/H.264 как дефолт до 2027 года, AV1 — как опциональный вариант.

AI-аугментация захвата. Размытие фона, трекинг объектов, on-device автоматическая редактура чувствительных областей — всё это становится стандартом. WebRTC-приложения поколения 2027 будут гонять небольшую ML-модель на каждом захваченном кадре.

Усиление приватности в Android 16. Ждём более гранулярные intent-ы захвата (коммерческая запись против личной демонстрации), требования к аудит-логам и, возможно, отзыв разрешений при неактивности.

WebRTC-NV. Лучший congestion control (gcc-next), нативные подсказки для аппаратного AV1, расширения масштабируемости RTC. Android обычно отстаёт от десктопа на 2–3 года.

MoQ (Media over QUIC). Кандидат на долгосрочную замену части WebRTC. В 2026 году ещё не готов для продакшена, но за ним стоит следить под проекты 2028+.

Когда НЕ стоит делать демонстрацию экрана на Android WebRTC самим

Скажем честно: это одна из более сложных Android-фичей, чтобы выкатить её правильно. Три сценария, когда лучше купить готовое или взять партнёра, а не строить с нуля.

1. Вам нужно через 4 недели. Команда, новая в WebRTC, всегда недооценивает матрицу тестирования. Берите LiveKit Cloud, Daily или 100ms; выкатывайтесь за 2 недели; перепишете потом, если будет нужно.

2. У вас один продукт в одной стране. Фиксированные затраты на сборку этого внутри плохо конкурируют с оплатой 0,4–0,7 ₽ за минуту участника managed-SFU.

3. У вас нет Android-инженера, который понимает foreground services. Наймите или партнёрьтесь; не учитесь этому на своих пользователях.

Гайд по архитектуре WebRTC для бизнеса в 2026 году — SFU, MCU, mesh: как выбрать.

AI + WebRTC — как умные агенты меняют коммуникацию в реальном времени — следующий слой стека.

Услуги разработки WebRTC от Фора Софт — что мы делаем для клиентов.

Разбор стоимости WebRTC-разработки — как на самом деле выглядят бюджеты.

Сравнение альтернатив Agora.io — если вы выбираете managed-SFU.

Часто задаваемые вопросы

Можно ли захватывать экран без диалога запроса разрешения?

Нет. Диалог согласия MediaProjection обеспечивается ОС, и на серийных устройствах его нельзя подавить. Обойти могут только привилегированные системные приложения (предустановленные OEM-ом с разрешением CAPTURE_VIDEO_OUTPUT); потребительским приложениям это недоступно.

Почему мои захваченные кадры идут чёрными?

У захватываемого приложения или окна стоит FLAG_SECURE, или оно рендерит DRM-защищённый контент (Netflix, Disney+, банковские приложения). Это обеспечивается на уровне ОС и железа, обойти нельзя. Опишите это ограничение явно; не обещайте пользователям, что они смогут расшарить своё банковское приложение.

Нужен ли foreground service, если приложение и так на переднем плане?

Начиная с Android 14 — да: даже если ваше приложение сейчас видно, проекция должна работать внутри foreground service типа mediaProjection. Иначе ОС бросит SecurityException.

Какой FPS брать для демонстрации экрана?

15 fps — хороший дефолт для большинства сценариев. Берите 5–10 fps для статичных документов и слайдов, 24–30 fps для воспроизведения видео или анимации. Более высокий FPS ест больше полосы и CPU и редко улучшает восприятие статичного контента.

Можно ли расшарить экран без WebRTC?

Да — можно захватывать кадры через MediaProjection и отправлять их через RTSP, RTMP, HLS или HTTP. WebRTC предпочтителен для сценариев с низкой задержкой, peer-to-peer или SFU; RTMP — для one-to-many вещания, где задержка 3–6 секунд допустима.

Как захватывать звук вместе с экраном?

Используйте AudioPlaybackCaptureConfiguration (Android 10+) вместе с проекцией, чтобы захватить системный звук. Микшируйте его с микрофонным AudioRecord, если нужны оба источника. Приложения, отказавшиеся через allowAudioPlaybackCapture="false", захватить нельзя — это решение исходного приложения.

Какое максимальное разрешение можно захватить?

Ограничено только разрешением дисплея устройства. На практике для передачи стоит уменьшать до 1280×720 или 1920×1080: нативное разрешение (например, 3200×1440) расточительно, и удалённый зритель его всё равно уменьшит.

Поддерживается ли демонстрация экрана на Android 9 и ниже?

MediaProjection доступен с Android 5.0 (API 21). Однако требования к foreground service резко менялись на Android 8, 10, 13 и 14, поэтому единая кодовая база с поддержкой старых и новых версий уходит в сильное ветвление. В 2026 году поддерживать ниже Android 10 редко имеет смысл — более 95% активных Android-устройств работают на 11+.

Можно ли это сделать, не залезая в нативный код?

Да — LiveKit, Daily и 100ms предлагают высокоуровневые Android-SDK, которые прячут MediaProjection и WebRTC за простым API. Если тонкий контроль не нужен — это самый быстрый путь.

Архитектура

Архитектура WebRTC для бизнеса в 2026 году

SFU, MCU, mesh: что выбрать под ваш масштаб.

AI + RTC

AI-агенты на WebRTC — плейбук

Где медиа реального времени встречается с агентным AI: стоимость, задержка, выбор фреймворка.

Стоимость

Стоимость разработки WebRTC

Сколько команды реально платят за выпуск WebRTC-фичей в 2026 году.

Вендор

Сравнение альтернатив Agora.io

Если вы выбираете managed-SFU вместо того, чтобы строить своё.

Кейс

BrainCert — виртуальный класс на WebRTC

Демонстрация экрана в продакшене на проекте с годовой выручкой 225 млн ₽.

Кейс

VOLO.live — система перевода в реальном времени

22 000+ участников на Black Hat 2025.

Итог — как выкатить демонстрацию экрана через Android WebRTC в 2026 году

Возьмите поддерживаемый форк WebRTC (getstream/webrtc-android), объявите foreground service типа mediaProjection, запустите сервис до того, как запросите у пользователя согласие на проекцию, передайте проекцию в ScreenCapturerAndroid и добавьте получившийся трек в PeerConnection с isScreencast=true. По умолчанию 720p, 15 fps, 1,5 Mbps. Слушайте callback-и ресайза и видимости из Android 14+; планируйте остановку на экране блокировки в Android 15; проектируйте фолбэк на TURN для сотовых сетей. Тестируйте на Pixel, Samsung и Xiaomi.

Фора Софт уже реализовала этот паттерн в нескольких боевых Android-приложениях, включая BrainCert, VOLO.live и Sprii. Если вы стартуете с нуля или пытаетесь починить застрявший WebRTC-проект — следующий шаг — 30-минутный звонок для скоупа.

Делаете WebRTC на Android?

Получите фиксированную оценку за 48 часов.

Мы заскоупим фичу демонстрации экрана, порекомендуем подходящий WebRTC-стек и зафиксируем цену — с оценками, которые на 30–40% ниже агентских ставок благодаря нашему подходу Agent Engineering.

Позвоните нам → Напишите нам →

  • Технологии