Przechwytuj strumień wideo z dowolnego elementu

François Beaufort
François Beaufort

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.

Zrzut ekranu przedstawiający połączenie wideo w Chrome.
Elad używa aplikacji innej firmy podczas rozmowy wideo z François.

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?

Zrzut ekranu przedstawiający menu, które zasłania treści przeznaczone do przechwycenia.
Nad treścią, którą chcesz przechwycić, pojawi się lista.

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

Zrzut ekranu z listą.
Lista Elada pojawia się nad treściami otrzymanymi przez François.

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ć.

Zrzut ekranu elementu docelowego bez widocznej listy rozwijanej.
François nie widzi listy od Elada.

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 RestrictionTargetcaptureTarget. 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.
Zrzut ekranu przedstawiający wynik przechwytywania przezroczystego celu o kształcie innym niż prostokąt.
Strumień wideo z nieprostokątnym przezroczystym celem przechwytywania (po prawej) to prostokąt z czarnym tłem, który zawiera nieprzezroczysty niebieski okrąg.

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.

Podziękowania

Zdjęcie: Paul Skorupskas, Unsplash