Тест веб-камери в потоці — що бачить інша сторона
Зображення, яке ви бачите у превю веб-камери, — це локальний захоплювальний вигляд — кадр камери, як його доставлено через [getUserMedia()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) — а не сирий вихід сенсора. Зображення, яке бачить отримувач вашого відеодзвінка, — це браузерний закодований потік, який був мовчки узгоджений, стиснутий і, можливо, понижений WebRTC. Цей посібник пояснює, як працює узгодження кодеків WebRTC, як використовувати getStats() на RTCPeerConnection для вимірювання фактичних параметрів потоку і як виправити поширені причини втрати якості. Зауважте: інструмент веб-камери цього сайту перевіряє лише локальний захоплювальний трек і частоту кадрів браузера; він не вимірює вихідний WebRTC-кодований потік.
Ви сидите у відеодзвінку, і ваше власне вікно показує чітке, добре освітлене зображення 1080p. Ви виглядаєте різко, фон чистий, і кадрування правильне. Потім колега каже, що ваше відео постійно замерзає і виглядає розмитим, а коли він демонструє екран, ви бачите себе у вигляді блочного, з розмитими краями зображення, яке могла б виробити бюджетна веб-камера десятирічної давності. Та сама камера. Той самий світло. Той самий комп’ютер. Інше зображення.
Ось що пропускають більшість посібників з відеодзвінків: цей розрив зазвичай не апаратна несправність і не дефект сенсора — хоча збійний драйвер іноді здатен це викликати. Зазвичай це різниця між тим, що виробляє ваша камера, і тим, що насправді відправляє ваш браузер. Ваше превю береться з локального захоплювального шляху — кадру камери, як його доставлено через getUserMedia() — до кодування WebRTC, що робить його більш вигідним виглядом вашого відео, ніж те, що отримують інші учасники. Цей вигляд може все ж включати масштабування, кольорове перетворення або обробку обмежень, що застосовуються браузером, тому це не сирий вихід сенсора. Те, що отримують інші учасники, — це стиснутий потік, який був узгоджений, перекодований, обмежений за швидкістю і, можливо, понижений WebRTC за мілісекунди до того, як він покине ваш комп’ютер.
Цей шар кодування невидимий з інтерфейсу користувача і мовчазний при нормальній роботі. Ніщо у вікні дзвінка не каже, що він існує, ніщо не повідомляє його рішень, і ніщо в превю їх не відображає. Знайома сцена: користувач витрачає години на перевстановлення драйвера камери, тому що дзвінок показує розмите зображення — лише щоб виявити через chrome://webrtc-internals, що браузер узгоджував 480p15 на основі оцінки пропускної здатності, а не через камеру або драйвер. На цій сторінці пояснюється, що відбувається між сенсором камери та екраном вашого співрозмовника, чому браузер мовчки знижує вашу якість — і, що найважливіше, — як виміряти фактичний потік, що покидає ваш комп’ютер, замість того, щоб довіряти превю.

