Przechwytuj strumień wideo z dowolnego elementu

François Beaufort
François Beaufort

Za pomocą interfejsu Screen Capture API możesz uchwycić cały bieżący kartę. Interfejs Element Capture API umożliwia przechwycenie i zapisanie konkretnego elementu HTML. Przekształca ono zrzut całej karty w zrzut konkretnego poddrzewa DOM, obejmując tylko bezpośrednich potomków elementu docelowego. Inaczej mówiąc, przycina i usuwa zarówno zasłaniające, jak i zasłaniane treści.

Dlaczego warto korzystać z Element Capture?

Zapoznanie się z wymaganiami aplikacji do wideokonferencji może pomóc Ci zrozumieć, w jakich sytuacjach Element Capture jest przydatny. Jeśli masz aplikację do rozmów wideo, która umożliwia umieszczanie aplikacji innych firm w iframe, możesz czasem chcieć przechwycić ten iframe jako film i przesłać go do uczestników zdalnych.

Zrzut ekranu z wideokonferencji w Chrome
Elad używa aplikacji innej firmy podczas rozmowy wideo z François.

Wywołanie metody getDisplayMedia() i pozwolenienie użytkownikowi na wybranie bieżącej karty spowoduje przesłanie całej bieżącej karty. Prawdopodobnie przesyła ona filmy do użytkowników. Możesz je przyciąć, korzystając z funkcji Zrzut obszaru ekranu.

Co jednak, jeśli prowadzący korzysta z aplikacji do wideokonferencji, a niektóre treści, na przykład lista rozwijana, są nakładane na treści, które mają być rejestrowane?

Zrzut ekranu z listą rozwijaną zasłaniającą treści przeznaczone do przechwycenia.
Nad treściami przeznaczonymi do przechwycenia pojawi się menu.

W tym przypadku funkcja Region Capture nie pomoże. Część listy może być widoczna na ekranach uczestników zdalnych.

Zrzut ekranu z wyświetloną listą rozwijaną
Lista rozwijana Elada pojawia się nad treściami otrzymanymi przez Françoisa.

Fakt, że funkcja Region Capture rejestruje w ten sposób części elementów (nazywana zakrywaniem treści), powoduje wiele problemów:

  • Zasłonięcie treści może uniemożliwić wyświetlenie treści, które użytkownik chce udostępnić.
  • Zasłonięte treści mogą być prywatne (np. powiadomienia na czacie).
  • Zasłonięcie treści może być mylące. (np. zmiana układu aplikacji może na chwilę wyświetlić filmy uczestników zdalnych na uchwyconym obszarze).

Interfejs API Element Capture rozwiązuje wszystkie te problemy, ponieważ pozwala na ukierunkowanie na element, który chcesz udostępnić.

Zrzut ekranu pokazujący element docelowy bez widocznej listy rozwijanej
François nie widzi listy z Elad.

Jak korzystać z Element Capture?

captureTarget to element na stronie, który zawiera treści, które użytkownik chce uchwycić. Chcesz, aby aplikacja internetowa do rozmów wideo rejestrowała captureTarget i udostępniała ją uczestnikom zdalnym. W ten sposób uzyskujesz RestrictionTargetcaptureTarget. Po ograniczeniu ścieżki wideo za pomocą tego RestrictionTarget ramki na tej ścieżce wideo składają się teraz tylko z pikseli, które są częścią elementu captureTarget i jego bezpośrednich potomków w DOM.

Jeśli captureTarget zmienia rozmiar, kształt lub położenie, ścieżka wideo podąża za nim, nie wymagając żadnych dodatkowych danych z żadnej z aplikacji internetowych. Zasłonięcie treści, które pojawiają się, znikają lub się przemieszczają, również nie wymaga specjalnego traktowania.

Ponownie wykonaj te czynności:

Najpierw zezwól użytkownikowi na przechwycenie 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 dowolnym elementem jako argumentem.

