Za pomocą interfejsu Screen Capture API możesz przechwycić całą bieżącą kartę. Element Capture API umożliwia przechwytywanie i nagrywanie konkretnego elementu HTML. Przekształca przechwycenie całej karty w przechwycenie określonego poddrzewa DOM, przechwytując tylko bezpośrednie elementy podrzędne elementu docelowego. Innymi słowy, przycina i usuwa zarówno treści zasłaniające, jak i zasłonięte.
Dlaczego warto korzystać z funkcji przechwytywania elementu?
Zastanów się, w jakich sytuacjach Element Capture może być przydatne, biorąc pod uwagę wymagania aplikacji do wideokonferencji. Jeśli masz aplikację do obsługi rozmów wideo, która umożliwia osadzanie aplikacji innych firm w elemencie iframe, możesz czasami chcieć przechwycić ten element iframe jako wideo i przesłać go do uczestników zdalnych.

Wywołanie funkcji getDisplayMedia()
i umożliwienie użytkownikowi wyboru bieżącej karty spowoduje przesłanie całej bieżącej karty. Prawdopodobnie spowoduje to przesłanie własnego filmu z powrotem do użytkownika. Możesz to przyciąć za pomocą Zrzutu obszaru.
Co jednak, jeśli prezenter korzysta z aplikacji do wideokonferencji i niektóre treści, np. lista rozwijana, pojawiają się na wierzchu treści, które mają zostać zarejestrowane?

Przechwytywanie regionu nie pomoże Ci w tym przypadku. Część listy może być widoczna na ekranach uczestników zdalnych.

Fakt, że funkcja przechwytywania regionu w ten sposób przechwytuje części elementów (tzw. zasłanianie treści), powoduje wiele problemów:
- Zasłanianie treści może uniemożliwić wyświetlenie treści, które użytkownik chciał udostępnić.
- Treści zasłaniające mogą być prywatne (np. powiadomienia na czacie).
- Treści zasłaniające mogą być mylące. (Na przykład zmiana układu aplikacji może na chwilę przenieść filmy uczestników zdalnych nad przechwycony obiekt).
Interfejs Element Capture API rozwiązuje wszystkie te problemy, umożliwiając kierowanie na element, który chcesz udostępnić.

