Webcam Real Stream Test — Wat je Preview Je Niet Laat Zien
De webcam-preview in je browser toont wat je camera opneemt, maar niet wat je gesprekspartner daadwerkelijk ontvangt. Tussen de camera en de ander zit een coderingslaag die resolutie, framerate en bitrate aanpast op basis van netwerkcondities en platformbeleid. Een camera die er perfect uitziet in de lokale weergave, kan er slecht uitzien tijdens het gesprek omdat de browser de stream stil naar beneden heeft bijgesteld. Deze gids legt uit wat er gebeurt tussen sensoren en scherm van de ander, waarom de browser je kwaliteit verlaagt, en — het belangrijkste — hoe je de werkelijke stream die je machine verlaat, meet in plaats van de preview te vertrouwen.
Je zit in een videogesprek en je eigen venster toont een scherp, goed verlicht beeld van 1080p. Je ziet er strak uit, de achtergrond is schoon, en de cadrering is juist. Dan zegt een collega dat je video blijft bevriezen en wazig ziet, en wanneer zij hun scherm deelt zie je jezelf als een blokkerig, zachtomlijnd beeld dat een budget-webcam van een decennium geleden zou hebben geproduceerd. Dezelfde camera. Dezelfde verlichting. Dezelfde machine. Een ander beeld.
Dit is wat de meeste videogesprek-guides over slaan: die kloof is meestal geen hardwarefout of sensordesect — hoewel een slecht functionerend stuurprogramma het soms ook kan veroorzaken. Het is typisch het verschil tussen wat je camera produceert en wat je browser werkelijk verzendt. Je preview wordt gevoed vanuit het lokale opnamepad — het frame dat de camera produceerde zoals geleverd via getUserMedia() — vóór WebRTC-codering, wat een gunstiger beeld is van je video dan wat de andere deelnemers ontvangen. Dat beeld kan nog steeds schaling, kleurconversie of constraint-verwerking bevatten die door de browser is toegepast, dus het is geen rauwe sensoroutput. Wat de andere deelnemers ontvangen, is een gecomprimeerde stream die is onderhandeld, hercodeerd, rate-beperkt en mogelijk gedegradeerd door WebRTC in de milliseconden voordat hij je machine verlaat.
Die coderingslaag is onzichtbaar vanuit de gebruikersinterface en zwijgt tijdens normale werking. Niets in het gesprekvenster vertelt je dat het bestaat, niets rapporteert zijn beslissingen, en niets in je preview weerspiegelt ze. Een bekend tafereel: een gebruiker besteedt uren aan het opnieuw installeren van de camerastuurprogramma omdat een gesprek een wazig beeld toont — alleen om via chrome://webrtc-internals te ontdekken dat de browser onderhandelde naar 480p15 op basis van bandwidth estimation, niet vanwege de camera of het stuurprogramma. Deze pagina legt uit wat er gebeurt tussen de camarasensoren en het scherm van je gesprekspartner, waarom de browser je kwaliteit verlaagt, en — het belangrijkste — hoe je de werkelijke stream die je machine verlaat, meet in plaats van de preview te vertrouwen.

