Video des Nutzers aufzeichnen

Mattenwaagen

Viele Browser haben jetzt die Möglichkeit, auf Video- und Audioeingaben des Nutzers zuzugreifen. Je nach Browser kann der Vorgang jedoch vollständig dynamisch und inline ausgeführt werden oder an eine andere App auf dem Gerät des Nutzers delegiert werden.

Einfach und schrittweise beginnen

Am einfachsten ist es, den Nutzer um eine vorab aufgezeichnete Datei zu bitten. Dazu erstellst du ein einfaches Dateieingabeelement und fügst einen accept-Filter hinzu, der angibt, dass wir nur Videodateien akzeptieren können, sowie ein capture-Attribut, das angibt, dass wir es direkt von der Kamera abrufen möchten.

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

Diese Methode funktioniert auf allen Plattformen. Auf dem Computer wird der Nutzer aufgefordert, eine Datei aus dem Dateisystem hochzuladen. Das Attribut capture wird dabei ignoriert. Unter iOS wird in Safari die Kamera-App geöffnet, über die du ein Video aufnehmen und dann zurück an die Webseite senden kannst. Auf Android-Geräten kann der Nutzer auswählen, in welcher App das Video aufgenommen werden soll, bevor es zur Webseite zurückgeleitet wird.

Viele Mobilgeräte haben mehr als eine Kamera. Falls Sie dies bevorzugen, können Sie das Attribut capture auf user setzen, wenn die Kamera zum Nutzer gerichtet sein soll, oder auf environment, wenn die Kamera nach außen gerichtet sein soll.

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

Dies ist nur ein Hinweis. Wenn der Browser die Option nicht unterstützt oder der gewünschte Kameratyp nicht verfügbar ist, wählt der Browser möglicherweise eine andere Kamera aus.

Sobald der Nutzer die Aufzeichnung abgeschlossen hat und wieder auf der Website ist, müssen Sie irgendwie auf die Dateidaten zugreifen. Zum schnellen Zugriff hängen Sie ein onchange-Ereignis an das Eingabeelement an und lesen dann die files-Eigenschaft des Ereignisobjekts.

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

Sobald Sie Zugriff auf die Datei haben, können Sie mit ihr alles tun, was Sie möchten. Beispielsweise können Sie…

  • Hängen Sie es direkt an ein <video>-Element an, damit Sie es abspielen können
  • Auf das Gerät des Nutzers herunterladen
  • Laden Sie sie auf einen Server hoch, indem Sie sie an eine XMLHttpRequest anhängen
  • Zeichnen Sie die Frames auf einen Canvas und wenden Sie Filter darauf an.

Die Eingabemethode für den Zugriff auf Videodaten ist zwar überall, aber die am wenigsten attraktivste Option. Wir möchten Zugang zur Kamera erhalten und direkt auf der Seite ein positives Erlebnis bieten.

Interaktiver Zugriff auf die Kamera

Moderne Browser können eine direkte Verbindung zur Kamera haben. Dies ermöglicht es uns, eine Website zu erstellen, die vollständig in die Webseite integriert ist, sodass der Nutzer den Browser niemals verlässt.

Zugriff auf die Kamera erhalten

Wir können über eine API in der WebRTC-Spezifikation namens getUserMedia() direkt auf die Kamera zugreifen. getUserMedia() fordert den Nutzer auf, Zugriff auf die verbundenen Mikrofone und Kameras zu erhalten.

Wenn der Vorgang erfolgreich war, gibt die API ein Stream-Element zurück, das die Daten von der Kamera oder dem Mikrofon enthält. Wir können es dann entweder an ein <video>-Element anhängen, an einen WebRTC-Stream anhängen oder mit der MediaRecorder API speichern.

Um Daten von der Kamera abzurufen, legen Sie einfach video: true im Einschränkungsobjekt fest, das an die getUserMedia() API übergeben wird.

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

Wenn Sie eine bestimmte Kamera auswählen möchten, können Sie zunächst die verfügbaren Kameras auflisten.

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

Sie können dann die beim Aufrufen von getUserMedia zu verwendende Geräte-ID übergeben.

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

