Acquisisci uno stream video da qualsiasi elemento

François Beaufort
François Beaufort

Con l'API Screen Capture, puoi acquisire l'intera scheda corrente. L'API Element Capture ti consente di acquisire e registrare un elemento HTML specifico. Trasforma l'acquisizione dell'intera scheda in uno specifico sottoalbero DOM, in modo da acquisire solo i discendenti diretti dell'elemento target. In altre parole, ritaglia e rimuove sia i contenuti oscuri che quelli occulti.

Perché usare Acquisizione di elementi?

Considerare i requisiti di un'applicazione per videoconferenze può aiutarti a capire dove Element Capture è utile. Se disponi di un'applicazione per videoconferenze che ti consente di incorporare applicazioni di terze parti in un iframe, a volte potresti voler acquisire l'iframe come video e trasmetterlo ai partecipanti da remoto.

Screenshot di una videochiamata in Chrome.
Elad utilizza un'applicazione di terze parti in una videochiamata con François.

Chiamare getDisplayMedia() e consentire all'utente di scegliere la scheda corrente trasmetterà l'intera scheda corrente. con ogni probabilità il video verrà ritrasmesso alle persone. Puoi ritagliare questo risultato utilizzando Acquisizione regione.

Tuttavia, cosa succede se il presentatore interagisce con l'applicazione di videoconferenza e alcuni contenuti, come un elenco a discesa, vengono visualizzati sopra i contenuti destinati all'acquisizione?

Screenshot di un elenco a discesa che include contenuti destinati all'acquisizione.
Sopra i contenuti destinati all'acquisizione viene visualizzato un elenco a discesa.

Acquisizione regione non ti aiuterebbe. Parte dell'elenco a discesa potrebbe essere visibile sugli schermi dei partecipanti da remoto.

Screenshot di un elenco a discesa acquisito.
L'elenco a discesa di Elad viene visualizzato sopra i contenuti ricevuti da Francesco.

Il fatto che l'acquisizione della regione acquisisca parti degli elementi in questo modo (noto come contenuti che ostruiscono) crea più problemi:

  • Occultamento dei contenuti potrebbe ostacolare la visualizzazione dei contenuti che l'utente intendeva condividere.
  • L'occultamento dei contenuti potrebbe essere privato (pensa alle notifiche della chat).
  • L'occultamento di contenuti può creare confusione. Ad esempio, un re-layout dell'applicazione potrebbe portare brevemente i video dei partecipanti da remoto al di sopra del target acquisito.

L'API Element Capture risolve tutti questi problemi, consentendoti di scegliere come target l'elemento che vuoi condividere.

Screenshot dell'elemento target senza un elenco a discesa visualizzato.
François non vede l'elenco a discesa di Elad.

Come si utilizza Element Capture?

captureTarget è un elemento della pagina che include i contenuti che l'utente vuole acquisire. Vuoi che l'app web per videoconferenze acquisisca captureTarget e la condivida con i partecipanti da remoto. Ricava quindi un valore RestrictionTarget da captureTarget. Dopo aver limitato la traccia video utilizzando questo RestrictionTarget, i frame in quella traccia video ora sono costituiti solo dai pixel che fanno parte di captureTarget e dei relativi discendenti diretti DOM.

Se captureTarget cambia dimensioni, forma o posizione, la traccia video segue le istruzioni, senza richiedere ulteriori input da nessuna delle app web. L'occultamento di contenuti che appaiono, scompaiono o si spostano non richiede interventi particolari.

Ripeti questi passaggi:

Per iniziare, consenti all'utente di acquisire la scheda corrente.

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

Definisci un RestrictionTarget chiamando RestrictionTarget.fromElement() con un elemento di tua scelta come input.

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

Quindi chiama restrictTo() sulla traccia video con RestrictionTarget come input. Una volta risolta l'ultima promessa, tutti i frame successivi verranno limitati.

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

// Enjoy! Transmit remotely.

Esegui un'analisi dettagliata

Rilevamento delle caratteristiche

Per verificare se RestrictionTarget.fromElement() è supportato, usa:

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

Ricavare un RestrictionTarget

Imposta lo stato attivo sull'elemento denominato captureTarget. Per ricavarne un RestrictionTarget, chiama RestrictionTarget.fromElement(captureTarget). In caso di esito positivo, la promessa restituita verrà risolta con un nuovo oggetto RestrictionTarget. In caso contrario, verrà rifiutato se hai generato un numero irragionevole di RestrictionTarget oggetti.

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

A differenza di un elemento, un oggetto RestrictionTarget è serializzabile. Può essere passato a un altro documento, ad esempio utilizzando Window.postMessage().

Con limitazioni

Quando acquisisci una scheda, la traccia video espone restrictTo(). Quando acquisisci la scheda corrente, è valido chiamare restrictTo() con null o qualsiasi RestrictionTarget derivato da un elemento all'interno della scheda corrente.

Le chiamate a restrictTo(restrictionTarget) mutano la traccia video in un'acquisizione di captureTarget, come se fosse disegnata da sola, indipendentemente dal resto del DOM. Vengono acquisiti anche tutti i discendenti di captureTarget; i fratelli di captureTarget vengono eliminati dall'acquisizione. Il risultato è che tutti i frame pubblicati sulla traccia sembrano ritagliati seguendo i contorni di captureTarget e tutti i contenuti ostruiti vengono rimossi.

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

Le chiamate a restrictTo(null) ripristinano lo stato originale della traccia.

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