Що ваше превю вам не показує
Відеодзвінки спираються на конвеєр, що працює повністю поза вашою увагою. Кожен кадр, який ви відправляєте, проходить через такі етапи:
- Сенсор камери захоплює кадр; потім браузер доставляє його через getUserMedia() із запитаним розділенням і частотою кадрів, що може включати масштабування, кольорове перетворення та обробку обмежень.
- Браузер отримує цей кадр через API getUserMedia() і передає його рушію WebRTC. Ваше локальне превю береться з цього етапу — тому воно завжди виглядає ідеально, незалежно від того, що відбувається далі.
- Кодер WebRTC стискає кадр у бітовий потік з використанням узгодженого кодека, при узгодженому розділенні, частоті кадрів і бітрейті.
- Закодований кадр розбивається на RTP-пакети і відправляється мережею, зазвичай через медіа-сервер, що пересилає його всім іншим.
- Кожен приймач декодує пакети назад у зображення і відображає його на своєму екрані.
Ваше превю підключається до конвеєра на другому етапі. Воно показує кадр камери, як його доставлено через getUserMedia(), до кодування WebRTC. Браузер може застосувати масштабування, кольорове перетворення або обробку обмежень на цьому етапі, але ніякого стиснення WebRTC не застосовується. Потік, який бачить ваш співрозмовник, — це те, що виходить з третього етапу. Між цими двома точками кодер вирішує, що отримає світ, і він приймає це рішення на основі умов, які ви ніколи не бачите.
Кодер мовчки узгоджує три параметри, і кожен може змінитися під час дзвінка без будь-якого повідомлення:
- Розділення — ширина і висота закодованих кадрів, які можуть впасти з 1920x1080 до 1280x720 або 640x480 самостійно.
- Частота кадрів — скільки кадрів на секунду виживає кодування, яка зазвичай падає першою (з 30 до 15 або нижче), оскільки зменшення частоти кадрів вдвічі скорочує швидкість передачі даних вдвічі без зміни розділення — хоча деякі реалізації можуть замість цього знизити розділення залежно від кодека і платформи.
- Бітрейт — скільки бітів на секунду кодеру дозволено витрачати, що задає загальний рівень стиснення.
Ці три значення визначають все, що бачить інша сторона. Зображення 1080p, стиснуте до низького бітрейту, виглядає м’яким і змазаним. Потік 30 кадрів на секунду, що раптово працює на 10 кадрах, виглядає дерганим і неприродним. Коли ви розумієте, що превю не повідомляє жодного з цих значень, загадка жахливого дзвінка з відмінною камерою розв’язується.
SDP узгоджує раніше, ніж ви пошлете кадр
Узгодження починається до того, як відправлено перший кадр. Коли ви приєднуєтеся до дзвінка, платформа і ваш браузер обмінюються пропозицією і відповіддю Session Description Protocol (SDP). SDP рекламує кодеки та медіа-можливості, які підтримує кожна сторона; фактичне розділення і частота кадрів далі узгоджуються через параметри відправки і прийому та обмежуються оцінкою пропускної здатності. У неформальному тестуванні на Chrome 125 на Windows 10 (травень 2024) відповідь SDP спостерігалася такою, що пропонує VP9 першим, потім H.264, потім VP8; на Safari 17 на macOS 14 (той самий період) H.264 з’являвся першим. Ці спостереження були зроблені на одному комп’ютері для кожного браузера без контрольованих мережевих умов, тому вони ілюструють різноманітність, що існує, а не визначають універсальний порядок. Фактично обраний кодек залежить від браузера, платформи, параметрів SDP та апаратних можливостей. Поширені вибори включають VP9, H.264, VP8 та AV1, але єдиного фіксованого порядку переваг не існує.
Вибір кодека — лише початок. Щойно дзвінок живий, вступає в дію другий механізм: оцінка пропускної здатності. WebRTC безперервно моніторить мережевий шлях в обох напрямках і запускає алгоритм керування перешкодою — найчастіше Google Congestion Control — який робить три вимірювання на основі, що ковзає:
- Втрати пакетів, що повідомляються приймачем через зворотні зв’язки RTCP.
- Круговий час, затримка між відправкою пакету і отриманням підтвердження його прибуття.
- Пропускна здатність, ефективна швидкість, з якою дані фактично проходять через з’єднання.
Алгоритм подає ці вимірювання в модель, яка оцінює, скільки пропускної здатності мережа здатна прийняти зараз. ця оцінка стає цільовим бітрейтом, що передається кодеру, і кодер адаптує свій вихід. Петля безперервна і швидка: коли оцінка падає, кодер перекодовує при нижчому бітрейті за частку секунди.
Пороги приблизні і залежать від конкретного алгоритму керування перешкодою. Стійкі втрати пакетів вище приблизно п’яти відсотків можуть викликати зниження цільового бітрейту, але точна поведінка — наскільки падає швидкість, чи змінюється розділення або частота кадрів і при якому рівні втрат — варіюється від алгоритму до алгоритму, кодека і платформи. Універсального правила з відсотка втрат до конкретного розділення виходу не існує. Зворотний зв’язок, що керує цими рішеннями, визначена в (Google: WebRTC Congestion Control Whitepaper, 2019; RFC 8888: Congestion Control Feedback for RTP). Потік 1080p при 30 кадрах на секунду зазвичай потребує близько чотирьох-шести мегабіт на секунду пропускної здатності завантаження, щоб виглядати чисто, хоча це залежить від кодека, налаштувань кодування і складності сцени. Якщо оцінювач робить висновок, що доступен лише один мегабіт, він не намагається протолкнути потік — він знижує ціль, і кодер відповідає зниженням розділення до 480p і частоти кадрів до 15 кадрів на секунду. Якщо оцінка падає далі, зображення деградує знову, аж до speaking head 320x240. Кожен крок навмисний: мета — удержати дзвінок живим і аудіо стабільним, а якість відео — перше, що жертвують ради цього.

