Videostream von einem beliebigen Element erfassen

François Beaufort
François Beaufort

Mit der Screen Capture API können Sie den gesamten aktuellen Tab erfassen. Mit der Element Capture API können Sie ein bestimmtes HTML-Element erfassen und aufzeichnen. Dabei wird eine Aufnahme des gesamten Tabs in eine Aufnahme eines bestimmten DOM-untergeordneten Knotens umgewandelt, wobei nur direkte Nachkommen des Zielelements erfasst werden. Mit anderen Worten: Es werden sowohl verdeckende als auch verdeckte Inhalte zugeschnitten und entfernt.

Vorteile von Element Capture

Wenn Sie die Anforderungen einer Videokonferenzanwendung berücksichtigen, können Sie besser nachvollziehen, in welchen Fällen Element Capture nützlich ist. Wenn Sie eine Videokonferenzanwendung haben, mit der Sie Drittanbieteranwendungen in einen iFrame einbetten können, möchten Sie diesen iFrame manchmal als Video erfassen und an die Teilnehmer an anderen Standorten senden.

Screenshot eines Videokonferenzanrufs in Chrome
Elad verwendet eine Drittanbieteranwendung in einem Videokonferenzanruf mit François.

Wenn getDisplayMedia() aufgerufen und der Nutzer den aktuellen Tab auswählen lässt, wird der gesamte aktuelle Tab übertragen. Dadurch wird wahrscheinlich das Video von Personen an sie zurückgesendet. Sie können dies mit der Funktion Bereich erfassen zuschneiden.

Was ist aber, wenn der Vortragende mit der Videokonferenzanwendung interagiert und einige Inhalte, z. B. eine Drop-down-Liste, zufällig über den Inhalten zu sehen sind, die erfasst werden sollen?

Screenshot einer Drop-down-Liste, die Inhalte verdeckt, die erfasst werden sollen
Über dem für die Aufnahme vorgesehenen Inhalt wird eine Drop-down-Liste angezeigt.

Die Funktion „Region Capture“ kann Ihnen dabei nicht helfen. Möglicherweise ist ein Teil der Drop-down-Liste auf den Bildschirmen der Teilnehmer im Homeoffice sichtbar.

Screenshot einer Drop-down-Liste
Die Drop-down-Liste von Elad wird über den von François empfangenen Inhalten angezeigt.

Da bei der Regionserfassung Teile von Elementen auf diese Weise erfasst werden (ausblendende Inhalte), kann es zu mehreren Problemen kommen:

  • Inhalte, die den Blick verdecken, können die Inhalte verdecken, die der Nutzer teilen wollte.
  • Die blockierten Inhalte können privat sein, z. B. Chatbenachrichtigungen.
  • Wenn Inhalte verdeckt werden, kann das verwirrend sein. Beispielsweise könnte ein Neulayout der Anwendung dazu führen, dass die eigenen Videos der Remote-Teilnehmer kurzzeitig über das erfasste Ziel erscheinen.

Die Element Capture API löst all diese Probleme, da Sie das Element auswählen können, das Sie teilen möchten.

Screenshot des Zielelements ohne Drop-down-Liste
François sieht die Drop-down-Liste von Elad nicht.

Wie verwende ich Element Capture?

Das captureTarget ist ein Element auf Ihrer Seite, das den Inhalt enthält, den der Nutzer erfassen möchte. Sie möchten, dass die Web-App für Videokonferenzen captureTarget erfasst und für Remote-Teilnehmer freigibt. Also leiten Sie ein RestrictionTarget von captureTarget ab. Nachdem der Videotrack mit dieser RestrictionTarget eingeschränkt wurde, bestehen Frames in diesem Videotrack jetzt nur noch aus den Pixeln, die zu captureTarget und seinen direkten DOM-Nachkommen gehören.

Wenn captureTarget seine Größe, Form oder Position ändert, folgt der Videotrack ohne zusätzliche Eingabe von einer der beiden Web-Apps. Auch wenn Inhalte verdeckt werden, die erscheinen, verschwinden oder sich bewegen, ist keine spezielle Behandlung erforderlich.

Gehen Sie noch einmal die folgenden Schritte durch:

Lassen Sie den Nutzer zuerst den aktuellen Tab erfassen.

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