Wat je preview je niet toont
Videogesprekken rusten op een pijplijn die volledig buiten je bewustzijn draait. Elk frame dat je zendt, gaat door de volgende fasen:
- De camarasensor vangt een frame op; de browser levert het vervolgens via getUserMedia() op de gevraagde resolutie en framerate, wat schaling, kleurconversie en constraint-verwerking kan omvatten.
- De browser ontvangt dat frame via de
getUserMedia()-API en geeft het aan de WebRTC-engine. Je lokale preview wordt gevoed vanuit deze fase — wat de reden is dat het er altijd perfect uitziet, ongeacht wat er hierna gebeurt. - De WebRTC-coderer comprimeert het frame naar een bitstroom met een onderhandelde codec, op een onderhandelde resolutie, framerate en bitrate.
- Het gecodeerde frame wordt opgesplitst in RTP-pakketten en verstuurd over het netwerk, meestal via een mediadienaar die het naar iedereen anders doorgeeft.
- Elke ontvanger decodeert de pakketten terug naar een beeld en render het op hun scherm.
Je preview tapt in de pijplijn bij fase twee. Het toont het frame dat de camera produceerde zoals geleverd via getUserMedia(), vóór WebRTC-codering. De browser kan schaling, kleurconversie of constraint-verwerking toepassen op deze fase, maar geen WebRTC-compressie wordt toegepast. De stream die je gesprekspartner ziet, is wat uit fase drie komt. Tussen die twee punten beslist de coderer wat de wereld ontvangt, en hij neemt die beslissing op basis van omstandigheden die je nooit ziet.
De coderer onderhandelt stilzwijgend over drie parameters, en elk kan zich midden in het gesprek veranderen zonder enige melding:
- Resolutie — de breedte en hoogte van de gecodeerde frames, die zichzelf kan verlagen van 1920 bij 1080 naar 1280 bij 720 of 640 bij 480.
- Framerate — hoeveel frames per seconde de codering overleeft, die doorgaans eerst daalt (van 30 naar 15 of lager) omdat halveren van de framerate de databitrate halveert zonder resolutie te veranderen — hoewel sommige implementaties in plaats daarvan resolutie verminderen, afhankelijk van codec en platform.
- Bitrate — hoeveel bits per seconde de coderer mag besteden, wat het algemene compressieniveau bepaalt.
Deze drie waarden bepalen alles wat de andere kant ziet. Een beeld van 1080p gecomprimeerd naar een lage bitrate ziet er zacht en smerig uit. Een stream van 30 fps die plotseling op 10 fps loopt, ziet er trillig en onnatuurlijk uit. Wanneer je begrijpt dat de preview geen van deze waarden rapporteert, lost het mysterie van het vreselijke gesprek met een geweldige camera zich op.
SDP onderhandelt voordat je een frame zendt
De onderhandeling begint vóór het eerste frame wordt verzonden. Wanneer je een gesprek begint, wisselen het platform en je browser een Session Description Protocol (SDP)-aanbod en antwoord. De SDP adverteert de codecs en mediakapaciteiten die elke kant ondersteunt; werkelijke resolutie en framerate worden vervolgens verder onderhandeld via zend- en ontvangstparameters en beperkt door bandwidth estimation. Bij informele tests op Chrome 125 op Windows 10 (mei 2024) was waargenomen dat het SDP-antwoord VP9 eerst aanbood, dan H.264, dan VP8; op Safari 17 op macOS 14 (zelfde periode) verscheen H.264 eerst. Deze waarnemingen werden gemaakt op één machine per browser zonder gecontroleerde netwerkcondities, zodat ze de variatie illustreren die bestaat in plaats van een universele volgorde te definiëren. De daadwerkelijk geselecteerde codec hangt af van browser, platform, SDP-parameters en hardwarecapaciteiten. Veelvoorkomende keuzes omvatten VP9, H.264, VP8 en AV1, maar er is geen enkele vaste voorkeursvolgorde over alle platforms.
Codecselectie is slechts het begin. Zodra het gesprek live is, neemt een tweede mechanisme over: bandwidth estimation. WebRTC monitort continu het netwerkpady in beide richtingen en voert een congestiecontrolealgoritme uit — het meest vaak Google Congestion Control — dat drie metingen op een rollende basis doet:
- Pakketverlies, gerapporteerd door de ontvanger via RTCP-feedbackberichten.
- Weercastetijd, de vertraging tussen het verzenden van een pakket en het ontvangen van een bevestiging van de aankomst.
- Doorvoer, de effectieve snelheid waarmee data werkelijk de verbinding oversteekt.
Het algoritme voedt deze metingen naar een model dat schat hoeveel bandbreedte het netwerk momenteel kan dragen. Die schatting wordt een doelbitrate die aan de coderer wordt doorgegeven, en de coderer past zijn output aan om te passen. De lus is continu en snel: wanneer de schatting daalt, hercodeert de coderer op een lagere bitrate binnen een fractie van een seconde.
De drempels zijn benaderend en hangen af van het specifieke congestiecontrolealgoritme dat in gebruik is. Aanhoudend pakketverlies boven ongeveer vijf procent kan een reductie van de doelbitrate uitlokken, maar het exacte gedrag — hoeveel de snelheid daalt, of resolutie of framerate ook veranderen, en bij welk verliespercentage — varieert per algoritme, codec en platform. Er is geen universele mapping van een verliespercentage naar een specifieke outputresolutie. De feedbacklus die deze beslissingen aanstuurt, is gedefinieerd in (Google: WebRTC Congestion Control Whitepaper, 2019; RFC 8888: Congestion Control Feedback for RTP). Een stream van 1080p bij 30 fps heeft typisch ongeveer vier tot zes megabit per seconde uploadbandbreedte nodig om schone te lijken, hoewel dit afhangt van codec, coderingsinstellingen en scenecomplexiteit. Als de estimator besluit dat slechts één megabit beschikbaar is, probeert hij de stream niet door te forceeren — hij verlaagt de doel, en de coderer reageert door resolutie te verlagen naar 480p en framerate naar 15 fps. Als de schatting verder daalt, degradeert het beeld opnieuw, helemaal tot een praatkop van 320 bij 240. Elke stap is doelbewust: het doel is om het gesprek levend te houden en de audio stabiel, en videokwaliteit is het eerste dat aan dat doel wordt offers.