Три патерни відмови, які приховує потік
Превю приховує фактичний стан потоку за трьома повторюваними патернами відмови. Навчіться розпізнавати кожен за симптомами, тому що правильне виправлення різниться для кожного випадку. Всі три поділяють одну ознаку: превю залишається ідеальним весь час, тому що береться до кодера. Тільки закодований потік — і тому екрани інших учасників — показує шкоду.
Пастка бітрейту
Симптоми: Ваше превю ідеально і ваш процесор вільний. Інша сторона бачить розмите, низькороздільне зображення, яке ніколи не чітиться, навіть під час паузи. Локальні записи виглядають відмінно; дзвінок — погано.
Діагноз: Браузер оцінив, що мережа не здатна нести повний потік, і обмежив бітрейт, змушуючи кодер стиснути розділення. Обмежувач — ваша пропускна здатність завантаження або ємність ретрансляції медіа-сервера, а не ваша камера. Запустіть тест швидкості і порівняйте ваше завантаження з чотирма-шістьма мегабітами, які потребує 1080p30. Якщо ви поділяєте з’єднання з іншими пристроями, що стрімлять, завантажують або синхронізують, вони конкурують за той самий бюджет.
Поріг втрат
Симптоми: Статичні кадри з дзвінка виглядають добре, але будь-який рух дерганий і роботизований. Аудіо залишається плавним, поки відео підсмикується, і короткі замороження відбуваються кожні кілька секунд, після чого зображення відновлюється на нижчій частоті кадрів.
Діагноз: Втрати пакетів періодично перетинають п’ятивідсотковий поріг, тому контролер перешкоди неодноразово зрізає цільовий бітрейт, і кодер скидає кадри для вирівнювання. Частота кадрів падає першою, тому що це найдешевший важіль — зниження з 30 до 15 кадрів на секунду скорочує швидкість передачі вдвічі без зміни розділення. Перевірте Wi-Fi-перешкоди, граничний Ethernet-кабель або VPN, що додає втрати і затримки. Відео буде продовжувати деградувати, поки мережевий шлях не буде відремонтований.
Замороження ключового кадру
Симптоми: Перші дві-п’ять секунд після приєднання, або після демонстрації екрана, інша сторона бачить заморожене або сильно змазане зображення. Потім зображення вступає в фокус і поводиться нормально до наступної великої зміни сцени.
Діагноз: Видеокодеки відправляють два типи кадрів. Ключові кадри кодують ціле зображення і з’являються з фіксованим інтервалом — зазвичай кожні 1-10 секунд залежно від платформи і конфігурації. Дельта-кадри кодують лише зміни відносно попереднього кадру, що робить їх крихітними. Якщо пакет дельта-кадра втрачено, приймач не може відновити цей кадр — він може запросити повторну передачу (NACK), попросити відправника новий ключовий кадр (PLI або FIR) або приховати помилку в очікуванні. Коли запит успішний, відновлення швидке; коли ні — зображення залишається замороженим до приходу наступного запланованого ключового кадру. Це очікування — замороження, яке ви бачите. Короткі інтервали ключових кадрів відновлюються швидше, але коштують пропускної здатності; довгі інтервали ефективні, але роблять кожну втрату більш видимою. Це не збій — це кодек, що працює за задумом.

