Registrazione video dell'utente

Mat Scales

Molti browser ora hanno la possibilità di accedere all'input video e audio dell'utente. Tuttavia, a seconda del browser, potrebbe trattarsi di un'esperienza dinamica e in linea completa o potrebbe essere delegata a un'altra app sul dispositivo dell'utente.

Inizia in modo semplice e graduale

Il modo più semplice è chiedere all'utente un file preregistrato. A tal fine, crea un semplice elemento di input file e aggiungi un filtro accept che indichi che puoi accettare solo file video e un attributo capture che indichi che vuoi recuperarli direttamente dalla videocamera.

<input type="file" accept="video/*" capture />

Questo metodo funziona su tutte le piattaforme. Sul computer, all'utente verrà chiesto di caricare un file dal file system (ignorando l'attributo capture). In Safari su iOS si aprirà l'app Fotocamera, che ti consente di registrare il video e poi di inviarlo di nuovo alla pagina web. Su Android, l'utente potrà scegliere l'app con cui registrare il video prima di inviarlo di nuovo alla pagina web.

Molti dispositivi mobili hanno più di una videocamera. Se hai una preferenza, puoi impostare l'attributo capture su user, se vuoi che la videocamera sia rivolta verso l'utente, o environment se vuoi la videocamera rivolta verso l'esterno.

<input type="file" accept="video/*" capture="user" />
<input type="file" accept="video/*" capture="environment" />

Tieni presente che questo è solo un suggerimento: se il browser non supporta l'opzione o se il tipo di videocamera richiesto non è disponibile, il browser potrebbe sceglierne un'altra.

Una volta che l'utente ha terminato la registrazione ed è di nuovo nel sito web, devi in qualche modo recuperare i dati del file. Puoi accedere rapidamente collegando un evento onchange all'elemento di input e leggendo la proprietà files dell'oggetto evento.

<input type="file" accept="video/*" capture="camera" id="recorder" />
<video id="player" controls></video>
<script>
  var recorder = document.getElementById('recorder');
  var player = document.getElementById('player');

  recorder.addEventListener('change', function (e) {
    var file = e.target.files[0];
    // Do something with the video file.
    player.src = URL.createObjectURL(file);
  });
</script>

Una volta ottenuto l'accesso al file, puoi utilizzarlo come preferisci. Ad esempio, puoi:

  • Collegalo direttamente a un elemento <video> per riprodurlo
  • Scaricalo sul dispositivo dell'utente
  • Caricalo su un server collegandoti a un XMLHttpRequest
  • Disegna i frame in una tela e applica i filtri

Sebbene l'utilizzo del metodo dell'elemento input per accedere ai dati dei video sia molto diffuso, è l'opzione meno interessante. Vogliamo davvero accedere alla fotocamera e offrire un'esperienza piacevole direttamente nella pagina.

Accedere alla fotocamera in modo interattivo

I browser moderni possono avere un canale diretto con la fotocamera, il che ci consente di creare esperienze completamente integrate con la pagina web e l'utente non dovrà mai uscire dal browser.

Ottenere l'accesso alla fotocamera

Possiamo accedere direttamente alla fotocamera utilizzando un'API nella specifica WebRTC chiamata getUserMedia(). getUserMedia() chiederà all'utente di accedere ai microfoni e alle videocamere collegati.

Se l'operazione ha esito positivo, l'API restituirà un elemento Stream che conterrà i dati della videocamera o del microfono e potremo quindi collegarlo a un elemento <video>, collegarlo a uno stream WebRTC oppure salvarlo utilizzando l'API MediaRecorder.

Per ottenere i dati dalla fotocamera, impostiamo video: true nell'oggetto constraints che viene passato all'API getUserMedia()

<video id="player" controls></video>
<script>
  var player = document.getElementById('player');

  var handleSuccess = function (stream) {
    player.srcObject = stream;
  };

  navigator.mediaDevices
    .getUserMedia({audio: true, video: true})
    .then(handleSuccess);
</script>

Se vuoi scegliere una videocamera specifica, puoi prima elencare le videocamere disponibili.

navigator.mediaDevices.enumerateDevices().then((devices) => {
  devices = devices.filter((d) => d.kind === 'videoinput');
});

Puoi quindi passare l'ID dispositivo che vuoi utilizzare quando chiami getUserMedia.

navigator.mediaDevices.getUserMedia({
  audio: true,
  video: {
    deviceId: devices[0].deviceId,
  },
});

Da solo, non è molto utile. Possiamo solo prendere i dati del video e riprodurli.

Accedi ai dati non elaborati dalla fotocamera