Jak korzystać z funkcji przechwytywania elementu?
captureTarget
to element na stronie, który zawiera treść, którą użytkownik chce przechwycić. Chcesz, aby aplikacja internetowa do rozmów wideo rejestrowała captureTarget
i udostępniała je uczestnikom zdalnym. W ten sposób uzyskujesz RestrictionTarget
z captureTarget
. Po ograniczeniu ścieżki wideo za pomocą tego RestrictionTarget
klatki na tej ścieżce wideo będą zawierać tylko piksele, które są częścią elementu captureTarget
i jego bezpośrednich elementów podrzędnych DOM.
Jeśli captureTarget
zmieni rozmiar, kształt lub położenie, ścieżka wideo będzie podążać za nim bez konieczności wprowadzania dodatkowych danych w żadnej z aplikacji internetowych. Zasłanianie treści, które pojawiają się, znikają lub przemieszczają się, również nie wymaga specjalnego traktowania.
Powtórz te kroki:
Zacznij od umożliwienia użytkownikowi przechwycenia bieżącej karty.
// Ask the user for permission to start capturing the current tab. const stream = await navigator.mediaDevices.getDisplayMedia({ preferCurrentTab: true, }); const [track] = stream.getVideoTracks();
Zdefiniuj RestrictionTarget
, wywołując funkcję RestrictionTarget.fromElement()
z wybranym elementem jako danymi wejściowymi.
// Associate captureTarget with a new RestrictionTarget const captureTarget = document.querySelector("#captureTarget"); const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);
Następnie wywołaj funkcję restrictTo()
na ścieżce wideo, używając RestrictionTarget
jako danych wejściowych. Gdy ostatnia obietnica zostanie spełniona, wszystkie kolejne ramki będą ograniczone.
// Start restricting the self-capture video track using the RestrictionTarget. await track.restrictTo(restrictionTarget); // Enjoy! Transmit remotely.
Szczegółowa analiza
Wykrywanie cech
Aby sprawdzić, czy znak RestrictionTarget.fromElement()
jest obsługiwany, użyj tego kodu:
if ("RestrictionTarget" in self && "fromElement" in RestrictionTarget) { // Deriving a restriction target is supported. }
Tworzenie obiektu RestrictionTarget
Skup się na elemencie o nazwie captureTarget
. Aby uzyskać z niego RestrictionTarget
, wywołaj funkcję RestrictionTarget.fromElement(captureTarget)
. Jeśli operacja się uda, zwrócony obiekt Promise zostanie rozwiązany za pomocą nowego obiektu RestrictionTarget
. W przeciwnym razie zostanie odrzucony, jeśli utworzysz nieuzasadnioną liczbę obiektów RestrictionTarget
.
const captureTarget = document.querySelector("#captureTarget"); const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);
W odróżnieniu od obiektu Element obiekt RestrictionTarget
jest serializowalny. Można go przekazać do innego dokumentu, np. za pomocą funkcji Window.postMessage()
.
Kierowanie ograniczone
Podczas przechwytywania karty ścieżka wideo udostępnia restrictTo()
. Podczas przechwytywania bieżącej karty można wywołać funkcję restrictTo()
z argumentem null
lub dowolnym argumentem RestrictionTarget
pochodzącym z elementu na bieżącej karcie.
Wywołania restrictTo(restrictionTarget)
przekształcają ścieżkę wideo w obraz captureTarget
, jakby był on rysowany samodzielnie, niezależnie od reszty DOM. Zostaną też przechwycone wszystkie elementy podrzędne elementu captureTarget
, a elementy równorzędne elementu captureTarget
zostaną wykluczone z przechwytywania. W rezultacie wszystkie klatki dostarczone na ścieżce są przycinane do konturów captureTarget
, a wszystkie treści zasłaniające i zasłonięte są usuwane.
// Start restricting the self-capture video track using the RestrictionTarget. await track.restrictTo(restrictionTarget);
Wywołania restrictTo(null)
przywracają ścieżkę do pierwotnego stanu.
// Stop restricting. await track.restrictTo(null);
Jeśli wywołanie funkcji restrictTo()
zakończy się powodzeniem, zwrócona obietnica zostanie rozwiązana, gdy będzie można zagwarantować, że wszystkie kolejne klatki wideo będą ograniczone do captureTarget
.
Jeśli się nie powiedzie, obietnica zostanie odrzucona. Nieudane połączenie z restrictTo()
może być spowodowane jednym z tych powodów:
- Jeśli
restrictionTarget
został wygenerowany na karcie innej niż ta, która jest rejestrowana. (Pamiętaj, że za pomocą przycisku „Udostępnij tę kartę” użytkownicy mogą w dowolnym momencie zmienić kartę, która jest rejestrowana). - Jeśli
restrictionTarget
pochodzi z elementu, który już nie istnieje. - Jeśli utwór ma klony. (Zobacz problem 1509418).
- Jeśli bieżąca ścieżka nie jest ścieżką wideo z nagraniem własnym.
- Jeśli element, z którego pochodzi
restrictionTarget
, nie kwalifikuje się do ograniczenia.
Uwagi dotyczące samodzielnego rejestrowania
Gdy aplikacja wywołuje funkcję getDisplayMedia()
, a użytkownik zdecyduje się zarejestrować własną kartę aplikacji, nazywamy to „samodzielnym rejestrowaniem”.
Metoda restrictTo()
jest dostępna na każdej ścieżce wideo z nagrywania karty, a nie tylko w przypadku nagrywania własnego. Funkcja przechwytywania elementów jest obecnie włączona tylko w przypadku samodzielnego przechwytywania. Dlatego przed próbą ograniczenia ścieżki warto sprawdzić, czy użytkownik wybrał bieżącą kartę. Można to zrobić za pomocą Capture Handle. Możesz też poprosić przeglądarkę o zachęcenie użytkownika do samodzielnego wykonania zdjęcia za pomocą funkcji preferCurrentTab
.
Przejrzystość
Klatki wideo, które aplikacja uzyskuje za pomocą interfejsu getDisplayMedia()
, nie zawierają kanału alfa. Jeśli aplikacja ustawi częściowo przezroczysty cel przechwytywania, usunięcie kanału alfa może mieć pewne konsekwencje:
- Kolory mogą się zmienić. Częściowo przezroczyste elementy docelowe narysowane na jasnym tle mogą wydawać się ciemniejsze po usunięciu kanału alfa, a te narysowane na ciemnym tle mogą wydawać się jaśniejsze.
- Kolory, które były niewidoczne lub niedostrzegalne dla użytkownika, gdy kanał alfa był ustawiony na maksymalną wartość, pojawią się po usunięciu kanału alfa. Jeśli na przykład przezroczyste sekcje miały kod RGBA
rgba(0, 0, 0, 0)
, może to spowodować pojawienie się nieoczekiwanych czarnych obszarów w przechwyconych klatkach.

