Artikelen · Experiment
Twee browsers, één scherm
Meekijken alsof je naast iemand zit, zonder je scherm te delen. Er gaat geen beeld over de lijn, alleen wat er gebeurt.
Wat ik me afvroeg
Kun je iemand op afstand volgen alsof je naast hem zit, zonder je hele scherm te delen? En hoe weinig is daarvoor nodig?
Scherm delen is alles of niets. De ander ziet je hele scherm, als video. Dat is zwaar voor de lijn, en het is meer dan je meestal wilt laten zien.
Wat ik deed
Ik verstuur geen beeld. Ik verstuur wat er gebeurt:
- plek: op welke pagina je bent;
- scrollen: hoe ver je bent;
- aanwijzer: waar je muis of vinger is;
- aandacht: welk veld je hebt aangeklikt;
- tekst: wat je daarin typt.
De ander heeft dezelfde pagina voor zich. Zijn browser bouwt met die vijf gegevens zelf het beeld op. In het voorbeeld zie je het: links ben jij, rechts de meekijker.
Het eerste experiment was groter. Meerdere mensen waren tegelijk aan het werk in dezelfde omgeving. In het menu zag je met gekleurde stippen wie waar was. Eén klik op volg, en je scherm liep mee met dat van de ander: dezelfde pagina, dezelfde plek, het veld dat oplicht, de tekst die verschijnt. En je kon op elk moment inbreken met beeld, geluid of een bericht.
In dat experiment liep het volgen via een server. De rechtstreekse verbinding tussen twee browsers, WebRTC, gebruikte ik alleen voor beeld, geluid en chat. Hier is het omgedraaid: deze pagina heeft geen server, dus alles gaat over de rechtstreekse lijn.
Wat me verbaasde
Hoe weinig er over de lijn gaat
Kijk naar de tellers onder de twee vlakken. Elke beweging van de aanwijzer is één bericht van hooguit 31 bytes. Naar een ander tabblad gaan: 22 bytes.
Typen kost het meest. Bij elke toets gaat de hele inhoud van het veld mee. Een zin van 45 tekens is 45 berichten, samen ruim 2,5 kB. Dat is nog steeds minder dan één kleine foto.
Video stuurt elk beeld opnieuw, ook als er niets verandert. Dit stuurt alleen iets als er iets gebeurt. Doe je niets, dan gaat er niets over de lijn.
Een stip is al genoeg
Zet het delen op aanwijzer en beweeg. Rechts beweegt alleen een stip. Toch weet je meteen: daar is iemand, en die kijkt naar dat stuk.
Zet het op plek. Nu zie je alleen op welk tabblad de ander is. Zelfs dat is al aanwezigheid. In het eerste experiment waren dat de stippen in het menu.
Delen heeft een grens
Zet het op tekst en typ een zin. Haal een woord weg en typ een ander. De meekijker ziet het allemaal: ook wat je weghaalt, ook je twijfel.
Je ziet de ander denken.
Dat is precies wat je wilt als je iemand helpt. En precies wat je niet wilt als je gewoon aan het werk bent. Daarom zit er een grens in: jij kiest hoeveel je deelt.
Eén stap terug, naar aandacht, en de meekijker ziet nog wel waar je bezig bent, maar niet meer wat je schrijft.
Zelfs twee vensters moeten aan elkaar worden voorgesteld
Twee browsers kunnen rechtstreeks met elkaar praten. Maar eerst moeten ze elkaar vinden. Ze wisselen een aanbod en een antwoord uit, en de adressen waarop ze te bereiken zijn. Die kennismaking gaat altijd via iets anders.
Tussen twee computers is dat een server. Hier zitten de twee kanten in dezelfde pagina, en geven ze het elkaar gewoon aan. Druk op open een tweede venster: dan doen twee vensters van je browser hetzelfde, via een kanaal dat de browser zelf biedt.
Na de kennismaking is het tussenstation niet meer nodig.
Hoe het werkt
Wat jij doet, wordt een klein bericht. Dit is het scrollen:
leadPane.scroller.addEventListener("scroll", () => {
if (scrollFrame) return;
scrollFrame = requestAnimationFrame(() => {
scrollFrame = 0;
if (state.level >= 2) send({ t: "scroll", y: scrollPos() });
});
}, { passive: true });
Hooguit één bericht per beeld, en alleen als je scrollen deelt. Het getal is een deel van de pagina, van 0 tot 1. Zo klopt het ook als het venster van de ander een andere maat heeft.
En dit is de kennismaking tussen de twee kanten in deze pagina:
const a = new RTCPeerConnection();
const b = new RTCPeerConnection();
a.onicecandidate = (e) => e.candidate && b.addIceCandidate(e.candidate);
b.onicecandidate = (e) => e.candidate && a.addIceCandidate(e.candidate);
const channel = a.createDataChannel("follow");
await a.setLocalDescription(await a.createOffer());
await b.setRemoteDescription(a.localDescription);
await b.setLocalDescription(await b.createAnswer());
await a.setRemoteDescription(b.localDescription);
Een aanbod, een antwoord, en de adressen over en weer. Daarna is channel een rechtstreekse lijn waar je tekst overheen stuurt.
De code
github.com/hexzmedia/exp-follow
Gemaakt met hulp van AI. De code, het voorbeeld op deze pagina en de tekst zijn met een AI-assistent gemaakt. Het idee, de vragen en de keuzes zijn van mij.