// 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, podając jako dane wejściowe funkcję RestrictionTarget. Gdy ostatnie obietnice zostaną spełnione, wszystkie kolejne ramki zostaną 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 RestrictionTarget.fromElement() jest obsługiwane, użyj:

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

Wyprowadzenie obiektu RestrictionTarget

Zwróć uwagę na element o nazwie captureTarget. Aby uzyskać z niego wartość RestrictionTarget, wywołaj funkcję RestrictionTarget.fromElement(captureTarget). W przypadku powodzenia zwrócona obietnica zostanie rozwiązana za pomocą nowego obiektu RestrictionTarget. W przeciwnym razie zostanie odrzucony, jeśli wyemitujesz nieuzasadnione ilości obiektów RestrictionTarget.

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

W przeciwieństwie do obiektu Element obiekt RestrictionTarget można zserializować. Może on zostać przekazany do innego dokumentu za pomocą na przykład Window.postMessage().

Kierowanie ograniczone

Podczas przechwytywania karty ścieżka wideo ujawnia restrictTo(). Podczas rejestrowania bieżącej karty można wywołać funkcję restrictTo() z parametrami null lub dowolnym parametrem RestrictionTarget pochodzącym z elementu na bieżącej karcie.

Wywołania funkcji restrictTo(restrictionTarget) zmieniają ścieżkę wideo na uchwyt captureTarget, tak jakby była ona rysowana samodzielnie, niezależnie od reszty modelu DOM. Wszystkie potomki elementu captureTarget są też rejestrowane; elementy pokrewne do captureTarget są eliminowane z rejestrowania. W efekcie wszystkie klatki dostarczone na ścieżce wyglądają tak, jakby zostały przycięte do kontur captureTarget, a zasłonięte i zasłonięte treści są usuwane.

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

Wywołania restrictTo(null) przywracają ścieżkę do jej pierwotnego stanu.

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

Jeśli wywołanie metody restrictTo() zakończy się pomyślnie, zwrócona obietnica zostanie rozwiązana, gdy będzie można zagwarantować, że wszystkie kolejne klatki filmu będą ograniczone do captureTarget.

Jeśli nie uda się tego zrobić, obietnica zostanie odrzucona. Nieudane połączenie z numerem restrictTo() może być spowodowane jednym z tych powodów:

  • Jeśli restrictionTarget została wyemitowana na karcie innej niż ta, na której odbywało się nagrywanie. (za pomocą przycisku „Udostępnij tę kartę” użytkownicy mogą w dowolnym momencie zmienić kartę, która ma być przechwycona).
  • 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 własnym nagraniem.
  • Jeśli element, z którego pochodzi restrictionTarget, nie kwalifikuje się do ograniczenia.

Wskazówki dotyczące samodzielnego rejestrowania

Gdy aplikacja wywołuje getDisplayMedia(), a użytkownik zdecyduje się na przechwycenie własnej karty aplikacji, nazywamy to „samoprzechwyceniem”.

Metoda restrictTo() jest dostępna na dowolnym ścieżce wideo z przechwytywaniem karty, a nie tylko w przypadku przechwytywania obrazu z kamery. Element Capture jest obecnie dostępny tylko do samodzielnego nagrywania. Dlatego przed próbą zablokowania utworu należy sprawdzić, czy użytkownik wybrał bieżącą kartę. Można to zrobić za pomocą funkcji chwytania uchwytu. Można też poprosić przeglądarkę o zachęcenie użytkownika do samodzielnego wykonania zdjęcia za pomocą preferCurrentTab.

Przejrzystość