Drie faalpatronen die je stream verborgen houdt
De preview verborgt de werkelijke staat van de stream achter drie terugkerende faalpatronen. Leer elk te herkennen aan zijn symptomen, want de juiste fix verschilt voor elk geval. Alle drie delen één aanwijzing: de preview blijft de hele tijd perfect, omdat het vóór de coderer wordt bemonsterd. Alleen de gecodeerde stream — en daarom de schermen van de andere deelnemers — toont de schade.
De bitrate-valkuil
Symptomen: Je preview is perfect en je machine heeft idle CPU. De andere kant ziet een wazig, lage-resolutiebeeld dat nooit scherper wordt, zelfs niet tijdens een pauze. Lokale opnames zien er uitstekend uit; het gesprek ziet er slecht uit.
Diagnose: De browser heeft geschat dat het netwerk de volledige stream niet kan dragen en de bitrate heeft begrensd, waardoor de coderer de resolutie moet inkrimpen. De beperking is je uploadbandbreedte of de relay-capaciteit van de mediadienaar, niet je camera. Voer een snelheidstest uit en vergelijk je gemeten upload met de vier tot zes megabit die 1080p30 vereist. Als je een verbinding deelt met andere apparaten die streamen, downloaden of synchroniseren, concurreren ze voor hetzelfde budget.
De verliesdrempel
Symptomen: Stille beelden van het gesprek zien er prima uit, maar elke beweging is trillig en robotachtig. Audio blijft soepel terwijl video hapering vertoont, en korte bevriezingen treden elke paar seconden op voordat het beeld op een lagere framerate hervat.
Diagnose: Pakketverlies overschrijdt af en toe de vijf procent drempel, zodat de congestiecontroller steeds de doelbitrate verlaagt en de coderer frames valt om te matchen. Framerate daalt eerst omdat het de goedkoopste hefbom is — verminderen van 30 naar 15 fps halveert de databitrate zonder resolutie te veranderen. Controleer op Wi-Fi-interferentie, een marginale Ethernetkabel, of een VPN die verlies en vertraging toevoegt. De video zal blijven degraderen tot het netwerkpady is hersteld.
De keyframe-bevriezing
Symptomen: De eerste twee tot vijf seconden nadat je joinde, of nadat je je scherm deelt, ziet de andere kant een bevroren of zwaar smerig beeld. Dan valt het beeld in focus en gedraagt zich normaal tot de volgende grote scênewisseling.
Diagnose: Videocodecs zenden twee frametypes. Keyframes coderen het volledige beeld en verschijnen op een vaste interval — doorgaans elke één tot tien seconden afhankelijk van het platform en de configuratie. Deltaframes coderen alleen de veranderingen sinds het vorige frame, wat ze kleintjes maakt. Als een pakket van een deltframe verloren gaat, kan de ontvanger dat frame niet reconstrueren — het kan een heruitzending aanvragen (NACK), de afzender vragen om een frisse keyframe (PLI of FIR), of de fout verbergen tijdens het wachten. Wanneer een verzoek slaagt, is herstel snel; wanneer het faalt, blijft het beeld bevroren tot de volgende geplande keyframe aankomt. Dat wachten is de bevriezing die je ziet. Korte keyframe-intervallen herstellen sneller maar kosten bandbreedte; lange intervallen zijn efficiënt maar maken elk verlies zichtbaarder. Dit is geen malfunction — het is de codec die werkt zoals ontworpen.