Вимірювання фактичного потоку через getStats()
Перестаньте вгадувати. Цифри не лестять, але вони правдиві. API WebRTC відкриває інтерфейс статистики, який повідомляє рівно те, що робить кодер, і будь-яка веб-сторінка, якою ви керуєте, може читати власне peer-з’єднання. Викличте getStats() на об’єкті RTCPeerConnection, потім відфільтруйте повернутий звіт для запису outbound-rtp з kind рівним video. На записах media-source і outbound-rtp ви знайдете значення, які мають значення:
- framesPerSecond на записі media-source — частота кадрів, яку камера доставляє кодеру. Якщо вона нижче 30 на камері 30 кадрів на секунду, сам захоплювальний шлях — проблема — часто причина в конкуренції за смугу USB; як її діагностувати, пояснює наш довідник про конкуренцію за смугу USB.
- framesPerSecond на записі outbound-rtp — частота кадрів, яку кодер фактично виробляє. Коли вона нижча за вхідну частоту, кодер скидає кадри.
- frameWidth і frameHeight на записі outbound-rtp — закодоване розділення. Порівняйте з налаштуваннями дзвінка; будь-яка різниця — мовчазне пониження.
- bytesSent на записі outbound-rtp — загальний закодований об’єм. Візьміть два вимірювання з інтервалом у секунду і обчисліть різницю, помножену на 8, щоб отримати фактичний бітрейт.
- packetsSent і packetsLost — зауважте: packetsLost на записі outbound-rtp не завжди заповнена; коефіцієнт втрат надійніше читати з запису remote-inbound-rtp, яка повідомляє перспективу приймача.
- currentRoundTripTime на записі candidate-pair — мережева затримка. Високий круговий час у поєднанні з втратами вказує на перешкоду.
Різні браузери можуть повідомляти трохи різні імена полів або опускати деяку статистику, тому переперевіряйте за сторінкою WebRTC-internals браузера, коли вона доступна.
Правила інтерпретації прості. Якщо outbound-rtp framesPerSecond помітно нижче media-source framesPerSecond, кодер скидає кадри під тиском. Якщо frameWidth і frameHeight нижче налаштованого розділення, бюджет з’єднання не зміг нести його. Якщо bytesSent перекладається в бітрейт, значно нижчий за вимогу кодека для цього розділення, зображення стискається — а превю, яке ніколи не бачить кодера, буде виглядати відмінно весь час.
Вам не потрібно писати код, щоб читати ці значення. Chrome і Edge постачаються з вбудованим переглядачем статистики на chrome://webrtc-internals, який фіксує кожне WebRTC-з’єднання в браузері, включаючи те, яке створила платформа дзвінків. Відкрийте його до приєднання до зустрічі, дозвольте йому записувати, потім перевірте записи outbound-rtp для відео-відправника. Ті самі цифри частоти кадрів, розділення, бітрейту та втрат там, а також графік таймлайну, що показує, коли саме кодер змінив вихід. Це найшвидший спосіб спіймати пониження якості в акті на реальному дзвінку платформи.
Виконайте це вимірювання, поки ваш дзвінок простоює у фоні, потім знову під час завантаженої зустрічі і порівняйте два набори цифр. Типове порівняння: у простої outbound-rtp framesPerSecond показує 30; під час завантаженої зустрічі він може впасти до 18, тоді як локальне превю все ще показує 30. Це порівняння виявляє, чи адекватна ваша базова мережа і чи конкуренція під час дзвінку є тим, що викликає пониження. Наш тест веб-камери показує розділення і частоту кадрів локального захоплювального треку, узгодженого через getUserMedia() — корисний базис для того, що здатна доставити камера в браузер, але не вимірювання вихідного WebRTC-кодованого потоку, для якого потрібне peer-з’єднання або сторінка WebRTC-internals браузера.
Zoom, Meet, Teams: три різні камери
Та сама камера, той самий ноутбук і та сама мережа можуть давати візуально різні результати в різних застосунках, тому що кожна платформа застосовує власну політику кодування поверх реалізації WebRTC браузера.
- Zoom зазвичай віддає пріоритет стабільності. Залежно від версії, типу акаунта та налаштувань зустрічі він може обмежити вихідне розділення і пожертвувати якістю відео, щоб зберегти стабільність аудіо та демонстрації екрана. Камера, здатна на 1080p, може транслювати 720p або нижче на Zoom.
- Google Meet зазвичай адаптується до виміряної пропускної здатності, рано знижуючи розділення і швидко відновлюючи його при покращенні умов. Його поведінка відстежує фактичний мережевий стан, на користь і на шкоду.
- Microsoft Teams застосовує власний ланцюг кодування та пост-обробки. Залежно від версії та налаштувань зустрічі зображення може стискатися додатково за межі сирого узгодження WebRTC.
- Нативний браузерний WebRTC, який ви отримуєте на голій веб-сторінці, відправляє узгоджений потік без політики платформи зверху. Це найближче до істини, на що здатне ваше обладнання і мережа в чистому WebRTC. Політики платформ різняться за версією, типом акаунта та конфігурацією зустрічі, тому сприймайте це як загальні тенденції, а не жорсткі правила.
Практичний наслідок: порівняння дзвінка в Zoom із дзвінком у Meet — це не тест камери. Це тест рішень кожної платформи про кодування. Спочатку виміряйте сирий потік простою сторінкою WebRTC або інструментом тест веб-камери. Якщо сирий потік чистий, а одна платформа все ще виглядає погано, політика платформи — обмежувач, і жодне оновлення обладнання не змінить її. Під час дзвінка платформи chrome://webrtc-internals дозволяє спостерігати рішення її кодера в реальному часі, так що ви бачите, чи пониження — політика платформи чи поведінка мережі — не довіряючи жодній зі сторін.
Сім кроків до чистого потоку
Ці кроки ізолюють окремі причини. Ви можете зупинитися, щойно потік виглядає правильно — але виміряйте до і після кожної зміни, щоб підтвердити, що виправлення фактично рушило цифри.
- Виміряйте першим. Відкрийте chrome://webrtc-internals або використовуйте getStats() на власному peer-з’єднанні і запишіть розділення, частоту кадрів та бітрейт. Якщо сирий потік уже понижено, ваша камера і з’єднання — проблема. Якщо він чистий, платформа — проблема.
- Перевірте пропускну здатність. Відеодзвінки потребують мінімум 1 Мбіт/с завантаження для 720p і приблизно 4 Мбіт/с для 1080p. Тестуйте з машини, з якої телефонуєте, а не з іншого пристрою, і переперевіряйте з іншим трафіком у мережі. Перейдіть на провідне з’єднання, якщо можете; втрати Wi-Fi — найпоширеніша причина невидимих понижень.
- Виправте освітлення. Добре освітлений суб’єкт стискається значно краще, ніж темний, тому що кодер витрачає бітрейт на видиму деталь, а не на шум. Обличчям до вікна або використовуйте м’яке джерело світла. Це нічого не коштує і часто дає більше покращення, ніж будь-яке налаштування.
- Відключіть відеошумоподавлення, коли ваше середовище вже тихе і добре освітлене. Деякі платформи застосовують агресивний денойзинг у умовах низького освітлення, що може помітно згладжувати дрібні деталі в закодованому потоці. Локальне превю не покаже цю різницю; лише закодований потік покаже. Перевірте налаштування конкретної платформи, щоб уточнити, які елементи керування доступні.
- Відключіть віртуальний фон. Сегментація фону додає накладні витрати до фактичного бітрейту і споживає цикли GPU від кодера. Чистий реальний фон з постійним освітленням перевершує будь-який віртуальний.
- Перевірте кодек. Якщо ваш процесор справляється, VP9 delivering найкращу якість на біт; якщо ви бачите пропуски кадрів або сплески процесора, H.264 кодує швидше. Деякі платформи надають перевагу кодеку в налаштуваннях.
- Протестуйте іншу платформу. Якщо якість добра на одній службі і погана на іншій, політика кодування платформи — обмежувач. Скоригуйте ваші очікування або ваш інструмент для зустрічей відповідно — ваше обладнання не винне.
Підсумок
Превю — це локальний самовигляд вашої камери: вигідний вигляд того, що ваша камера здатна доставити в браузер. Потік — це те, що світ насправді бачить — узгоджений, стиснутий і сформований мережевими умовами та політикою платформи. Це два різних відео одного суб’єкта, і лише одне з них має значення для того, як вас сприймають. Якщо ви коли-небудь дивувалися, чому ваша камера виглядає відмінно на вашому екрані, але жахливо у дзвінку, тепер у вас є відповідь і інструмент для вимірювання.
Відкрийте chrome://webrtc-internals. Приєднайтеся до наступного дзвінка. Спостерігайте записи outbound-rtp. Якщо frameWidth або framesPerSecond нижче за те, що ви встановили в налаштуваннях камери, пониження відбувається. Причина зазвичай пов’язана з пропускною здатністю — що вашому браузеру дозволено витрачати, і чи здатне ваше з’єднання фактично нести потік, який, як ви думаєте, ви відправляєте — але навантаження на процесор, вибір кодера, політики платформи та конфігурація обмежень також можуть сприяти або домінувати в деградації.