Video des Nutzers aufzeichnen

Mat Scales

Viele Browser können jetzt auf die Video- und Audioeingabe des Nutzers zugreifen. Je nach Browser kann es sich jedoch um eine vollständig dynamische und Inline-Ansicht handeln oder die Funktion wird an eine andere App auf dem Gerät des Nutzers delegiert.

Am einfachsten ist es, den Nutzer nach einer vorab aufgezeichneten Datei zu fragen. Erstellen Sie dazu ein einfaches Dateieingabeelement und fügen Sie einen accept-Filter hinzu, der angibt, dass nur Videodateien zulässig sind, und ein capture-Attribut, das angibt, dass die Daten direkt von der Kamera abgerufen werden sollen.

<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. Dabei wird das Attribut capture ignoriert. In Safari auf iOS wird die Kamera-App geöffnet, sodass Sie ein Video aufnehmen und dann zurück an die Webseite senden können. Auf Android-Geräten kann der Nutzer auswählen, mit welcher App er das Video aufnehmen möchte, bevor es an die Webseite gesendet wird.

Viele Mobilgeräte haben mehrere Kameras. Wenn Sie eine Präferenz haben, können Sie das capture-Attribut auf user festlegen, wenn die Kamera auf den 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" />

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

Sobald der Nutzer die Aufzeichnung beendet hat und wieder auf der Website ist, müssen Sie irgendwie an die Dateidaten gelangen. Sie können schnell darauf zugreifen, indem Sie dem Eingabeelement ein onchange-Ereignis zuordnen und dann die files-Eigenschaft des Ereignisobjekts lesen.

<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 damit alles tun, was Sie möchten. Beispielsweise können Sie…

  • Sie können sie direkt an ein <video>-Element anhängen, damit sie abgespielt werden kann.
  • Sie laden sie auf das Gerät des Nutzers herunter.
  • Sie können sie auf einen Server hochladen, indem Sie sie an einen XMLHttpRequest anhängen.
  • Frames in ein Canvas zeichnen und Filter darauf anwenden

Die Methode, über ein Eingabeelement auf Videodaten zuzugreifen, ist zwar weit verbreitet, aber die am wenigsten attraktive Option. Wir möchten unbedingt Zugriff auf die Kamera erhalten und Nutzern direkt auf der Seite eine gute Nutzererfahrung bieten.

Interaktiv auf die Kamera zugreifen

Moderne Browser können eine direkte Verbindung zur Kamera haben, sodass wir Funktionen entwickeln können, die vollständig in die Webseite eingebunden sind und bei denen der Nutzer den Browser nicht verlassen muss.

Zugriff auf die Kamera erhalten

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

Bei Erfolg gibt die API einen Stream zurück, der die Daten entweder von der Kamera oder vom Mikrofon enthält. Diese können dann entweder an ein <video>-Element oder an einen WebRTC-Stream angehängt oder mit der MediaRecorder API gespeichert werden.

Um Daten von der Kamera abzurufen, legen wir einfach video: true im Objekt „constraints“ 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 zuerst die verfügbaren Kameras auflisten.

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

Du kannst dann die gewünschte deviceId übergeben, wenn du getUserMedia aufrufst.

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

Das ist an sich nicht sehr nützlich. Wir können nur die Videodaten abrufen und wiedergeben.

Auf die Rohdaten der Kamera zugreifen

Wenn Sie auf die Rohvideodaten der Kamera zugreifen möchten, können Sie jeden Frame in ein <canvas> zeichnen und die Pixel direkt bearbeiten.

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

context.drawImage(myVideoElement, 0, 0);

Bei 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 eines abgespielten Videos verwendet. Wenn Sie mehrere Frames verarbeiten möchten, müssen Sie das Video jedes Mal neu auf dem Canvas zeichnen.

Weitere Informationen dazu findest du in unserem Artikel zum Anwenden von Echtzeiteffekten auf Bilder und Videos.

Daten von der Kamera speichern

Die Daten von der Kamera lassen sich am einfachsten mit der MediaRecorder API speichern.

Die MediaRecorder API nimmt den von getUserMedia erstellten Stream auf und speichert die Daten aus dem Stream nach und nach an Ihrem gewünschten 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 eine Blob umwandeln können, die dann auf unserem Webserver oder direkt im Speicher des Geräts des Nutzers gespeichert werden kann.

Erlaubnis zur verantwortungsvollen Verwendung der Kamera einholen

Wenn der Nutzer Ihrer Website noch nicht die Berechtigung zur Kameranutzung erteilt hat, wird er vom Browser aufgefordert, dies zu tun, sobald Sie getUserMedia aufrufen.

Nutzer mögen es nicht, wenn sie aufgefordert werden, auf leistungsstarke Geräte auf ihrem Computer zuzugreifen. Sie blockieren die Anfrage häufig oder ignorieren sie, wenn sie den Kontext der Aufforderung nicht verstehen. Es empfiehlt sich, den Zugriff auf die Kamera nur dann anzufordern, wenn er zum ersten Mal benötigt wird. Sobald der Nutzer den Zugriff gewährt hat, werden Sie nicht noch einmal gefragt. Wenn er den Zugriff jedoch ablehnt, können Sie nicht noch einmal auf den Zugriff zugreifen, um den Nutzer um Erlaubnis zu bitten.

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

Die getUserMedia API gibt Ihnen keine Auskunft darüber, ob Sie bereits Zugriff auf die Kamera haben. Das stellt Sie vor ein Problem: Wenn Sie eine ansprechende Benutzeroberfläche erstellen möchten, um Nutzer dazu zu bringen, Ihnen Zugriff auf die Kamera zu gewähren, müssen Sie um Zugriff auf die Kamera bitten.

In einigen Browsern kann das Problem mithilfe der Permission API behoben werden. Mit der navigator.permission API kannst du den Status der Zugriffsberechtigung für bestimmte APIs abfragen, ohne dass du noch einmal aufgefordert wirst.

Wenn Sie prüfen möchten, ob Sie Zugriff auf die Kamera des Nutzers haben, können Sie {name: 'camera'} in die Abfragemethode übergeben. Es wird dann Folgendes zurückgegeben:

  • granted: Der Nutzer hat Ihnen zuvor Zugriff auf die Kamera gewährt.
  • prompt: Der Nutzer hat dir keinen Zugriff gewährt und wird aufgefordert, wenn du getUserMedia aufrufst.
  • denied: Der Zugriff auf die Kamera wurde vom System oder vom Nutzer explizit blockiert und Sie können nicht darauf zugreifen.

Außerdem können Sie jetzt schnell prüfen, ob Sie Ihre Benutzeroberfläche an die Aktionen anpassen müssen, die der Nutzer ausführen muss.

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