Definieren Sie eine RestrictionTarget, indem Sie RestrictionTarget.fromElement() mit einem Element Ihrer Wahl als Eingabe aufrufen.

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

Rufe dann restrictTo() auf dem Videotrack mit RestrictionTarget als Eingabe auf. Sobald das letzte Promise aufgelöst wurde, werden alle nachfolgenden Frames eingeschränkt.

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

// Enjoy! Transmit remotely.

Im Detail

Funktionserkennung

So prüfen Sie, ob RestrictionTarget.fromElement() unterstützt wird:

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

RestrictionTarget ableiten

Legen Sie den Fokus auf das Element namens captureTarget. Um ein RestrictionTarget daraus abzuleiten, rufen Sie RestrictionTarget.fromElement(captureTarget) auf. Das zurückgegebene Promise wird bei Erfolg mit einem neuen RestrictionTarget-Objekt aufgelöst. Andernfalls wird es abgelehnt, wenn Sie eine unangemessen hohe Anzahl von RestrictionTarget-Objekten erstellt haben.

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

Im Gegensatz zu einem Element ist ein RestrictionTarget-Objekt serialisierbar. Sie können sie beispielsweise mit Window.postMessage() an ein anderes Dokument übergeben.

Eingeschränkt

Wenn Sie einen Tab aufzeichnen, wird im Videotrack restrictTo() angezeigt. Wenn Sie den aktuellen Tab erfassen, können Sie restrictTo() entweder mit null oder mit einem RestrictionTarget aufrufen, das von einem Element auf dem aktuellen Tab abgeleitet wurde.

Aufrufe von restrictTo(restrictionTarget) wandeln den Videotrack in eine Aufnahme von captureTarget um, als wäre er unabhängig vom Rest des DOMs selbst gezeichnet worden. Alle Nachkommen von captureTarget werden ebenfalls erfasst. Geschwister von captureTarget werden aus der Erfassung ausgeschlossen. Das Ergebnis ist, dass alle über den Track gesendeten Frames so erscheinen, als wären sie auf die Konturen von captureTarget zugeschnitten. Alle verdeckten und verdeckten Inhalte werden entfernt.

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

Durch Aufrufe an restrictTo(null) wird der Track auf seinen ursprünglichen Zustand zurückgesetzt.

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

Wenn der Aufruf von restrictTo() erfolgreich ist, wird das zurückgegebene Promise aufgelöst, wenn garantiert werden kann, dass alle nachfolgenden Videoframes auf captureTarget beschränkt werden.

Bei Nichtbestehen wird das Promise abgelehnt. Ein fehlgeschlagener Aufruf von restrictTo() kann aus einem der folgenden Gründe erfolgen:

  • Wenn die restrictionTarget auf einem anderen Tab als dem erfassten Tab erstellt wurde. Mit der Schaltfläche „Diesen Tab stattdessen teilen“ können Nutzer jederzeit ändern, welcher Tab erfasst wird.
  • Wenn die restrictionTarget aus einem Element abgeleitet wurde, das nicht mehr vorhanden ist.
  • Ob der Track Klone hat (Siehe Problem 1509418.)
  • Der aktuelle Track ist kein von Ihnen selbst aufgenommener Videotrack.
  • Wenn das Element, von dem restrictionTarget abgeleitet wurde, nicht für eine Einschränkung infrage kommt.

Aspekte bei der Erfassung durch Nutzer

Wenn eine App getDisplayMedia() aufruft und der Nutzer den Tab der App selbst erfassen möchte, wird dies als „Selbsterfassung“ bezeichnet.

Die Methode restrictTo() wird in jedem Tab-Videotrack angezeigt, nicht nur für Selbstaufnahmen. Die Elementerfassung ist jedoch vorerst nur für Selbstaufnahmen aktiviert. Es empfiehlt sich daher, zu prüfen, ob der Nutzer den aktuellen Tab ausgewählt hat, bevor Sie versuchen, den Titel einzuschränken. Dazu können Sie den Capture-Griff verwenden. Es ist auch möglich, den Browser zu bitten, den Nutzer mit preferCurrentTab zur Selbstaufnahme anzuregen.

Transparenz