Niekwalifikujące się cele przechwytywania
Zawsze możesz ograniczyć śledzenie do dowolnego prawidłowego obiektu docelowego. Ramki nie będą jednak generowane w określonych warunkach, np. jeśli element lub jego element nadrzędny jest display:none
. Ogólne uzasadnienie jest takie, że ograniczenie dotyczy tylko elementu, który obejmuje pojedynczy, spójny, dwuwymiarowy, prostokątny obszar, którego piksele można logicznie określić w izolacji od elementów nadrzędnych lub równorzędnych.
Aby element kwalifikował się do ograniczenia, musi tworzyć własny kontekst układania. Aby to zapewnić, możesz określić właściwość CSS isolation i ustawić ją na isolate
.
<div id="captureTarget" style="isolation: isolate;"></iframe>
Pamiętaj, że element docelowy może w dowolnym momencie stać się odpowiedni lub nieodpowiedni do ograniczenia, np. jeśli aplikacja zmieni swoje właściwości CSS. Aplikacja musi używać rozsądnych celów przechwytywania i unikać nieoczekiwanych zmian ich właściwości. Jeśli element docelowy przestanie kwalifikować się do ograniczenia, nowe klatki nie będą emitowane na ścieżce, dopóki element docelowy ponownie nie będzie kwalifikować się do ograniczenia.
Obsługa przeglądarek
Funkcja przechwytywania elementów jest dostępna tylko na komputerach w Chrome 132 i nowszych.
Bezpieczeństwo i prywatność
Aby poznać kompromisy w zakresie bezpieczeństwa, zapoznaj się z sekcją Privacy and Security Considerations (Kwestie związane z prywatnością i bezpieczeństwem) w specyfikacji Element Capture.
Przeglądarka Chrome rysuje niebieskie obramowanie wokół krawędzi przechwyconych kart.
Prezentacja
Możesz wypróbować przechwytywanie elementów, uruchamiając wersję demonstracyjną.
Prześlij opinię
Zespół Chrome i społeczność zajmująca się standardami internetowymi chcą poznać Twoje wrażenia związane z funkcją przechwytywania elementów.
Opisz projekt
Czy w przypadku funkcji przechwytywania elementu coś nie działa zgodnie z oczekiwaniami? Czy brakuje metod lub właściwości, które są potrzebne do realizacji Twojego pomysłu? Masz pytania lub uwagi dotyczące modelu zabezpieczeń?
- Zgłoś problem ze specyfikacją w repozytorium GitHub lub dodaj swoje uwagi do istniejącego problemu.
Masz problem z implementacją?
Czy w implementacji Chrome występuje błąd? A może implementacja różni się od specyfikacji?
- Zgłoś błąd na stronie https://new.crbug.com. Podaj jak najwięcej szczegółów i proste instrukcje odtworzenia problemu.
Przydatne linki
Podziękowania
Zdjęcie: Paul Skorupskas, Unsplash