Нагружать WebRTC-систему HTTP-инструментами — это фикция: вы долбите сигнальный endpoint, пока самое дорогое — DTLS-криптография, RTP-форвардинг, джиттер-буферы на SFU — простаивает. Perfscale теперь гоняет полный медиа-путь: каждый виртуальный пользователь выполняет настоящие ICE/DTLS-SRTP рукопожатия и шлёт или принимает настоящий RTP — против вашего сервера или против другого VU.
WebRTC — премиальная возможность, доступная на планах Scale и Enterprise. Тесты с действиями pro/webrtc-* отклоняются при создании на Starter. Фича поставляется в агенте 0.4.0 и работает одинаково в perfscale CLI, агенте perfscaled и под управлением controlplane.
Три сценария, комбинируемые в одном тесте
- WHIP/WHEP — стандартизированные endpoint'ы публикации/просмотра. Публикуйте синтетическое или файловое AV в WHIP-endpoint, смотрите WHEP-поток и измеряйте его.
- Кастомный сигналинг — LiveKit, mediasoup, Janus, любой проприетарный протокол: wasm-библиотека получает SDP-оффер и возвращает ответ, так что вендорские особенности живут в версионируемых библиотеках, а не в движке.
- P2P-звонки между парами VU — один композитный шаг выполняет весь звонок: пейринг → коннект → медиа в обе стороны → hold → статистика → закрытие. Сигнальный сервер не нужен.
Публикация в WHIP-endpoint
# test.yaml
steps:
- name: publish camera
use: pro/webrtc-connect@v1
with:
signal: whip
url: https://stream.example.com/whip/cam-${vu}
bearer: ${WHIP_TOKEN}
outputs: cam
- name: send media
use: pro/webrtc-publish@v1
with:
id: ${cam.id}
tracks:
- kind: video
codec: av1
source: synthetic
bitrate: 1500kbps
resolution: 1280x720
- kind: audio
codec: opus
source: synthetic
bitrate: 64kbps
Синтетическое аудио — это тон Opus с дизерингом амплитуды (чтобы энкодер не сворачивался в DTX); синтетическое видео — движущийся тест-паттерн с вшитой меткой времени. Движок — чистый Rust, поэтому поведение resolution: зависит от кодека: AV1 кодируется по-настоящему через rav1e в запрошенном разрешении и битрейте — примерно одно ядро CPU на кодируемый трек, честная цена настоящего кодирования. VP8 и H.264 проигрывают встроенный ассет 320x240 (несовпадающий resolution: пишет предупреждение, а не врёт). source: file зацикливает ваши файлы: IVF (VP8/AV1), Annex-B H.264, Opus-in-Ogg.
Мультитрек и симулькаст
Реальные клиенты шлют больше одной камеры. Объявите раскладку на коннекте (в WHIP нет пересогласования), затем прикрепите треки на publish:
- name: publish connect
use: pro/webrtc-connect@v1
with:
signal: whip
url: https://stream.example.com/whip/studio-${vu}
tracks: # по умолчанию 1 аудио + 1 видео
- { kind: audio }
- { kind: video } # камера
- kind: video # демонстрация экрана, симулькаст
layers: [ { rid: f }, { rid: h }, { rid: q } ]
outputs: studio
Слои симулькаста получают строки a=rid / a=simulcast в оффере, per-layer SSRC в проводе и per-layer метрики отправки (webrtc_video1_f_bitrate_bps). Одно честное ограничение: настоящий AV1 SVC (пространственные слои внутри одного потока) отклоняется с точечной ошибкой — у rav1e нет API пространственных слоёв, и мы это не подделываем.
P2P-звонки между вашими VU
Композитный шаг сводит пары VU через эфемерные shared-переменные — с driver: redis тот же тест охватывает несколько инстансов агента:
steps:
- name: p2p call
use: pro/webrtc-call@v1
with:
pairing:
driver: redis
key: webrtc-room-1
strategy: adjacent # vu 2k-1 звонит vu 2k
media: bidirectional
hold: 30s
Каждая ошибка несёт тег стадии — ice, dtls, signaling, publish, subscribe, hold — со счётчиками webrtc_call_errors_<stage>, так что регрессия сама указывает на фазу вместо общего «звонок упал».
Когда сеть сопротивляется
Соединения могут переживать ICE-disconnect вместо смерти: on_disconnect: restart выполняет настоящий ICE-рестарт — свежие креды пересигнализируются через WHIP PATCH (application/trickle-ice-sdpfrag) или через вашу библиотеку — до 3 попыток, с учётом в webrtc_ice_restarts_total. На приёме jitter_buffer_ms применяет настоящую задержку проигрывания по расписанию RTP-таймстампов — поглощение джиттера стоит TTFF того же размера, ровно как в проде. А sink: record сохраняет каждый принятый трек по каждому VU (.ogg / .ivf / .h264), чтобы можно было глазами увидеть, что сеть сделала с медиа.
Что измеряется
Сетап попадает рядом с вашими HTTP-перцентилями — webrtc_ice_duration_ms, webrtc_dtls_duration_ms, webrtc_setup_ms, webrtc_ttff_ms — плюс фоновый сэмплер getStats для качества медиа: RTT, джиттер, потери пакетов, битрейт по типам треков и per-track/per-layer серии для мультитрека. Гейтьте CI как обычно:
webrtc_setup_ms_failed: ["rate<0.05"]
webrtc_call_errors_ice: ["count==0"]
Где читать дальше
Полный справочник — все параметры, таблица кодеков и контейнеров, модель ошибок — в документации:
→ Документация WebRTC → Гайд по WebRTC в CLI
Если вы на Scale или Enterprise — направьте это на свой SFU и запускайте. Если ещё нет — это повод для апгрейда.