Videoframes, die die App über getDisplayMedia() erhält, enthalten keinen Alphakanal. Wenn eine App ein teilweise transparentes Aufnahmeziel festlegt, hat das Entfernen des Alphakanals einige mögliche Folgen:

  • Die Farben können sich ändern. Teilweise transparente Zielelemente, die auf einem hellen Hintergrund gezeichnet wurden, können dunkler erscheinen, wenn der Alphakanal entfernt wird. Elemente, die auf einem dunklen Hintergrund gezeichnet wurden, können heller erscheinen.
  • Farben, die für den Nutzer unsichtbar oder nicht wahrnehmbar waren, wenn der Alphakanal auf das Maximum gesetzt war, werden angezeigt, sobald der Alphakanal entfernt wird. Das kann beispielsweise zu unerwarteten schwarzen Bereichen in den aufgenommenen Frames führen, wenn die transparenten Bereiche den RGBA-Code rgba(0, 0, 0, 0) haben.
Screenshot des Ergebnisses eines nicht rechteckigen transparenten Aufnahmeziels.
Der nicht rechteckige Videostream für das transparente Erfassungsziel (rechts) ist ein Rechteck mit schwarzem Hintergrund, das einen undurchsichtigen blauen Kreis enthält.

Unzulässige Erfassungsziele

Sie können einen Track jederzeit auf ein beliebiges gültiges Aufnahmeziel beschränken. Unter bestimmten Bedingungen werden jedoch keine Frames erstellt, z. B. wenn das Element oder ein übergeordnetes Element display:none ist. Die Einschränkung gilt nur für ein Element, das aus einem einzigen zusammenhängenden zweidimensionalen rechteckigen Bereich besteht, dessen Pixel unabhängig von übergeordneten oder untergeordneten Elementen logisch bestimmt werden können.

Ein wichtiges Kriterium für die Einschränkung eines Elements ist, dass es einen eigenen Stapelkontext bildet. Dazu können Sie die CSS-Eigenschaft isolation mit dem Wert isolate angeben.

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

Das Zielelement kann jederzeit zwischen „Eingeschränkt“ und „Nicht eingeschränkt“ wechseln, z. B. wenn die App ihre CSS-Eigenschaften ändert. Die App muss angemessene Erfassungsziele verwenden und ihre Eigenschaften nicht unerwartet ändern. Wenn das Zielelement nicht mehr zulässig ist, werden keine neuen Frames für den Track gesendet, bis das Zielelement wieder für die Einschränkung infrage kommt.

Element Capture aktivieren

Die Element Capture API ist in Chrome auf dem Computer über das Element Capture-Flag verfügbar und kann unter chrome://flags/#element-capture aktiviert werden.

Für diese Funktion beginnt ein Ursprungstest von Chrome 121 auf Computern, mit dem Entwickler die Funktion für Besucher ihrer Websites aktivieren können, um Daten von echten Nutzern zu erheben. Weitere Informationen zu Ursprungstests finden Sie unter Erste Schritte mit Ursprungstests.

Sicherheit und Datenschutz

Weitere Informationen zu den Sicherheitsabwägungen finden Sie in der Element Capture-Spezifikation im Abschnitt Datenschutz- und Sicherheitsaspekte.

Der Chrome-Browser zeichnet einen blauen Rahmen um die Ränder der erfassten Tabs.

Demo

Du kannst Element Capture ausprobieren, indem du die Demo auf Glitch ausführst. Sehen Sie sich den Quellcode an.

Feedback

Das Chrome-Team und die Webstandards-Community möchten gerne wissen, welche Erfahrungen Sie mit Element Capture gemacht haben.

Designbeschreibung

Funktioniert die Funktion „Region Capture“ nicht wie erwartet? Oder fehlen Methoden oder Eigenschaften, die Sie für die Implementierung Ihrer Idee benötigen? Haben Sie Fragen oder Kommentare zum Sicherheitsmodell?

  • Melden Sie ein Problem mit der Spezifikation im GitHub-Repository oder fügen Sie Ihre Gedanken zu einem vorhandenen Problem hinzu.

Problem bei der Implementierung?

Haben Sie bei der Implementierung von Chrome einen Fehler gefunden? Oder unterscheidet sich die Implementierung von der Spezifikation?

  • Melden Sie den Fehler unter https://new.crbug.com. Geben Sie dabei so viele Details wie möglich an und machen Sie eine einfache Anleitung zur Reproduktion. Glitch eignet sich hervorragend, um schnell und einfach Reproduktionen zu teilen.

Danksagung

Foto von Paul Skorupskas auf Unsplash