Alleine ist das nicht besonders nützlich. Wir können nur die Videodaten nehmen und sie abspielen.

Auf die Rohdaten der Kamera zugreifen

Für den Zugriff auf die Videorohdaten von der Kamera können Sie jeden Frame in ein <canvas> zeichnen und die Pixel direkt bearbeiten.

Bei einem 2D-Canvas können Sie die drawImage-Methode des Kontexts verwenden, um den aktuellen Frame eines <video>-Elements auf dem Canvas zu zeichnen.

context.drawImage(myVideoElement, 0, 0);

Mit einem WebGL-Canvas können Sie ein <video>-Element als Quelle für eine Textur verwenden.

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

In beiden Fällen wird der aktuelle Frame des wiedergegebenen Videos verwendet. Wenn Sie mehrere Frames verarbeiten möchten, müssen Sie das Video jedes Mal neu auf den Canvas zeichnen.

Weitere Informationen finden Sie in unserem Artikel zum Anwenden von Echtzeiteffekten auf Bilder und Videos.

Daten von der Kamera speichern

Am einfachsten lassen sich die Daten von der Kamera mit der MediaRecorder API speichern.

Die MediaRecorder API nimmt den von getUserMedia erstellten Stream und speichert die Daten dann schrittweise an Ihrem bevorzugten Ziel.

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

In unserem Fall speichern wir die Daten direkt in einem Array, das wir später in ein Blob-Objekt umwandeln können, das dann auf unserem Webserver oder direkt im Speicher des Geräts des Nutzers gespeichert werden kann.

Berechtigung zur verantwortungsvollen Verwendung der Kamera einholen

Wenn der Nutzer Ihrer Website noch keinen Zugriff auf die Kamera gewährt hat, wird er beim Aufruf von getUserMedia vom Browser aufgefordert, Ihrer Website die Berechtigung für die Kamera zu gewähren.

Nutzer sind hasserfüllt, wenn sie aufgefordert werden, Zugriff auf leistungsstarke Geräte auf ihrem Computer zu erhalten, und sie blockieren die Anfrage häufig oder sie ignorieren sie, wenn sie den Kontext, für den die Aufforderung erstellt wurde, nicht verstehen. Es hat sich bewährt, den Zugriff auf die Kamera nur bei Bedarf anzufordern. Sobald der Nutzer den Zugriff gewährt hat, wird er nicht noch einmal gefragt, wenn er den Zugriff jedoch ablehnt, können Sie den Zugriff nicht noch einmal erhalten, um den Nutzer um Erlaubnis zu bitten.

Mit der Permissions API prüfen, ob Sie bereits Zugriff haben

Mit der getUserMedia API erfahren Sie nicht, ob Sie bereits Zugriff auf die Kamera haben. Dies stellt ein Problem dar: Um eine übersichtliche Benutzeroberfläche bereitzustellen, über die der Nutzer dir Zugriff auf die Kamera gewähren kann, musst du den Zugriff auf die Kamera anfordern.

Dieses Problem lässt sich in einigen Browsern mithilfe der Permission API beheben. Mit der navigator.permission API können Sie den Status der Möglichkeit für den Zugriff auf bestimmte APIs abfragen, ohne noch einmal nachfragen zu müssen.

Um herauszufinden, ob Sie Zugriff auf die Kamera des Nutzers haben, können Sie {name: 'camera'} an die Abfragemethode übergeben. Sie gibt dann eines der folgenden Ergebnisse zurück:

  • granted: der Nutzer hat dir zuvor Zugriff auf die Kamera gewährt
  • prompt: Der Nutzer hat Ihnen keinen Zugriff gewährt und wird gefragt, wenn Sie getUserMedia aufrufen.
  • denied: Das System oder der Nutzer hat den Zugriff auf die Kamera explizit blockiert und Sie können nicht darauf zugreifen.

Und Sie können jetzt schnell prüfen, ob Sie Ihre Benutzeroberfläche anpassen müssen, um den Aktionen des Nutzers Rechnung zu tragen.

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