Leg een videostream vast van elk element

François Beaufort
François Beaufort

Met de Screen Capture API kunt u het volledige huidige tabblad vastleggen. Met de Element Capture API kunt u een specifiek HTML-element vastleggen en opnemen. Het transformeert een opname van het hele tabblad in een opname van een specifieke DOM-subboom, waarbij alleen directe afstammelingen van het doelelement worden vastgelegd. Met andere woorden, het snijdt en verwijdert zowel occluderende als occludeerde inhoud.

Waarom Element Capture gebruiken?

Als u de vereisten van een videoconferentietoepassing in overweging neemt, kunt u beter begrijpen waar Element Capture nuttig is. Als u een toepassing voor videoconferenties heeft waarmee u toepassingen van derden in een iframe kunt insluiten, wilt u dat iframe soms als video vastleggen en naar externe deelnemers verzenden.

Schermafbeelding van een videoconferentiegesprek in Chrome.
Elad gebruikt een applicatie van derden tijdens een videoconferentiegesprek met François.

Door getDisplayMedia() aan te roepen en de gebruiker het huidige tabblad te laten kiezen, wordt het gehele huidige tabblad verzonden. Hierdoor wordt waarschijnlijk de eigen video van mensen naar hen teruggestuurd. U kunt dit wegsnijden met behulp van Regio Capture .

Maar wat als de presentator de videoconferentietoepassing gebruikt en bepaalde inhoud, zoals een vervolgkeuzelijst, bovenop de inhoud komt die bedoeld is om vast te leggen?

Schermafbeelding van een vervolgkeuzelijst met inhoud die bedoeld is om vast te leggen.
Er verschijnt een vervolgkeuzelijst boven de inhoud die bedoeld is om vast te leggen.

Regio Capture zou je daar niet helpen. Een deel van de vervolgkeuzelijst kan zichtbaar worden op de schermen van externe deelnemers.

Schermafbeelding van een vastgelegde vervolgkeuzelijst.
De vervolgkeuzelijst van Elad verschijnt bovenaan de inhoud die François heeft ontvangen.