De werkelijke stream meten met getStats()
Houd op met raden. De cijfers zijn niet flatterend, maar ze zijn waar. De WebRTC-API exposeert een statistieken-interface die precies rapporteert wat de coderer doet, en elke webpagina die je beheert, kan zijn eigen peer connection lezen. Roep getStats() aan op het RTCPeerConnection-object, en filter het teruggegeven rapport voor de outbound-rtp-entry waarvan kind video is. Op de media-source- en outbound-rtp-entries vind je de waarden die tellen:
- framesPerSecond (op de media-source-entry) — de framerate die de camera aan de coderer levert. Als deze onder de 30 staat op een 30 fps-camera, is het opnamepad zelf het probleem — vaak een kwestie van USB-bandbreedteconcurrentie; onze gids over USB-bandbreedteconcurrentie legt uit hoe je dat vaststelt.
- framesPerSecond (op de outbound-rtp-entry) — de framerate die de coderer werkelijk produceert. Wanneer deze lager is dan de ingangsrate, valt de coderer frames.
- frameWidth en frameHeight (op de outbound-rtp-entry) — de gecodeerde resolutie. Vergelijk met je gesprekinstellingen; elk verschil is een stille downgrade.
- bytesSent (op de outbound-rtp-entry) — totale gecodeerde data. Bemonster twee keer met een seconde tussentijds en bereken het verschil maal 8 om de werkelijke bitrate te krijgen.
- packetsSent en packetsLost — noteer dat packetsLost op de outbound-rtp-entry niet altijd wordt ingevuld; de verliesratio is betrouwbaarder te lezen vanaf de remote-inbound-rtp-entry, die het ontvangerperspectief rapporteert.
- currentRoundTripTime (op de candidate-pair-entry) — de netwerkvertraging. Een hoge RTT gecombineerd met verlies wijst op congestie.
Verschillende browsers kunnen lichtjes andere veldnamen rapporteren of sommige statistieken volledig weglaten, dus cross-check tegen de WebRTC-internalspagina van de browser wanneer beschikbaar.
De interpretateregels zijn simpel. Als de outbound-rtp framesPerSecond duidelijk lager is dan de media-source framesPerSecond, valt de coderer frames onder druk. Als frameWidth en frameHeight lager zijn dan de resolutie die je configureerde, kon het verbindingbudget het niet dragen. Als bytesSent vertaalt naar een bitrate ver beneden de codecvereiste voor die resolutie, wordt het beeld gecrushd — en de preview, die de coderer nooit ziet, zal de hele tijd er prima uitzien.
Je hoeft geen code te schrijven om deze waarden te lezen. Chrome en Edge leveren een ingebouwde statistiekenviewer bij chrome://webrtc-internals die elke WebRTC-verbinding in de browser vangt, inclusief de ene die een gesprekplatform creëerde. Open het vóór dat je een vergadering begint, laat het opnemen, en inspecteer de outbound-rtp-entries voor de videozender nadien. Dezelfde framerate-, resolutie-, bitrate- en verliescijfers zijn daar, samen met een tijdlijngrafiek die precies toont wanneer de coderer zijn output veranderde. Dit is de snelste manier om een downgrade in actie te vangen tijdens een echt platformgesprek.
Voer deze meting uit terwijl je eigen gesprek in de achtergrond draait, en dan weer tijdens een drukke vergadering, en vergelijk de twee sets cijfers. Een typische vergelijking: inactief, outbound-rtp framesPerSecond leest 30; tijdens een drukke vergadering kan het dalen naar 18 terwijl de lokale preview nog steeds 30 toont. Die vergelijking onthult of je basaal netwerk toereikend is en of concurrenie tijdens het gesprek is wat de downgrade aanmaakt. Onze webcamtest toont de resolutie en framerate van het lokale opnametrack zoals onderhandeld via getUserMedia() — een handig basispunt voor wat je camera aan de browser kan leveren, maar geen meting van de uitgaande WebRTC-gecodeerde stream, die een peer connection of de WebRTC-internalspagina van de browser vereist.
Zoom, Meet, Teams: drie verschillende camera’s
Dezelfde camera, dezelfde laptop en hetzelfde netwerk kunnen zichtbaar verschillende resultaten produceren in verschillende applicaties, omdat elk platform zijn eigen coderingsbeleid toepast bovenop de WebRTC-implementatie van de browser.
- Zoom geeft doorgaans prioriteit aan stabiliteit. Afhankelijk van versie, accounttype en vergaderinstellingen kan het de uitgaande resolutie cap en videokwaliteit offers om audio en schermsharing stabiel te houden. Een camera met 1080p-capaciteit kan 720p of lager zenden op Zoom.
- Google Meet neigt naar aanpassing aan gemeten bandbreedte, verlaagt resolutie vroeg en herstelt het snel wanneer condities verbeteren. Zijn gedrag volgt je werkelijke netwerkstaat, voor het betere en het slechtere.
- Microsoft Teams past zijn eigen coderings- en postprocessingpijp toe. Afhankelijk van versie en vergaderinstellingen kan het beeld verder worden gecomprimeerd ver voorbij de ruwe WebRTC-onderhandeling.
- Browser-native WebRTC, het soort dat je krijgt op een kale webpagina, zendt de onderhandelde stream zonder platformbeleid erbovenop. Het is het dichtst bij de grondwaarheid van wat je hardware en netwerk kunnen leveren onder plain WebRTC. Platformbeleid varieert per versie, accounttype en vergaderconfiguratie, dus behandel deze als algemene tendensen in plaats van vaste regels.
Het praktische gevolg: een Zoom-gesprek vergelijken met een Meet-gesprek is geen cameratest. Het is een test van het coderingsbeleid van elk platform. Meet de ruwe stream eerst met een plain WebRTC-pagina of de webcamtest-tool. Als de ruwe stream schoon is en één platform er nog steeds slecht uitziet, is het platformbeleid de beperking, en geen enkele hardware-upgrade zal het veranderen. Wanneer een platformgesprek gaande is, laat chrome://webrtc-internals je zijn codererbeslissingen live bekijken, zodat je kunt zien of de downgrade het platformbeleid is of het netwerkgedrag, zonder de zelfrapportage van beide kanten te vertrouwen.
Zeven stappen naar een schone stream
Deze stappen isoleren onderscheidende oorzaken. Je kunt stoppen zodra de stream er correct uitziet — maar meet voor en na elke verandering om te bevestigen dat de fix werkelijk de cijfers heeft verplaatst.
- Meet eerst. Open chrome://webrtc-internals of gebruik getStats() op je eigen peer connection en noteer resolutie, framerate en bitrate. Als de ruwe stream al gedegradeerd is, zijn je camera en verbinding het probleem. Als het schoon is, is het platform het.
- Controleer bandbreedte. Videogesprekken hebben minimaal 1 Mbps upload voor 720p en ongeveer 4 Mbps voor 1080p. Test vanaf de machine waarvandaan je belt, niet van een ander apparaat, en herhaal de test met ander verkeer op het netwerk. Schakel over naar een bekabelde verbinding als je kunt; Wi-Fi-verlies is de meest voorkomende oorzaak van onzichtbare downgrades.
- Fixeer verlichting. Een goed verlicht onderwerp comprimeert aanzienlijk beter dan een donker, omdat de coderer bitrate besteedt aan zichtbaar detail in plaats van aan ruis. Draai je gezicht naar een raam of gebruik een zacht lichtbron. Dit kost niets en produceert vaak een grotere verbetering dan elke instelling.
- Schakel videoruisconfiguratie uit wanneer je omgeving al stil en goed verlicht is. Sommige platforms passen agressieve denoising toe in weinig verlichte scènes, wat fijne details merkbaar kan verzachten in de gecodeerde stream. De lokale preview zal dit verschil niet tonen; alleen de gecodeerde stream dat. Controleer de specifieke platforminstellingen om te bevestigen welke bedieningen beschikbaar zijn.
- Schakel virtuele achtergrond uit. Achtergrondsegmentatie voegt overhead toe aan de effectieve bitrate en verbruikt GPU-cycli van de coderer. Een schone echteachtergrond met consistente verlichting overtreft elke virtuele.
- Controleer de codec. Als je CPU het aan kan, levert VP9 de beste kwaliteit per bit; als je frame-drops of CPU-spikes ziet, codeert H.264 sneller. Sommige platforms bieden een codecvoorkeur in de instellingen.
- Test een ander platform. Als de kwaliteit goed is op één service en slecht op een andere, is het platformbeleid de beperking. Pas je verwachtingen of je vergadertool dienovereenkomstig aan — je hardware is niet de schuldige.
Het eindoordeel
De preview is de lokale zelfbeeld van je camera: een gunstig beeld van wat je camera aan de browser kan leveren. De stream is wat de wereld werkelijk ziet — onderhandeld, gecomprimeerd en gevormd door netwerkcondities en platformbeleid. Het zijn twee verschillende video’s van hetzelfde onderwerp, en alleen één van hen telt voor hoe jij overkomt. Als je je ooit af hebt gevraagd waarom je camera er geweldig uitziet op je scherm maar vreselijk in het gesprek, heb je nu het antwoord en het hulpmiddel om het te meten.
Open chrome://webrtc-internals. Begin je volgende gesprek. Kijk naar de outbound-rtp-entries. Als frameWidth of framesPerSecond lager zijn dan wat je in je camera-instellingen hebt ingesteld, gebeurt de downgrade. De oorzaak is typisch bandbreedte-gerelateerd — wat je browser mag besteden, en of je verbinding de stream daadwerkelijk kan dragen die je denkt te zenden — maar CPU-belasting, encoderselectie, platformbeleiden en constraint-configuratie kunnen ook bijdragen aan of de degradatie domineren.