Per accedere ai dati video non elaborati della videocamera, puoi disegnare ogni fotogramma in un <canvas> e manipulare direttamente i pixel.

Per una tela 2D, puoi utilizzare il metodo drawImage del contesto per disegnare il frame corrente di un elemento <video> nella tela.

context.drawImage(myVideoElement, 0, 0);

Con una tela WebGL puoi utilizzare un elemento <video> come origine per una texture.

gl.texImage2D(
  gl.TEXTURE_2D,
  0,
  gl.RGBA,
  gl.RGBA,
  gl.UNSIGNED_BYTE,
  myVideoElement,
);

Tieni presente che in entrambi i casi verrà utilizzato il fotogramma corrente di un video in riproduzione. Per elaborare più fotogrammi, devi ridisegnare ogni volta il video sulla tela.

Scopri di più in questo articolo sull'applicazione di effetti in tempo reale a immagini e video.

Salvare i dati della videocamera

Il modo più semplice per salvare i dati della videocamera è utilizzare l'API MediaRecorder.

L'API MediaRecorder acquisirà lo stream creato da getUserMedia e poi salverà progressivamente i dati dello stream nella destinazione che preferisci.

<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
  let shouldStop = false;
  let stopped = false;
  const downloadLink = document.getElementById('download');
  const stopButton = document.getElementById('stop');

  stopButton.addEventListener('click', function() {
    shouldStop = true;
  })

  var handleSuccess = function(stream) {
    const options = {mimeType: 'video/webm'};
    const recordedChunks = [];
    const mediaRecorder = new MediaRecorder(stream, options);

    mediaRecorder.addEventListener('dataavailable', function(e) {
      if (e.data.size > 0) {
        recordedChunks.push(e.data);
      }

      if(shouldStop === true && stopped === false) {
        mediaRecorder.stop();
        stopped = true;
      }
    });

    mediaRecorder.addEventListener('stop', function() {
      downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
      downloadLink.download = 'acetest.webm';
    });

    mediaRecorder.start();
  };

  navigator.mediaDevices.getUserMedia({ audio: true, video: true })
      .then(handleSuccess);
</script>

Nel nostro caso, salviamo i dati direttamente in un array che in un secondo momento possiamo trasformare in un Blob, che può essere utilizzato per salvare i dati sul nostro server web o direttamente nello spazio di archiviazione del dispositivo dell'utente.

Chiedere l'autorizzazione per utilizzare la videocamera in modo responsabile

Se l'utente non ha precedentemente concesso al tuo sito l'accesso alla fotocamera, nel momento in cui chiami getUserMedia, il browser gli chiederà di concedere al tuo sito l'autorizzazione ad accedere alla fotocamera.

Gli utenti detestano che venga chiesto loro di accedere a dispositivi potenti sulla propria macchina e spesso bloccano la richiesta o la ignorano se non comprendono il contesto in cui è stata creata. Come best practice, ti consigliamo di chiedere di accedere alla fotocamera solo la prima volta che serve. Una volta che l'utente ha concesso l'accesso, non gli verrà chiesto di nuovo, ma se rifiuta l'accesso, non potrai più accedere per chiedere all'utente l'autorizzazione.

Utilizza l'API Permissions per verificare se disponi già dell'accesso

L'API getUserMedia non ti fornisce alcuna informazione su se hai già accesso alla videocamera. Questo presenta un problema: per fornire un'interfaccia utente piacevole e convincere l'utente a concederti l'accesso alla fotocamera, devi chiedere l'accesso alla fotocamera.

Questo problema può essere risolto in alcuni browser utilizzando l'API Permission. L'API navigator.permission ti consente di eseguire query sullo stato della possibilità di accedere a API specifiche senza dover inviare una nuova richiesta.

Per verificare se hai accesso alla videocamera dell'utente, puoi passare {name: 'camera'} al metodo di query, che restituirà:

  • granted: l'utente ti ha già concesso l'accesso alla fotocamera.
  • prompt: l'utente non ti ha concesso l'accesso e gli verrà chiesto di farlo quando chiamerai getUserMedia.
  • denied: il sistema o l'utente ha bloccato esplicitamente l'accesso alla videocamera e non potrai accedervi.

Ora puoi verificare rapidamente se devi modificare l'interfaccia utente per adattarla alle azioni che l'utente deve intraprendere.

navigator.permissions.query({name: 'camera'}).then(function (result) {
  if (result.state == 'granted') {
  } else if (result.state == 'prompt') {
  } else if (result.state == 'denied') {
  }
  result.onchange = function () {};
});

Feedback