Ramki wideo, które aplikacja przesyła do getDisplayMedia(), nie zawierają kanału alfa. Jeśli aplikacja ustawia cel przechwytywania z częściowo przezroczystym kanałem alfa, usunięcie tego kanału może mieć pewne konsekwencje:

  • Kolory mogą się zmienić. Częściowo przezroczyste elementy docelowe narysowane na jasnym tle mogą wydawać się ciemniejsze, gdy usuniesz kanał alfa, a te narysowane na ciemnym tle mogą wydawać się jaśniejsze.
  • Kolory, które były niewidoczne lub niewyczuwalne dla użytkownika, gdy kanał alfa był ustawiony na maksimum, będą widoczne po usunięciu tego kanału. Może to na przykład prowadzić do nieoczekiwanych czarnych obszarów na zarejestrowanych klatkach, jeśli przezroczyste sekcje mają kod RGBA rgba(0, 0, 0, 0).
Zrzut ekranu z wynikiem przezroczystego celu przechwytywania o nieprostokątnym kształcie.
Przekaz wideo docelowego z przezroczystym uchwytem niebędącym prostokątem (po prawej) to czarny prostokąt na tle, który zawiera nieprzezroczysty niebieski okrąg.

Niekwalifikujące się cele przechwytywania

W każdej chwili możesz zacząć ograniczać ścieżkę do dowolnego prawidłowego celu przechwytywania. Jednak w pewnych warunkach nie będą one tworzone, np. gdy element lub jego przodek ma wartość display:none. Ogólnie chodzi o to, że ograniczenie dotyczy tylko elementu, który składa się z jednego spójnego, dwuwymiarowego prostokątnego obszaru, którego piksele można logicznie określić niezależnie od elementów nadrzędnych lub siostrzanych.

Aby element mógł być objęty ograniczeniem, musi mieć własny kontekst nakładania się. Aby to zrobić, możesz ustawić właściwość CSS isolation 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. gdy aplikacja zmieni właściwości CSS. Aplikacja musi używać odpowiednich celów przechwytywania i nie zmieniać ich właściwości w nieoczekiwany sposób. Jeśli element docelowy nie spełnia kryteriów, nowe klatki nie będą emitowane na ścieżce, dopóki element docelowy nie będzie ponownie spełniał kryteriów ograniczenia.

Włączanie Element Capture

Interfejs Element Capture API jest dostępny w Chrome na komputerach za pomocą flagi Element Capture i można go włączyć na stronie chrome://flags/#element-capture.

Ta funkcja wchodzi w ramach próby wersji źródłowej w Chrome 121 na komputery, co pozwala deweloperom włączyć ją dla odwiedzających ich witryny, aby zbierać dane od rzeczywistych użytkowników. Więcej informacji o testach pochodzenia znajdziesz w artykule Pierwsze kroki z testami pochodzenia.

Bezpieczeństwo i prywatność

Aby dowiedzieć się więcej o kosztach związanych z bezpieczeństwem, przeczytaj sekcję Uwzględnianie prywatności i zabezpieczeń w specyfikacji Element Capture.

Przeglądarka Chrome rysuje niebieską ramkę wokół krawędzi przechwyconych kart.

Prezentacja

Możesz wypróbować Element Capture, uruchamiając demo na Glitch. Pamiętaj, aby sprawdzić kod źródłowy.

Prześlij opinię

Zespół Chrome i społeczność zajmująca się standardami internetowymi chce poznać Twoje wrażenia z korzystania z Element Capture.

Opowiedz nam o projektowaniu

Czy coś w funkcji Region Capture nie działa zgodnie z oczekiwaniami? A może brakuje metod lub właściwości, których potrzebujesz do wdrożenia swojego pomysłu? Masz pytania lub uwagi dotyczące modelu zabezpieczeń?

  • Zgłoś problem ze specyfikacją w repozytorium GitHub lub podziel się opinią na temat istniejącego problemu.

Problem z implementacją?

Czy znalazłeś/znalazłaś błąd w implementacji Chrome? 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 odtwarzania problemu. Glitch to świetne narzędzie do szybkiego i łatwego udostępniania informacji o powtarzających się problemach.

Poświadczenia

Zdjęcie: Paul Skorupskas z Unsplash