Het feit dat Region Capture delen van elementen op deze manier vastlegt (ook wel occluderende inhoud genoemd) zorgt voor meerdere problemen:

  • Het afsluiten van inhoud kan de weergave belemmeren van de inhoud die de gebruiker wilde delen.
  • Het afsluiten van inhoud kan privé zijn (denk aan chatmeldingen).
  • Het afsluiten van inhoud kan verwarrend zijn. (Een nieuwe lay-out van de applicatie zou bijvoorbeeld kort de eigen video's van de deelnemers op afstand over het vastgelegde doel kunnen brengen.)

De Element Capture API lost al deze problemen op, doordat u zich kunt richten op het element dat u wilt delen.

Schermafbeelding van het doelelement zonder vervolgkeuzelijst in beeld.
François ziet de vervolgkeuzelijst van Elad niet.

Hoe gebruik ik Element Capture?

De captureTarget is een element op uw pagina dat de inhoud bevat die de gebruiker wil vastleggen. U wilt dat de webapp voor videoconferenties captureTarget vastlegt en deelt met externe deelnemers. U leidt dus een RestrictionTarget af van captureTarget . Na het beperken van de videotrack met behulp van deze RestrictionTarget , bestaan ​​frames op die videotrack nu alleen uit de pixels die deel uitmaken van captureTarget en de directe DOM-afstammelingen ervan.

Als captureTarget van grootte, vorm of locatie verandert, volgt de videotrack mee, zonder dat er extra invoer van een van de webapps nodig is. Het afsluiten van inhoud die verschijnt, verdwijnt of beweegt, vereist eveneens geen speciale behandeling.

Bekijk deze stappen opnieuw:

Begin door de gebruiker toe te staan ​​het huidige tabblad vast te leggen.

// Ask the user for permission to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
 preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();

Definieer een RestrictionTarget door RestrictionTarget.fromElement() aan te roepen met een element naar keuze als invoer.

// Associate captureTarget with a new RestrictionTarget
const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

Roep vervolgens restrictTo() aan op de videotrack met de RestrictionTarget als invoer. Zodra de laatste belofte is vervuld, worden alle volgende frames beperkt.

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

// Enjoy! Transmit remotely.

Diepe duik

Functiedetectie

Om te controleren of RestrictionTarget.fromElement() wordt ondersteund, gebruikt u:

if ("RestrictionTarget" in self && "fromElement" in RestrictionTarget) {
  // Deriving a restriction target is supported.
}

Leid een beperkingsdoel af

Focus op het element genaamd captureTarget . Om er een RestrictionTarget van af te leiden, roept u RestrictionTarget.fromElement(captureTarget) aan. De geretourneerde Promise wordt, indien succesvol, opgelost met een nieuw RestrictionTarget -object. Anders wordt het afgewezen als u een onredelijk aantal RestrictionTarget objecten heeft aangemaakt.

const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

In tegenstelling tot een element is een RestrictionTarget object serialiseerbaar . Het kan bijvoorbeeld aan een ander document worden doorgegeven met behulp van Window.postMessage() .

Beperken

Bij het vastleggen van een tabblad wordt restrictTo() op de videotrack zichtbaar. Bij het vastleggen van het huidige tabblad is het geldig om restrictTo() aan te roepen met null of een RestrictionTarget afgeleid van een element binnen het huidige tabblad.

Aanroepen van restrictTo(restrictionTarget) muteren de videotrack in een capture van captureTarget , alsof deze op zichzelf is getekend, onafhankelijk van de rest van de DOM. Eventuele afstammelingen van captureTarget worden ook vastgelegd; broers en zussen van captureTarget worden geëlimineerd uit de capture. Het resultaat is dat alle frames die op de track worden afgeleverd, eruit zien alsof ze zijn bijgesneden volgens de contouren van captureTarget , en dat alle occluderende en occludeerde inhoud wordt verwijderd.

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

Aanroepen van restrictTo(null) brengen de track terug naar de oorspronkelijke staat.

// Stop restricting.
await track.restrictTo(null);

Als de aanroep van restrictTo() succesvol is, wordt de geretourneerde Promise opgelost wanneer gegarandeerd kan worden dat alle volgende videoframes beperkt zullen worden tot captureTarget .

Als dit niet lukt, wordt de belofte afgewezen. Een mislukte aanroep van restrictTo() kan een van de volgende redenen hebben:

  • Als de restrictionTarget is aangemaakt op een ander tabblad dan het tabblad dat wordt vastgelegd. (Houd er rekening mee dat gebruikers met de knop 'Dit tabblad in plaats daarvan delen' op elk gewenst moment kunnen wijzigen welk tabblad wordt vastgelegd.)
  • Als de restrictionTarget is afgeleid van een element dat niet meer bestaat.
  • Als de track klonen bevat. (Zie uitgave 1509418. )
  • Als de huidige track geen videotrack met zelfopname is.
  • Als het element waarvan restrictionTarget is afgeleid, niet in aanmerking komt voor beperking.

Overwegingen bij zelfopname

Wanneer een app getDisplayMedia() aanroept en de gebruiker ervoor kiest om het eigen tabblad van de app vast te leggen, noemen we dat 'self-capture'.

De methode restrictTo() wordt weergegeven op elke videotrack voor het vastleggen van tabbladen, en niet alleen voor zelfopname. Maar Element Capture is voorlopig alleen ingeschakeld voor zelfopname. Het is daarom raadzaam om te controleren of de gebruiker het huidige tabblad heeft geselecteerd, voordat u probeert de track te beperken. Dit kan worden bereikt met behulp van Capture Handle . Het is ook mogelijk om de browser te vragen de gebruiker aan te zetten tot zelfopname met behulp van preferCurrentTab .

Transparantie

Videoframes die de app via getDisplayMedia() ontvangt, bevatten geen alfakanaal. Als een app een gedeeltelijk transparant vastlegdoel instelt, heeft het strippen van het alfakanaal enkele mogelijke gevolgen:

  • Kleuren kunnen veranderen. Gedeeltelijk transparante doelelementen die op een lichte achtergrond zijn getekend, kunnen donkerder lijken als het alfakanaal wordt verwijderd, en elementen die op een donkere achtergrond zijn getekend, kunnen lichter lijken.
  • Kleuren die onzichtbaar of niet waarneembaar waren voor de gebruiker toen het alfakanaal op het maximum werd ingesteld, verschijnen zodra het alfakanaal is verwijderd. Dit zou bijvoorbeeld kunnen leiden tot onverwachte zwarte gebieden in de vastgelegde frames als de transparante secties de RGBA-code rgba(0, 0, 0, 0) hadden.
Screenshot van het resultaat van een niet-rechthoekig transparant vangdoel.
De niet-rechthoekige, transparante doelvideostream (rechts) is een zwarte achtergrondrechthoek met een ondoorzichtige blauwe cirkel.

Niet-geschikte veroveringsdoelen

Het is altijd mogelijk om een ​​track te beperken tot elk geldig vangdoel. Onder bepaalde omstandigheden worden er echter geen frames geproduceerd, bijvoorbeeld als het element of een voorouder display:none is. De algemene redenering is dat de beperking alleen van toepassing is op een element dat een enkel, samenhangend, tweedimensionaal, rechthoekig gebied omvat, waarvan de pixels logisch kunnen worden bepaald los van eventuele ouder- of zusterelementen.

Een belangrijke overweging om ervoor te zorgen dat het element in aanmerking komt voor beperking, is dat het zijn eigen stapelcontext moet vormen. Om dit te garanderen, kunt u de isolatie -CSS-eigenschap opgeven en deze instellen op isolate .

<div id="captureTarget" style="isolation: isolate;"></iframe>

Houd er rekening mee dat het doelelement op elk willekeurig moment kan schakelen tussen wel of niet in aanmerking komen voor beperking, bijvoorbeeld als de app de CSS-eigenschappen wijzigt. Het is aan de app om redelijke vastlegdoelen te gebruiken en te voorkomen dat hun eigenschappen onverwachts worden gewijzigd. Als het doelelement niet meer in aanmerking komt, zullen er eenvoudigweg geen nieuwe frames op de baan worden uitgezonden totdat het doelelement weer in aanmerking komt voor beperking.

Elementopname inschakelen

De Element Capture API is beschikbaar in Chrome op desktop achter de Element Capture-vlag en kan worden ingeschakeld op chrome://flags/#element-capture .

Deze functie gaat ook een origin-proefversie van Chrome 121 op desktop in , waarmee ontwikkelaars de functie kunnen inschakelen waarmee bezoekers van hun sites gegevens van echte gebruikers kunnen verzamelen. Zie Aan de slag met origin-proefversies voor meer informatie over origin-proefversies.

Beveiliging en privacy

Om de beveiligingsafwegingen te begrijpen, bekijk het gedeelte Privacy- en beveiligingsoverwegingen van de Element Capture-specificatie.

De Chrome-browser tekent een blauwe rand rond de randen van vastgelegde tabbladen.

Demo

Je kunt met Element Capture spelen door de demo op Glitch uit te voeren. Zorg ervoor dat u de broncode bekijkt .

Feedback

Het Chrome-team en de webstandaardengemeenschap willen graag horen over uw ervaringen met Element Capture.

Vertel ons over het ontwerp

Is er iets aan Regio Capture dat niet werkt zoals je had verwacht? Of ontbreken er methoden of eigenschappen die je nodig hebt om je idee te implementeren? Heeft u een vraag of opmerking over het beveiligingsmodel?

  • Dien een spec-probleem in op de GitHub-repository of voeg uw mening toe aan een bestaand probleem.

Probleem met de implementatie?

Heeft u een bug gevonden in de implementatie van Chrome? Of wijkt de uitvoering af van de specificaties?

  • Dien een bug in op https://new.crbug.com . Zorg ervoor dat u zoveel mogelijk details en eenvoudige reproductie-instructies opneemt. Glitch werkt uitstekend voor het delen van snelle en gemakkelijke reproducties.

Dankbetuigingen

Foto door Paul Skorupskas op Unsplash