Se la chiamata a restrictTo() ha esito positivo, la promessa restituita viene risolta quando è possibile garantire che tutti i fotogrammi video successivi saranno limitati a captureTarget.

In caso contrario, la promessa viene rifiutata. Una chiamata al numero restrictTo() non riuscita per uno dei seguenti motivi:

  • Se restrictionTarget è stato inserito in una scheda diversa da quella acquisita. Tieni presente che, utilizzando il pulsante "Condividi questa scheda", gli utenti possono modificare la scheda acquisita in qualsiasi momento.
  • Se restrictionTarget deriva da un elemento che non esiste più.
  • Se la traccia ha dei cloni. Vedi il problema 1509418.
  • Se la traccia corrente non è una traccia video con acquisizione automatica.
  • Se l'elemento da cui è stato derivato restrictionTarget non è idoneo per la limitazione.

Considerazioni sull'acquisizione automatica

Quando un'app chiama getDisplayMedia() e l'utente sceglie di acquisire la scheda dell'app, questa operazione viene chiamata "acquisizione personale".

Il metodo restrictTo() è esposto in tutte le tracce video relative all'acquisizione di schede, non solo per l'acquisizione automatica. Tuttavia, per il momento Acquisizione elemento è abilitata solo per l'acquisizione automatica. È quindi consigliabile verificare se l'utente ha selezionato la scheda corrente prima di tentare di limitare la traccia. A questo scopo, puoi utilizzare l'handle di acquisizione. È anche possibile chiedere al browser di incoraggiare l'utente a scattare l'acquisizione personale utilizzando preferCurrentTab.

Trasparenza

I frame video ricevuti dall'app tramite getDisplayMedia() non includono un canale alfa. Se un'app imposta un obiettivo di acquisizione parzialmente trasparente, la rimozione del canale alfa ha alcune possibili conseguenze:

  • I colori potrebbero cambiare. Gli elementi target parzialmente trasparenti disegnati su uno sfondo chiaro potrebbero apparire più scuri quando il canale alfa viene rimosso, mentre quelli su uno sfondo scuro potrebbero apparire più chiari.
  • I colori che erano invisibili o impercettibili per l'utente quando il canale alfa era impostato al massimo, appariranno dopo la rimozione del canale alfa. Ad esempio, questo potrebbe causare aree nere impreviste nei frame acquisiti, se le sezioni trasparenti avessero il codice RGBA rgba(0, 0, 0, 0).
Screenshot del risultato di un target di acquisizione trasparente non rettangolare.
Il video stream di destinazione dell'acquisizione trasparente non rettangolare (a destra) è un rettangolo con sfondo nero che contiene un cerchio blu opaco.

Target di acquisizione non idonei

È sempre possibile iniziare a limitare un canale a qualsiasi target di acquisizione valido. Tuttavia, i frame non verranno generati in determinate condizioni, ad esempio se l'elemento o un predecessore è display:none. La logica generale è che la restrizione si applica solo a un elemento che comprende una singola area rettangolare, coesa, bidimensionale, i cui pixel possono essere determinati logicamente isolando da qualsiasi elemento principale o di pari livello.

Una considerazione importante per garantire che l'elemento sia idoneo per la limitazione è che deve formare un proprio contesto in pila. Per farlo, puoi specificare la proprietà CSS di isolamento impostandola su isolate.

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

Tieni presente che l'elemento target può passare da idoneo a non idoneo per la limitazione in qualsiasi momento arbitrario, ad esempio se l'app cambia le proprietà CSS. Spetta all'app utilizzare target di acquisizione ragionevoli ed evitare di modificare inaspettatamente le relative proprietà. Se l'elemento target non è più idoneo, i nuovi frame non verranno emessi sulla traccia finché l'elemento target non diventa nuovamente idoneo alla limitazione.

Attivazione dell'acquisizione degli elementi

L'API Element Capture è disponibile in Chrome su computer desktop con il flag Element Capture e può essere attivata all'indirizzo chrome://flags/#element-capture.

Questa funzionalità sta anche entrendo in una prova dell'origine di Chrome 121 su computer, che consente agli sviluppatori di abilitare la funzionalità per consentire ai visitatori dei loro siti di raccogliere dati da utenti reali. Consulta la Guida introduttiva alle prove dell'origine per maggiori informazioni sulle prove dell'origine.

Sicurezza e privacy

Per comprendere i compromessi in termini di sicurezza, consulta la sezione Considerazioni su privacy e sicurezza della specifica di Element Capture.

Il browser Chrome traccia un bordo blu intorno ai bordi delle schede acquisite.

Demo

Puoi giocare con Acquisizione elemento eseguendo la demo su Glitch. Assicurati di controllare il codice sorgente.

Feedback

Il team di Chrome e la community degli standard web vogliono conoscere la tua esperienza con Element Capture.

Parlaci del design

C'è qualcosa di Region Capture che non funziona come ti aspettavi? Oppure mancano metodi o proprietà che ti servono per implementare la tua idea? Hai una domanda o un commento sul modello di sicurezza?

  • Segnala un problema relativo alle specifiche sul repository GitHub o aggiungi le tue opinioni a un problema esistente.

Problemi con l'implementazione?

Hai trovato un bug nell'implementazione di Chrome? Oppure l'implementazione è diversa dalle specifiche?

  • Segnala un bug all'indirizzo https://new.crbug.com. Assicurati di includere il maggior numero di dettagli possibile e di semplici istruzioni per la riproduzione. Glitch è la soluzione perfetta per condividere riproduzioni in modo facile e veloce.

Riconoscimenti

Foto di Paul Skorupskas su Unsplash