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é utilizzare Element Capture?

Considerare i requisiti di un'applicazione per videoconferenze può aiutarti a capire dove Element Capture è utile. Se hai un'applicazione di videoconferenza 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 remoti.

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

Se chiami getDisplayMedia() e lasci che sia l'utente a scegliere la scheda corrente, verrà trasmessa l'intera scheda corrente. con ogni probabilità il video verrà ritrasmesso alle persone. Puoi ritagliarlo utilizzando Acquisizione regione.

Tuttavia, cosa succede se il presentatore interagisce con l'applicazione di videoconferenza e alcuni contenuti, ad esempio un elenco a discesa, vengono sovrapposti ai contenuti che devono essere acquisiti?

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

La funzionalità di acquisizione della regione non ti aiuterà. 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 François.

Il fatto che la funzionalità di acquisizione di regioni acquisisca parti di elementi in questo modo (noto come contenuti che coprono) crea diversi problemi:

  • Occultamento dei contenuti potrebbe ostacolare la visualizzazione dei contenuti che l'utente intendeva condividere.
  • I contenuti coperti potrebbero essere privati (ad esempio le notifiche della chat).
  • L'occultamento dei contenuti potrebbe creare confusione. Ad esempio, un nuovo layout dell'applicazione potrebbe mostrare brevemente i video dei partecipanti remoti sul 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 faccio a utilizzare Element Capture?

captureTarget è un elemento della pagina che include i contenuti che l'utente vuole acquisire. Vuoi che l'app web di videoconferenza acquisisca captureTarget e la condivida con i partecipanti remoti. Quindi derivi un RestrictionTarget da captureTarget. Dopo aver limitato la traccia video utilizzando questo RestrictionTarget, i frame di quella traccia video ora consistono solo dei pixel che fanno parte di captureTarget e dei suoi discendenti DOM diretti.

Se captureTarget cambia dimensioni, forma o posizione, la traccia video segue, senza richiedere alcun input aggiuntivo da parte di nessuna delle app web. Allo stesso modo, l'occultamento di contenuti che appaiono, scompaiono o si spostano non richiede un trattamento speciale.

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 saranno limitati.

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

// Enjoy! Transmit remotely.

Approfondimento

Rilevamento di funzionalità

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

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

Ricavare un RestrictionTarget

Concentrati sull'elemento denominato captureTarget. Per ricavare un RestrictionTarget, chiama RestrictionTarget.fromElement(captureTarget). Se l'operazione va a buon fine, 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. Ad esempio, può essere passato a un altro documento 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) trasformano 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. Di conseguenza, tutti i fotogrammi caricati sulla traccia vengono ritagliati in base ai contorni di captureTarget e tutti i contenuti che coprono e vengono coperti 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 di esito negativo, la promessa viene rifiutata. Una chiamata a restrictTo() non andrà a buon fine per uno dei seguenti motivi:

  • Se il token restrictionTarget è stato coniato 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 è stato derivato 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 acquisita autonomamente.
  • Se l'elemento da cui è stato dedotto restrictionTarget non è idoneo per le limitazioni.

Considerazioni sulla cattura autonoma

Quando un'app chiama getDisplayMedia() e l'utente sceglie di acquisire la scheda dell'app, si parla di "acquisizione autonoma".

Il metodo restrictTo() è esposto su qualsiasi traccia video di acquisizione di schede e non solo per l'acquisizione di sé. Tuttavia, per il momento l'acquisizione di elementi è abilitata solo per l'acquisizione automatica. È quindi consigliabile verificare se l'utente ha selezionato la scheda corrente prima di tentare di limitare il canale. Questo può essere ottenuto utilizzando Capture Handle. È anche possibile chiedere al browser di indurre l'utente a scattare un selfie utilizzando preferCurrentTab.

Trasparenza

I fotogrammi video acquisiti dall'app tramite getDisplayMedia() non includono un canale alpha. 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 disegnati 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.
Lo stream video target di acquisizione trasparente non rettangolare (a destra) è un rettangolo di sfondo nero contenente un cerchio blu opaco.

Target di acquisizione non idonei

È sempre possibile iniziare a limitare una traccia a qualsiasi target di acquisizione valido. Tuttavia, i frame non verranno prodotti in determinate condizioni, ad esempio se l'elemento o un suo antenato è display:none. Il principio generale è che la limitazione si applica solo a un elemento che comprende un'area rettangolare bidimensionale singola e coesa, i cui pixel possono essere determinati logicamente indipendentemente da eventuali elementi principali o fratelli.

Un aspetto importante per garantire che l'elemento sia idoneo alla limitazione è che deve formare il proprio contesto di accodamento. Per assicurarti che ciò avvenga, puoi specificare la proprietà CSS isolation 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, ad esempio se l'app modifica le sue proprietà CSS. Spetta all'app utilizzare target di acquisizione ragionevoli ed evitare di modificarne le proprietà in modo imprevisto. Se l'elemento target non è più idoneo, i nuovi frame non verranno semplicemente emessi nel canale finché l'elemento target non sarà nuovamente idoneo alla limitazione.

Attivazione di Acquisizione elementi

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

Questa funzionalità è inclusa anche in una prova dell'origine da Chrome 121 su computer, che consente agli sviluppatori di attivarla per i visitatori dei loro siti al fine di raccogliere dati da utenti reali. Consulta la guida introduttiva alle prove dell'origine per saperne di più 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 provare Element Capture 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 in merito a Acquisizione regione che non funziona come previsto? Oppure mancano metodi o proprietà necessari per implementare la tua idea? Hai una domanda o un commento sul modello di sicurezza?

  • Invia una segnalazione relativa alle specifiche nel repository GitHub o aggiungi il tuo parere a una segnalazione 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 istruzioni semplici per la riproduzione. Glitch è ideale per condividere riproduzioni rapide e semplici.

Riconoscimenti

Foto di Paul Skorupskas su Unsplash